Crater generation script
unknown
csharp
3 years ago
3.8 kB
70
Indexable
/// <summary>
/// Generates a crater at a given world position, of a diameter X meters and a depth of X meters and some dirt all around (percentage of crater's full diameter)
/// </summary>
/// <param name="p_worldPos"></param>
/// <param name="p_holeDiameter"></param>
/// <param name="p_depth"></param>
void SpawnCrater(Vector3 p_worldPos, float p_holeDiameter, float p_depth, float p_dirtPercentageOnEdges)
{
float fullCraterSize = p_holeDiameter + (p_holeDiameter * p_dirtPercentageOnEdges); // Base hole diameter + dirt edges
// Setting the dirt height on the edges of the crater
float dirtHeight = p_holeDiameter > 1 ? 0.25f * p_depth : 0f; // Doing the edges of the crater only if the crater is big enough, otherwise looks pretty bad
// Converting real world size (meters) in heightmap size and taking into account resolution
fullCraterSize = (_heightMapResolution * fullCraterSize) / _terrainData.size.x;
// Converting the real world depth asked in scaled height of the terrain, so that 1m depth is always 1m depth, regardless of the terrain's Y scale / max height
p_depth /= _terrainData.size.y;
dirtHeight /= _terrainData.size.y;
// Converting world coordinates into terrain coordinates
int xBase = (int)(((p_worldPos.x - _terrainPos.x) / _terrainData.size.x) * _heightMapResolution);
int zBase = (int)(((p_worldPos.z - _terrainPos.z) / _terrainData.size.x) * _heightMapResolution);
// Clamping the terrainX and terrainZ values so we don't get errors
// Also moving the area to be centered on the real world point (center of our crater to be on the world point)
xBase = (int)Mathf.Clamp((float)xBase - fullCraterSize / 2f, 0, _heightMapResolution);
zBase = (int)Mathf.Clamp((float)zBase - fullCraterSize / 2f, 0, _heightMapResolution);
// Rounding the crater's size to the nearest integer because the terrain array only takes integers
int roundedCraterSize = (int)Mathf.Ceil(fullCraterSize);
float[,] heights = _terrainData.GetHeights(xBase, zBase, roundedCraterSize, roundedCraterSize); // Getting the heights values we want to modify
float radius = fullCraterSize / 2f; // Radius is half of the crater's diameter, useful to get some distance stuff
// Cache
float tempHeight;
float distanceToCenter;
float percDistanceToCenter;
for (int x = 0; x < roundedCraterSize; x++)
for (int z = 0; z < roundedCraterSize; z++)
{
distanceToCenter = Vector2.Distance(new Vector2(x, z), new Vector2(radius, radius));
if (distanceToCenter <= radius)
{
percDistanceToCenter = distanceToCenter / radius; // How far from the center this terrain node is
// Dirt edge
if (percDistanceToCenter >= 1f - p_dirtPercentageOnEdges) tempHeight = heights[x, z] + (p_depth * _craterDirtShape.Evaluate(1f - percDistanceToCenter)); // Smoothing
// Crater's hole
else tempHeight = heights[x, z] - (p_depth * _craterDepthShape.Evaluate(percDistanceToCenter)); // Smoothing
heights[x, z] = Mathf.Clamp(tempHeight, 0, 1); // Setting the new height
}
}
// Using SetHeightsDelayLOD doesn't help at all, doesn't change a thing
//_terrainData.SetHeightsDelayLOD(xBase, zBase, heights);
//_terrainData.SyncHeightmap();
_terrainData.SetHeights(xBase, zBase, heights);
}Editor is loading...