问题
最近发现unity地形系统的一个bug,导入的场景地形数据关联错乱了,关联到别的场景的地形数据了,meta替换了也没用,不清楚它具体是怎么关联的。
看下面的案例:
可以看到正常这个场景的地形数据应该关联的是Scene_Empty_Terrain的数据,但是现在它关联到别的了。
那我们强制把正确的地形数据拖过去行不行,我们试下!
我们发现,强制拖过去会有一个警告,意思大概是地形数据和该地形的collider数据不匹配。而在Terrain的Inspector界面并没有找到任何的关联Terrain Data的地方。
解决办法
解决方法有两个:
切换到Debug模式,可以暴露出来Terrain Data参数,替换即可。
方法1
- 右键这里的小箭头,切换成Debug模式
- 我们能看到Terrain Data参数暴露出来了,将正确的Terrain Data拖过去替换即可
方法2
其实使用上面的方式已经可以解决了,第二种是想推荐下下面的地形拷贝类,本鱼蛋自己也做个备份,方便后续使用。这个地形深度拷贝也很有用,在一些场景比如想复制一份出来删除东西作为导航网格,可以这样操作。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class TerrainDataTransfer : EditorWindow {
TerrainData terrainDataFrom;
TerrainData terrainDataTo;
bool isJustCopy;
[MenuItem("Custom/TerrainDataTransfer")]
private static void ShowWindow() {
var window = GetWindow<TerrainDataTransfer>();
window.titleContent = new GUIContent("TerrainDataTransfer");
window.Show();
}
private void OnGUI() {
GUILayout.Label("原始地形数据");
terrainDataFrom = (TerrainData)EditorGUILayout.ObjectField(terrainDataFrom,typeof(TerrainData),true);
GUILayout.Label("目标地形数据");
terrainDataTo = (TerrainData)EditorGUILayout.ObjectField(terrainDataTo,typeof(TerrainData),true);
isJustCopy = GUILayout.Toggle(isJustCopy,"仅复制");
if(GUILayout.Button("复制terrain")){
TransferData(terrainDataFrom,terrainDataTo);
}
}
private void TransferData(TerrainData dataFrom, TerrainData dataTo){
//dataTo = new TerrainData(); 会导致重定向,从而找不到本尊
///复制参数
dataTo.heightmapResolution = dataFrom.heightmapResolution;
dataTo.size = dataFrom.size;
dataTo.wavingGrassAmount = dataFrom.wavingGrassAmount;
dataTo.wavingGrassSpeed = dataFrom.wavingGrassSpeed;
dataTo.wavingGrassStrength = dataFrom.wavingGrassStrength;
dataTo.wavingGrassTint = dataFrom.wavingGrassTint;
dataTo.detailPrototypes = dataFrom.detailPrototypes;
dataTo.treeInstances = dataFrom.treeInstances;
dataTo.treePrototypes = dataFrom.treePrototypes;
dataTo.alphamapResolution = dataFrom.alphamapResolution;
dataTo.baseMapResolution = dataFrom.baseMapResolution;
dataTo.splatPrototypes = dataFrom.splatPrototypes;
float[,] heights = dataFrom.GetHeights(0,0, dataFrom.heightmapResolution,dataFrom.heightmapResolution);
dataTo.SetHeights(0,0,heights);
float[,,] alphaMap = dataFrom.GetAlphamaps(0,0, dataFrom.alphamapWidth, dataFrom.alphamapHeight);
dataTo.SetAlphamaps(0,0, alphaMap);
///是否只是拷贝数据
if(isJustCopy)
return;
//在场景中创建地表
GameObject obj = Terrain.CreateTerrainGameObject(dataTo);
obj.name = "TerrainNew";
}
}
-
将上面的脚本导入到项目中
-
打开编辑器窗口Custom/TerrainDataTransfer
-
选择原始地形和目标地形文件,点击复制terrain按钮,即可自动在场景中创建出地形出来
-
如果勾选“仅复制”选项,那么只会把原始地形和目标地形数据同步一份过去
希望能帮到大家,喜欢本文章也点个赞加个关注,谢谢,我会长期分享自己的踩坑经验。