├── .gitattributes ├── 00_Start_Project.unitypackage ├── 01_End_Project.unitypackage ├── LICENSE ├── README.md └── Scripts ├── MapGenerator.cs ├── MapRenderer.cs ├── NoiseHelper.cs ├── NoiseSettings.cs ├── PerlinWorm.cs └── RiverGenerator.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /00_Start_Project.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SunnyValleyStudio/Perlin-Worms-Unity-tutorial/fdd62459725360bc61a25fcfc0c7516f202bfa24/00_Start_Project.unitypackage -------------------------------------------------------------------------------- /01_End_Project.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SunnyValleyStudio/Perlin-Worms-Unity-tutorial/fdd62459725360bc61a25fcfc0c7516f202bfa24/01_End_Project.unitypackage -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 SunnyValleyStudio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Perlin-Worms-Unity-tutorial 2 | [](https://youtu.be/B8qarIAuE6M) 3 | 4 |
Create procedural rivers in unity 2d top down example map using Perlin worms algorithm. 5 | 6 | 7 |
Attribution:
8 | Made by Sunny Valley Studio
9 |
--------------------------------------------------------------------------------
/Scripts/MapGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using UnityEngine;
6 | using UnityEngine.Tilemaps;
7 |
8 | public class MapGenerator : MonoBehaviour
9 | {
10 | public MapRenderer mapRenderer;
11 | public TileBase grassTile, waterTile, hillTile, snowTile, maxPosTile;
12 | public int mapSize;
13 | public NoiseSettings mapSettings;
14 | public float hillHeight = 0.5f, snowHeight = 0.6f, waterHeight = 0.4f;
15 | public float[,] noiseMap;
16 |
17 | private void Start()
18 | {
19 | noiseMap = new float[mapSize, mapSize];
20 | PrepareMap();
21 | }
22 |
23 | public void PrepareMap()
24 | {
25 | Debug.Log("Generating map");
26 | mapRenderer.ClearMap();
27 |
28 | for (int x = 0; x < mapSize; x++)
29 | {
30 | for (int y = 0; y < mapSize; y++)
31 | {
32 | var noise = NoiseHelper.SumNoise(x, y, mapSettings);
33 | noiseMap[x, y] = noise;
34 | if (noise > snowHeight)
35 | {
36 | mapRenderer.SetTileTo(x, y, snowTile);
37 | }else if(noise > hillHeight)
38 | {
39 | mapRenderer.SetTileTo(x, y, hillTile);
40 | }else if (noise < waterHeight)
41 | {
42 | mapRenderer.SetTileTo(x, y, waterTile);
43 | }
44 | else
45 | {
46 | mapRenderer.SetTileTo(x, y, grassTile);
47 | }
48 |
49 | }
50 | }
51 | }
52 |
53 | public void ShowMaximas()
54 | {
55 | var result = NoiseHelper.FindLocalMaxima(noiseMap);
56 | result = result.Where(pos => noiseMap[pos.x, pos.y] > snowHeight).OrderBy(pos => noiseMap[pos.x, pos.y]).Take(20).ToList();
57 | foreach (var item in result)
58 | {
59 | mapRenderer.SetTileTo(item.x, item.y, maxPosTile);
60 | }
61 | }
62 |
63 | public void ShowMinimas()
64 | {
65 | var result = NoiseHelper.FindLocalMinima(noiseMap);
66 | result = result.Where(pos => noiseMap[pos.x, pos.y] < waterHeight).OrderBy(pos => noiseMap[pos.x, pos.y]).Take(20).ToList();
67 | foreach (var item in result)
68 | {
69 | mapRenderer.SetTileTo(item.x, item.y, maxPosTile);
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/Scripts/MapRenderer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 | using UnityEngine.Tilemaps;
6 |
7 | public class MapRenderer : MonoBehaviour
8 | {
9 | public Tilemap map;
10 |
11 | public void ClearMap()
12 | {
13 | map.ClearAllTiles();
14 | }
15 |
16 | public void SetTileTo(int x, int y, TileBase tiletype)
17 | {
18 | map.SetTile(map.WorldToCell(new Vector3(x, y, 0)), tiletype);
19 | }
20 |
21 | public void SetTileTo(Vector3 pos, TileBase tiletype)
22 | {
23 | map.SetTile(map.WorldToCell(pos), tiletype);
24 | }
25 |
26 | public Vector3Int GetCellposition(Vector3 pos)
27 | {
28 | return map.WorldToCell(pos);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Scripts/NoiseHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | public static class NoiseHelper
7 | {
8 |
9 | public static float SumNoise(float x, float y, NoiseSettings noiseSettings)
10 | {
11 | float amplitude = 1;
12 | float frequency = noiseSettings.startFrequency;
13 | float noiseSum = 0;
14 | float amplitudeSum = 0;
15 | for (int i = 0; i < noiseSettings.octaves; i++)
16 | {
17 | noiseSum += amplitude * Mathf.PerlinNoise(x * frequency, y * frequency);
18 | amplitudeSum += amplitude;
19 | amplitude *= noiseSettings.persistance;
20 | frequency *= 2;
21 |
22 | }
23 | return noiseSum / amplitudeSum; // set range back to 0-1
24 |
25 | }
26 |
27 | public static float RangeMap(float inputValue, float inMin, float inMax, float outMin, float outMax)
28 | {
29 | return outMin + (inputValue - inMin) * (outMax - outMin) / (inMax - inMin);
30 | }
31 |
32 | public static List