From 95cf531ccf056a65343675dd045c9d406eeee6a3 Mon Sep 17 00:00:00 2001 From: tddebart Date: Thu, 31 Mar 2022 21:56:54 +0200 Subject: [PATCH] improved chunk generation (now 1 chunk at a time) --- Assets/Scenes/World.unity | 170 +++++++++++++++--- Assets/_Scripts/Entity's/BaseEntity.cs | 8 + .../_Scripts/Entity's/Player/GameManager.cs | 7 +- Assets/_Scripts/Entity's/Player/Player.cs | 1 + Assets/_Scripts/F3MenuManger.cs | 7 +- Assets/_Scripts/NoiseVisualizer.cs | 7 +- Assets/_Scripts/World/ChunkData.cs | 15 +- Assets/_Scripts/World/Lighting.cs | 2 + Assets/_Scripts/World/World.cs | 8 +- Assets/_Scripts/World/WorldDataHelper.cs | 20 +-- Assets/_Scripts/World/World_Generation.cs | 73 ++++---- Assets/_Scripts/WorldGeneration/MyNoise.cs | 9 +- 12 files changed, 240 insertions(+), 87 deletions(-) diff --git a/Assets/Scenes/World.unity b/Assets/Scenes/World.unity index 8dec18f4..35f05ac5 100644 --- a/Assets/Scenes/World.unity +++ b/Assets/Scenes/World.unity @@ -1344,6 +1344,120 @@ RectTransform: m_AnchoredPosition: {x: 20, y: 0} m_SizeDelta: {x: 100, y: 100} m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &647558308 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 647558313} + - component: {fileID: 647558312} + - component: {fileID: 647558311} + - component: {fileID: 647558310} + - component: {fileID: 647558309} + m_Layer: 0 + m_Name: Plane (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &647558309 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 647558308} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6b46bf24d89a16b42914d86f13716d3a, type: 3} + m_Name: + m_EditorClassIdentifier: + settings: {fileID: 11400000, guid: 0e63362b226ea1b4aaf0207cff8a5abd, type: 2} + resolution: 250 + _renderer: {fileID: 647558311} +--- !u!64 &647558310 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 647558308} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 4 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &647558311 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 647558308} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 257 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &647558312 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 647558308} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &647558313 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 647558308} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 500, y: 100, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 13 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &739261251 GameObject: m_ObjectHideFlags: 0 @@ -3020,7 +3134,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e113280f9ab044168541f6fef84d3095, type: 3} m_Name: m_EditorClassIdentifier: - renderDistance: 2 + renderDistance: 1 chunkSize: 16 chunkHeight: 16 worldHeight: 96 @@ -3035,6 +3149,7 @@ MonoBehaviour: blockLightMultiplier: 1.18 dayColor: {r: 0.46666667, g: 0.8156863, b: 0.9137255, a: 1} nightColor: {r: 0.12591669, g: 0.22711694, b: 0.254717, a: 1} + disabled: 0 OnWorldCreated: m_PersistentCalls: m_Calls: @@ -3065,6 +3180,7 @@ MonoBehaviour: m_StringArgument: m_BoolArgument: 0 m_CallState: 2 + validateDone: 1 chunksToUpdate: [] --- !u!4 &1422854026 Transform: @@ -3444,7 +3560,7 @@ MonoBehaviour: playerChunkPosition: {x: 0, y: 0, z: 0} playerSpawned: 0 world: {fileID: 1422854025} - detectionTime: 1 + detectionTime: 0.01 --- !u!4 &1493713240 Transform: m_ObjectHideFlags: 0 @@ -3733,31 +3849,31 @@ MonoBehaviour: m_EditorClassIdentifier: biomeGenerator: {fileID: 975012410} biomeCenters: - - {x: 78, y: 0, z: 77} - - {x: -203, y: 0, z: -180} - - {x: -159, y: 0, z: -70} - - {x: -179, y: 0, z: 10} - - {x: -152, y: 0, z: 84} - - {x: -143, y: 0, z: 200} - - {x: -121, y: 0, z: -188} - - {x: -67, y: 0, z: -81} - - {x: -87, y: 0, z: -28} - - {x: -83, y: 0, z: 87} - - {x: -61, y: 0, z: 138} - - {x: -11, y: 0, z: -159} - - {x: 0, y: 0, z: -99} - - {x: -3, y: 0, z: -10} - - {x: -5, y: 0, z: 75} - - {x: -19, y: 0, z: 185} - - {x: 78, y: 0, z: -172} - - {x: 83, y: 0, z: -68} - - {x: 91, y: 0, z: -44} - - {x: 92, y: 0, z: 154} - - {x: 162, y: 0, z: -190} - - {x: 171, y: 0, z: -109} - - {x: 158, y: 0, z: 1} - - {x: 150, y: 0, z: 79} - - {x: 146, y: 0, z: 139} + - {x: 77, y: 0, z: 77} + - {x: -163, y: 0, z: -163} + - {x: -163, y: 0, z: -89} + - {x: -163, y: 0, z: -35} + - {x: -163, y: 0, z: 77} + - {x: -163, y: 0, z: 139} + - {x: -83, y: 0, z: -177} + - {x: -83, y: 0, z: -74} + - {x: -83, y: 0, z: -27} + - {x: -83, y: 0, z: 75} + - {x: -83, y: 0, z: 173} + - {x: -3, y: 0, z: -163} + - {x: -3, y: 0, z: -68} + - {x: -3, y: 0, z: 36} + - {x: -3, y: 0, z: 60} + - {x: -3, y: 0, z: 169} + - {x: 77, y: 0, z: -163} + - {x: 77, y: 0, z: -66} + - {x: 77, y: 0, z: 29} + - {x: 77, y: 0, z: 131} + - {x: 157, y: 0, z: -176} + - {x: 157, y: 0, z: -45} + - {x: 157, y: 0, z: -17} + - {x: 157, y: 0, z: 74} + - {x: 157, y: 0, z: 182} temperatureNoiseSettings: {fileID: 11400000, guid: 0e63362b226ea1b4aaf0207cff8a5abd, type: 2} domainWarping: {fileID: 1658937130} diff --git a/Assets/_Scripts/Entity's/BaseEntity.cs b/Assets/_Scripts/Entity's/BaseEntity.cs index 5a410437..4538d9ec 100644 --- a/Assets/_Scripts/Entity's/BaseEntity.cs +++ b/Assets/_Scripts/Entity's/BaseEntity.cs @@ -215,6 +215,14 @@ public void CalculateVelocity() velocity.y = CheckUpCollision(velocity.y); } + // If our feet are in a block we we shouldn't fall + if (world.GetBlock(transform.position).BlockData.generateCollider) + { + velocity.y = 0; + isGrounded = true; + verticalMomentum = 0; + } + } diff --git a/Assets/_Scripts/Entity's/Player/GameManager.cs b/Assets/_Scripts/Entity's/Player/GameManager.cs index 60fbbc61..f2324cfc 100644 --- a/Assets/_Scripts/Entity's/Player/GameManager.cs +++ b/Assets/_Scripts/Entity's/Player/GameManager.cs @@ -53,9 +53,14 @@ private void SetCurrentChunkCenter() currentChunkCenter.y = playerChunkPosition.y + world.chunkHeight / 2; } + public Vector3Int GetCurrentChunkCenter() + { + return WorldDataHelper.GetChunkPosition(world, Vector3Int.RoundToInt(localPlayer.transform.position)); + } + private IEnumerator CheckForChunkLoading() { - yield return new WaitForSeconds(detectionTime); + yield return null; if ( Mathf.Abs(currentChunkCenter.x - localPlayer.transform.position.x) > world.chunkSize / 2 || Mathf.Abs(currentChunkCenter.z - localPlayer.transform.position.z) > world.chunkSize / 2 || diff --git a/Assets/_Scripts/Entity's/Player/Player.cs b/Assets/_Scripts/Entity's/Player/Player.cs index fb92e228..d2cfd7d3 100644 --- a/Assets/_Scripts/Entity's/Player/Player.cs +++ b/Assets/_Scripts/Entity's/Player/Player.cs @@ -144,6 +144,7 @@ public Block TargetedBlock(float tReach,out Vector3Int lastGlobalPos) { var pos = cam.position + cam.forward * step; var block = world.GetBlock(pos); + if (block == null) return null; if (BlockDataManager.blockTypeDataDictionary[(int)block.type].generateCollider) { return block; diff --git a/Assets/_Scripts/F3MenuManger.cs b/Assets/_Scripts/F3MenuManger.cs index 3ccb565a..5ec84138 100644 --- a/Assets/_Scripts/F3MenuManger.cs +++ b/Assets/_Scripts/F3MenuManger.cs @@ -49,8 +49,11 @@ public void Update() CreateF3Text("Target", "Targeted Block: " + blockPos.x + ", " + blockPos.y + ", " + blockPos.z, false); CreateF3Text("BlockType", targetedBlock.type.ToString(), false); var frontBlock = World.Instance.GetBlock(frontGlobalBlockPos); - CreateF3Text("BlockLight", "Block light level: " + frontBlock.GetBlockLight(), false); - CreateF3Text("SkyLight", "Sky light level: " + frontBlock.GetSkyLight(), false); + if (frontBlock != null) + { + CreateF3Text("BlockLight", "Block light level: " + frontBlock.GetBlockLight(), false); + CreateF3Text("SkyLight", "Sky light level: " + frontBlock.GetSkyLight(), false); + } } else { diff --git a/Assets/_Scripts/NoiseVisualizer.cs b/Assets/_Scripts/NoiseVisualizer.cs index 69e78ed7..336409da 100644 --- a/Assets/_Scripts/NoiseVisualizer.cs +++ b/Assets/_Scripts/NoiseVisualizer.cs @@ -28,7 +28,12 @@ public void UpdateTexture() { for (var y = 0; y < resolution; y++) { - var color = Color.Lerp(Color.black, Color.white, MyNoise.Redistribution(MyNoise.OctavePerlin(x, y, settings), settings)); + var value = MyNoise.OctavePerlin(x, y, settings); + if (value > 0.9f) + { + var g = 0; + } + var color = new Color(value, value, value); pixs[y * resolution + x] = color; } } diff --git a/Assets/_Scripts/World/ChunkData.cs b/Assets/_Scripts/World/ChunkData.cs index 3bab8a23..fe47c72e 100644 --- a/Assets/_Scripts/World/ChunkData.cs +++ b/Assets/_Scripts/World/ChunkData.cs @@ -157,10 +157,17 @@ public MeshData GetMeshData() public void UpdateLight() { - Lighting.CalculateSkyLightRemove(this); - Lighting.CalculateSkyLightExtend(this); - - Lighting.CalculateLight(this); + try + { + Lighting.CalculateSkyLightRemove(this); + Lighting.CalculateSkyLightExtend(this); + + Lighting.CalculateLight(this); + } + catch (Exception e) + { + Debug.LogError(e); + } } public void CalculateBlockLight() diff --git a/Assets/_Scripts/World/Lighting.cs b/Assets/_Scripts/World/Lighting.cs index 03407595..9ad6511b 100644 --- a/Assets/_Scripts/World/Lighting.cs +++ b/Assets/_Scripts/World/Lighting.cs @@ -145,6 +145,8 @@ public static void BlockSunRay(ChunkData data, Block block) public static void RemoveSkyLight(ChunkData data, Block block, int oldLightValue) { + if (block == null) return; + if (oldLightValue > 0) { oldLightValue--; diff --git a/Assets/_Scripts/World/World.cs b/Assets/_Scripts/World/World.cs index bd72394f..7ea78d7b 100644 --- a/Assets/_Scripts/World/World.cs +++ b/Assets/_Scripts/World/World.cs @@ -40,7 +40,8 @@ public partial class World : MonoBehaviour [Space] public Color dayColor; public Color nightColor; - private bool disabled; + [HideInInspector] + public bool disabled; private CancellationTokenSource taskTokenSource = new CancellationTokenSource(); @@ -54,7 +55,7 @@ public partial class World : MonoBehaviour public Dictionary blocksToPlaceAfterGeneration = new Dictionary(); - private bool validateDone; + public bool validateDone; private void Awake() @@ -164,6 +165,7 @@ public void SetBlock(Vector3Int blockPos, BlockType blockType) { var chunkPos = WorldDataHelper.GetChunkPosition(this, blockPos); var chunk = WorldDataHelper.GetChunk(this, chunkPos); + if (chunk == null) return; chunk.ModifiedByPlayer = true; SetBlock(chunk, blockPos, blockType); } @@ -249,7 +251,7 @@ public Block GetBlock(Vector3Int globalPos) if (containerChunk == null) { - return null; + return BlockHelper.NOTHING; } var blockPos = containerChunk.GetLocalBlockCoords(new Vector3Int(globalPos.x, globalPos.y, globalPos.z)); diff --git a/Assets/_Scripts/World/WorldDataHelper.cs b/Assets/_Scripts/World/WorldDataHelper.cs index 2329b429..380f18b6 100644 --- a/Assets/_Scripts/World/WorldDataHelper.cs +++ b/Assets/_Scripts/World/WorldDataHelper.cs @@ -17,20 +17,20 @@ public static Vector3Int GetChunkPosition(World world, Vector3Int worldSpacePos) public static List GetChunkPositionsInRenderDistance(World world, Vector3Int playerPos) { - var startX = playerPos.x - world.renderDistance * world.chunkSize; - var startZ = playerPos.z - world.renderDistance * world.chunkSize; - var endX = playerPos.x + world.renderDistance * world.chunkSize; - var endZ = playerPos.z + world.renderDistance * world.chunkSize; + var startX = playerPos.x - Mathf.Min(world.renderDistance, World.Instance.IsWorldCreated ? world.renderDistance : 8) * world.chunkSize; + var startZ = playerPos.z - Mathf.Min(world.renderDistance, World.Instance.IsWorldCreated ? world.renderDistance : 8) * world.chunkSize; + var endX = playerPos.x + Mathf.Min(world.renderDistance, World.Instance.IsWorldCreated ? world.renderDistance : 8) * world.chunkSize; + var endZ = playerPos.z + Mathf.Min(world.renderDistance, World.Instance.IsWorldCreated ? world.renderDistance : 8) * world.chunkSize; return GetPositionsInRenderDistance(world,playerPos, startX, startZ, endX, endZ); } public static List GetDataPositionsInRenderDistance(World world, Vector3Int playerPos) { - var startX = playerPos.x - (world.renderDistance+1) * world.chunkSize; - var startZ = playerPos.z - (world.renderDistance+1) * world.chunkSize; - var endX = playerPos.x + (world.renderDistance+1) * world.chunkSize; - var endZ = playerPos.z + (world.renderDistance+1) * world.chunkSize; + var startX = playerPos.x - (Mathf.Min(world.renderDistance, World.Instance.IsWorldCreated ? world.renderDistance : 8)+1) * world.chunkSize; + var startZ = playerPos.z - (Mathf.Min(world.renderDistance, World.Instance.IsWorldCreated ? world.renderDistance : 8)+1) * world.chunkSize; + var endX = playerPos.x + (Mathf.Min(world.renderDistance, World.Instance.IsWorldCreated ? world.renderDistance : 8)+1) * world.chunkSize; + var endZ = playerPos.z + (Mathf.Min(world.renderDistance, World.Instance.IsWorldCreated ? world.renderDistance : 8)+1) * world.chunkSize; return GetPositionsInRenderDistance(world,playerPos, startX, startZ, endX, endZ); } @@ -68,7 +68,7 @@ public static HashSet GetPositionsToCreate(WorldData worldData, List { return allChunkPositionsNeeded .Where(pos => !worldData.chunkDict.ContainsKey(pos)) - .OrderBy(pos => Vector3.Distance(playerPos, pos)) + .OrderBy(pos => Vector3.Distance(playerPos, pos)).Take(World.Instance.IsWorldCreated ? World.Instance.chunksGenerationPerFrame : allChunkPositionsNeeded.Count) .ToHashSet(); } @@ -76,7 +76,7 @@ public static HashSet GetDataPositionsToCreate(WorldData worldData, { return allChunkDataPositionsNeeded .Where(pos => !worldData.chunkDataDict.ContainsKey(pos)) - .OrderBy(pos => Vector3.Distance(playerPos, pos)) + .OrderBy(pos => Vector3.Distance(playerPos, pos)).Take(World.Instance.IsWorldCreated ? 9 + World.Instance.chunksGenerationPerFrame*3 : allChunkDataPositionsNeeded.Count) .ToHashSet(); } diff --git a/Assets/_Scripts/World/World_Generation.cs b/Assets/_Scripts/World/World_Generation.cs index 860cf2d5..fb3dbdb4 100644 --- a/Assets/_Scripts/World/World_Generation.cs +++ b/Assets/_Scripts/World/World_Generation.cs @@ -15,8 +15,9 @@ public partial class World { public async void GenerateWorld() { + OnValidate(); IsWorldCreated = false; - + updateThread?.Abort(); updateThread = new Thread(UpdateLoop); updateThread.Start(); @@ -53,21 +54,7 @@ private async Task GenerateWorld(Vector3Int position) dataStopWatch.Start(); Profiler.BeginThreadProfiling("GenerateWorld", "GenerateData"); - - - // foreach(var pos in worldGenerationData.chunkDataPositionsToCreate) - // { - // if(taskTokenSource.IsCancellationRequested) - // { - // taskTokenSource.Token.ThrowIfCancellationRequested(); - // } - // - // var data = new ChunkData(chunkSize, chunkHeight, this, pos); - // var newData = terrainGenerator.GenerateChunkData(data, mapSeedOffset); - // dataDict.TryAdd(pos, newData); - // - // }; - + try { dataDict = await CalculateWorldChunkData(worldGenerationData.chunkDataPositionsToCreate); @@ -168,7 +155,7 @@ public UniTask> CreateMeshDataAsync(L { while (dataToRender.Count > 0) { - Parallel.For(0, chunksGenerationPerFrame, i => + Parallel.For(0, 1, i => { if(taskTokenSource.IsCancellationRequested) { @@ -235,29 +222,43 @@ private UniTask> CalculateWorldChunk { Profiler.BeginThreadProfiling("MyThreads","CalculateWorldChunkData"); var dataDict = new ConcurrentDictionary(); - while (chunkDataPositionsToCreate.Count > 0) + // while (chunkDataPositionsToCreate.Count > 0) + // { + // if(chunkDataPositionsToCreate.Count < chunksGenerationPerFrame) + // { + // chunksGenerationPerFrame = chunkDataPositionsToCreate.Count; + // } + // + // Parallel.For(0,chunksGenerationPerFrame, i => + // { + // if(taskTokenSource.IsCancellationRequested) + // { + // taskTokenSource.Token.ThrowIfCancellationRequested(); + // } + // + // var pos = chunkDataPositionsToCreate.First(); + // var data = new ChunkData(chunkSize, chunkHeight, this, pos); + // var newData = terrainGenerator.GenerateChunkData(data, mapSeedOffset); + // dataDict.TryAdd(pos, newData); + // + // chunkDataPositionsToCreate.Remove(pos); + // }); + // UniTask.NextFrame(); + // } + + Parallel.ForEach(chunkDataPositionsToCreate, pos => { - if(chunkDataPositionsToCreate.Count < chunksGenerationPerFrame) + if(taskTokenSource.IsCancellationRequested) { - chunksGenerationPerFrame = chunkDataPositionsToCreate.Count; + taskTokenSource.Token.ThrowIfCancellationRequested(); } - - Parallel.For(0,chunksGenerationPerFrame, i => - { - if(taskTokenSource.IsCancellationRequested) - { - taskTokenSource.Token.ThrowIfCancellationRequested(); - } - var pos = chunkDataPositionsToCreate.First(); - var data = new ChunkData(chunkSize, chunkHeight, this, pos); - var newData = terrainGenerator.GenerateChunkData(data, mapSeedOffset); - dataDict.TryAdd(pos, newData); - - chunkDataPositionsToCreate.Remove(pos); - }); - UniTask.NextFrame(); - } + var data = new ChunkData(chunkSize, chunkHeight, this, pos); + var newData = terrainGenerator.GenerateChunkData(data, mapSeedOffset); + dataDict.TryAdd(pos, newData); + + }); + // foreach(var pos in chunkDataPositionsToCreate) // { // if(taskTokenSource.IsCancellationRequested) diff --git a/Assets/_Scripts/WorldGeneration/MyNoise.cs b/Assets/_Scripts/WorldGeneration/MyNoise.cs index 8e4ff481..3410787e 100644 --- a/Assets/_Scripts/WorldGeneration/MyNoise.cs +++ b/Assets/_Scripts/WorldGeneration/MyNoise.cs @@ -28,21 +28,24 @@ public static float OctavePerlin(float x, float z, NoiseSettings settings) float total = 0; float frequency = 1; float amplitude = 1; - float amplitudeSum = 0; // Used for normalizing result to 0.0 - 1.0 range + float maxValue = 0; // Used for normalizing result to 0.0 - 1.0 range for (int i = 0; i < settings.octaves; i++) { total += Mathf.PerlinNoise((settings.offset.x + settings.worldSeedOffset.x + x) * frequency, (settings.offset.y + settings.worldSeedOffset.y + z) * frequency) * amplitude; - amplitudeSum += amplitude; + maxValue += amplitude; amplitude *= settings.persistence; frequency *= 2; } - var result = total / amplitudeSum; + var result = total / maxValue; if (result < 0) { result = 0; + } else if (result > 1) + { + result = 1; } noiseStopwatch.Stop();