/// <summary> /// Randomly spawns in the map a given number of MapElements. /// </summary> /// <param name="objectToSpawn">The map element's prefab to spawn</param> /// <param name="seed">The seed to use to generate the perlin noise</param> /// <param name="spawningHeightRange">In which area of the map this is wanted to spawn. -1 means the bottom of the sea. 1 means the highest points in the world. 0 is the shoreline.</param> /// <param name="quantity">The amount of MapElements to spawn</param> /// <param name="parent">The transform that must be the parent of the spawned MapElement</param> /// <param name="requireNavMesh">Must the locations where the MapElements will spawn require a valid NavMeshSurface?</param> public List <MapElement> SpawnMapElementsRandomly(GameObject objectToSpawn, int seed, Vector2 spawningHeightRange, int quantity, Transform parent, bool requireNavMesh) { List <MapElement> spawnedMapElements = new List <MapElement>(); int totalCountToAvoidInfiniteLoop = 5000 * quantity; int spawnedCount = 0; RandomEssentials randomEssentials = new RandomEssentials(seed); while (spawnedCount < quantity) { totalCountToAvoidInfiniteLoop--; if (totalCountToAvoidInfiniteLoop < 0) { Debug.LogWarning($"Skipped the spawning of x{quantity-spawnedCount}/{{quantity}} {objectToSpawn.name}. No spawnable positions were found."); break; } Vector2 checkPosition = randomEssentials.GetRandomVector2(-mapManager.mapConfiguration.mapRadius, mapManager.mapConfiguration.mapRadius); if (IsSpawnablePositionOnTerrain(checkPosition, spawningHeightRange, requireNavMesh, out Vector3 spawnablePosition)) { spawnedMapElements.Add(SpawnMapElement(objectToSpawn, spawnablePosition, Quaternion.identity, parent)); spawnedCount++; } } return(spawnedMapElements); }
/// <summary> /// Spawns a group of MapElements in the map using a pseudo random perlin noise distribution. /// </summary> /// <param name="objectToSpawn">The map element's prefab to spawn</param> /// <param name="seed">The seed to use to generate the perlin noise</param> /// <param name="spawningHeightRange">In which area of the map this is wanted to spawn. -1 means the bottom of the sea. 1 means the highest points in the world. 0 is the shoreline.</param> /// <param name="probability">The probability of the object being spawned at any given spot (following the perlin noise distribution)</param> /// <param name="density">The density of the spawning. 1 meaning all the available spots where the probability says spawn should happen will be filled. 0 means none.</param> /// <param name="parent">The transform that must be the parent of the spawned MapElement</param> /// <param name="noiseMapSettings">The settings to be used for the perlin noise map</param> /// <param name="requireNavMesh">Must the locations where the MapElements will spawn require a valid NavMeshSurface?</param> public List <MapElement> SpawnMapElementsWithPerlinNoiseDistribution(GameObject objectToSpawn, int seed, Vector2 spawningHeightRange, float probability, float density, Transform parent, NoiseMapSettings noiseMapSettings, bool requireNavMesh) { List <MapElement> spawnedMapElements = new List <MapElement>(); RandomEssentials rng = new RandomEssentials(seed); float[,] noise = Noise.GenerateNoiseMap((int)mapManager.mapConfiguration.mapRadius * 2, (int)mapManager.mapConfiguration.mapRadius * 2, noiseMapSettings, Vector2.zero, seed); for (int x = 0; x < noise.GetLength(0); x++) { for (int y = 0; y < noise.GetLength(1); y++) { if (!(noise[x, y] >= 1 - probability)) { continue; } if (rng.GetRandomBool(1 - density)) { continue; } if (IsSpawnablePositionOnTerrain(new Vector2(x - mapManager.mapConfiguration.mapRadius, y - mapManager.mapConfiguration.mapRadius), spawningHeightRange, requireNavMesh, out Vector3 spawnablePosition)) { spawnedMapElements.Add(SpawnMapElement(objectToSpawn, spawnablePosition, Quaternion.identity, parent)); } } } return(spawnedMapElements); }
private void Update() { var i = UnityEngine.Random.insideUnitSphere; if (Input.GetKey(KeyCode.A)) { Vector2 pos = RandomEssentials.GetNew().GetPointInsideCircle(center, radius); Debug.Log($"INSTANTIATING AT {pos}"); Instantiate(spawned, pos, Quaternion.identity); } }
/// <summary> /// Generates a perlin noise map of a given width and height. /// </summary> /// <returns>An 2D array of floats containing the perlin noise map.</returns> public static float[,] GenerateNoiseMap(int width, int height, NoiseMapSettings noiseSettings, Vector2 sampleCenter, int seed) { float[,] noiseMap = new float[width, height]; RandomEssentials rng = new RandomEssentials(seed); Vector2[] octaveOffsets = new Vector2[noiseSettings.octaves]; float maxPossibleHeight = 0; float amplitude = 1f; float frequency = 1f; for (int i = 0; i < noiseSettings.octaves; i++) { float offsetX = rng.Next(-100000, +100000) + noiseSettings.offset.x + sampleCenter.x; float offsetY = rng.Next(-100000, +100000) - noiseSettings.offset.y - sampleCenter.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= noiseSettings.persistance; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = width / 2f; float halfHeight = height / 2f; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { amplitude = 1f; frequency = 1f; float noiseHeight = 0f; for (int i = 0; i < noiseSettings.octaves; i++) { float sampleX = ((x - halfWidth + octaveOffsets[i].x) / noiseSettings.scale * frequency); float sampleY = ((y - halfHeight + octaveOffsets[i].y) / noiseSettings.scale * frequency); float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; amplitude *= noiseSettings.persistance; frequency *= noiseSettings.lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap [x, y] = noiseHeight; if (noiseSettings.normalizeMode == NormalizeMode.Global) { float normalizedHeight = (noiseMap [x, y] + 1) / (maxPossibleHeight / 0.9f); noiseMap [x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } if (noiseSettings.normalizeMode == NormalizeMode.Local) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { noiseMap [x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap [x, y]); } } } return(noiseMap); }