Unity中实现炸弹爆炸地形凹陷变形的问题求助
解决Unity地形炸弹凹陷变形的代码问题
原代码存在的核心问题及修复方案
编译错误:泛型缺失
原代码Terrain terrain = GetComponent();缺少泛型参数,会直接编译失败,需修正为:Terrain terrain = GetComponent<Terrain>();坐标转换错误
直接使用世界坐标计算高度图索引是错误的,需要先将世界坐标转为地形本地坐标,再进行比例计算:Vector3 localPos = terrain.transform.InverseTransformPoint(pos);高度图索引越界
高度图的索引范围是0 ~ heightmapResolution-1,计算时需用heightmapResolution-1避免越界,同时通过Clamp限制合法范围:int posXInTerrain = Mathf.Clamp((int)((localPos.x / terrain.terrainData.size.x) * (heightmapRes - 1)), 0, heightmapRes - 1); int posZInTerrain = Mathf.Clamp((int)((localPos.z / terrain.terrainData.size.z) * (heightmapRes - 1)), 0, heightmapRes - 1);变形量单位不匹配
地形高度图的数值是0~1的相对比例(对应地形总高度),而非世界单位。需将世界空间的deformationAmount转换为相对比例:float relativeDeformation = deformationAmount / terrain.terrainData.size.y;遍历范围过大导致性能浪费
原代码遍历整个高度图,效率极低。应仅遍历变形半径覆盖的区域,减少不必要的计算:int startX = Mathf.Max(0, posXInTerrain - (int)deformationRadius); int endX = Mathf.Min(heightmapRes - 1, posXInTerrain + (int)deformationRadius); int startZ = Mathf.Max(0, posZInTerrain - (int)deformationRadius); int endZ = Mathf.Min(heightmapRes - 1, posZInTerrain + (int)deformationRadius);
修正后的完整代码
using UnityEngine; public class TerrainDeformer : MonoBehaviour { public void DeformTerrain(Vector3 pos, float deformationAmount, float deformationRadius) { Terrain terrain = GetComponent<Terrain>(); if (terrain == null) { Debug.LogError("当前物体上未挂载Terrain组件!"); return; } // 世界坐标转地形本地坐标 Vector3 localPos = terrain.transform.InverseTransformPoint(pos); int heightmapRes = terrain.terrainData.heightmapResolution; // 计算爆炸点在高度图中的合法索引 int posXInTerrain = Mathf.Clamp((int)((localPos.x / terrain.terrainData.size.x) * (heightmapRes - 1)), 0, heightmapRes - 1); int posZInTerrain = Mathf.Clamp((int)((localPos.z / terrain.terrainData.size.z) * (heightmapRes - 1)), 0, heightmapRes - 1); // 转换变形量为高度图相对比例 float relativeDeformation = deformationAmount / terrain.terrainData.size.y; // 确定需要修改的高度图区域 int startX = Mathf.Max(0, posXInTerrain - (int)deformationRadius); int endX = Mathf.Min(heightmapRes - 1, posXInTerrain + (int)deformationRadius); int startZ = Mathf.Max(0, posZInTerrain - (int)deformationRadius); int endZ = Mathf.Min(heightmapRes - 1, posZInTerrain + (int)deformationRadius); int width = endX - startX + 1; int depth = endZ - startZ + 1; // 获取目标区域的高度图数据 float[,] heights = terrain.terrainData.GetHeights(startX, startZ, width, depth); // 遍历生成凹陷 for (int x = 0; x < width; x++) { for (int z = 0; z < depth; z++) { float dist = Vector2.Distance(new Vector2(startX + x, startZ + z), new Vector2(posXInTerrain, posZInTerrain)); if (dist < deformationRadius) { // 平方衰减让凹陷边缘更自然,可调整幂次改变陡峭程度 float falloff = Mathf.Pow((deformationRadius - dist) / deformationRadius, 2); float delta = falloff * relativeDeformation; // 确保高度不低于0 heights[x, z] = Mathf.Max(0, heights[x, z] - delta); } } } // 将修改后的高度图写回地形 terrain.terrainData.SetHeights(startX, startZ, heights); } }
额外优化建议
- 若频繁触发地形变形,可使用
TerrainData.SetHeightsDelayLOD替代SetHeights,延迟LOD更新提升性能;或放入协程分帧处理,避免卡顿。 - 可调整衰减公式的幂次,比如
Mathf.Pow(falloff, 3)让凹陷更陡峭,Mathf.Sqrt(falloff)让边缘更平缓,适配不同爆炸效果需求。
内容的提问来源于stack exchange,提问作者SOOBATON
相关产品推荐
相关产品推荐

