如何编写Editor脚本使Cube随Terrain画笔修改的高度同步调整Y轴位置
在Unity编辑器中让Cube随Terrain高度实时同步位置
核心实现逻辑
通过Unity编辑器的地形修改监听事件,实时获取Cube对应地形位置的高度,保持Cube与地形的初始相对Y轴偏移量,从而实现位置同步。
步骤与代码实现
- 创建Editor脚本
将脚本放在Assets/Editor目录下(必须,否则编辑器无法触发逻辑):
using UnityEditor; using UnityEngine; [InitializeOnLoad] public class TerrainCubeSync { public static GameObject targetCube; private static float _yOffset; static TerrainCubeSync() { // 初始化时记录Cube与地形的初始Y偏移 if (targetCube != null && Terrain.activeTerrain != null) { float terrainHeight = Terrain.activeTerrain.SampleHeight(targetCube.transform.position); _yOffset = targetCube.transform.position.y - terrainHeight; } // 监听地形高度修改事件 Terrain.onTerrainChanged += OnTerrainHeightUpdated; } private static void OnTerrainHeightUpdated(Terrain terrain, TerrainChangedFlags flags) { // 仅响应高度图修改事件 if ((flags & TerrainChangedFlags.Heightmap) == 0 || targetCube == null || terrain == null) return; Vector3 cubePos = targetCube.transform.position; // 获取当前地形对应位置的高度 float currentTerrainHeight = terrain.SampleHeight(cubePos); // 保持初始偏移量更新Cube位置 targetCube.transform.position = new Vector3(cubePos.x, currentTerrainHeight + _yOffset, cubePos.z); } // 编辑器菜单快速设置同步目标Cube [MenuItem("Tools/Set Sync Cube")] private static void AssignSyncCube() { if (Selection.activeGameObject == null || Selection.activeGameObject.GetComponent<MeshFilter>() == null) { Debug.LogWarning("请选中一个带有MeshFilter的GameObject作为同步目标"); return; } targetCube = Selection.activeGameObject; if (Terrain.activeTerrain != null) { float terrainHeight = Terrain.activeTerrain.SampleHeight(targetCube.transform.position); _yOffset = targetCube.transform.position.y - terrainHeight; } Debug.Log($"已设置同步Cube: {targetCube.name}"); } }
- 使用方法
- 选中场景中的Cube,点击顶部菜单栏
Tools > Set Sync Cube,完成同步目标绑定。 - 用地形画笔修改Terrain高度时,Cube会自动保持与地形的初始相对位置同步调整Y轴坐标。
关键细节说明
Terrain.SampleHeight:获取指定世界坐标对应的地形高度(基于地形本地坐标系,默认Terrain无缩放旋转时可直接使用世界坐标)。Terrain.onTerrainChanged:仅在地形被修改时触发,比编辑器每帧更新更高效,避免不必要的性能消耗。- 初始偏移量
_yOffset:确保Cube始终保持与地形的相对高度,无论初始位置是否贴合地形。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

