89 lines
3.0 KiB
C#
89 lines
3.0 KiB
C#
using UnityEngine;
|
||
using UnityEditor;
|
||
using System.Collections.Generic;
|
||
|
||
public class ReplacePrefabsWithTerrainTrees : EditorWindow
|
||
{
|
||
Terrain targetTerrain;
|
||
|
||
[MenuItem("Tools/Terrain/Replace Prefabs with Trees")]
|
||
static void ShowWindow()
|
||
{
|
||
GetWindow<ReplacePrefabsWithTerrainTrees>("Replace Prefabs");
|
||
}
|
||
|
||
void OnGUI()
|
||
{
|
||
EditorGUILayout.HelpBox("先在 Project 里选中你想替换的 Prefabs,然后点击按钮。", MessageType.Info);
|
||
|
||
targetTerrain = (Terrain)EditorGUILayout.ObjectField("目标 Terrain", targetTerrain, typeof(Terrain), true);
|
||
|
||
if (GUILayout.Button("替换选中 Prefab 实例为 Terrain 树"))
|
||
{
|
||
if (targetTerrain == null)
|
||
targetTerrain = Terrain.activeTerrain;
|
||
|
||
if (targetTerrain == null)
|
||
{
|
||
Debug.LogError("未指定 Terrain,也未检测到活动地形。");
|
||
return;
|
||
}
|
||
|
||
ReplacePrefabs();
|
||
}
|
||
}
|
||
|
||
void ReplacePrefabs()
|
||
{
|
||
Object[] selectedPrefabs = Selection.GetFiltered(typeof(GameObject), SelectionMode.Assets);
|
||
if (selectedPrefabs.Length == 0)
|
||
{
|
||
Debug.LogWarning("你需要在 Project 面板中选择 Prefab!");
|
||
return;
|
||
}
|
||
|
||
TerrainData terrainData = targetTerrain.terrainData;
|
||
Vector3 terrainPos = targetTerrain.transform.position;
|
||
|
||
List<TreeInstance> newTrees = new List<TreeInstance>(terrainData.treeInstances);
|
||
int count = 0;
|
||
|
||
foreach (GameObject prefab in selectedPrefabs)
|
||
{
|
||
GameObject[] instances = FindObjectsOfType<GameObject>();
|
||
foreach (GameObject obj in instances)
|
||
{
|
||
if (PrefabUtility.GetCorrespondingObjectFromSource(obj) == prefab)
|
||
{
|
||
Vector3 worldPos = obj.transform.position;
|
||
|
||
// 转换为 Terrain 本地坐标(归一化)
|
||
Vector3 normalizedPos = (worldPos - terrainPos);
|
||
normalizedPos.x /= terrainData.size.x;
|
||
normalizedPos.z /= terrainData.size.z;
|
||
normalizedPos.y = 0f;
|
||
|
||
// 选择一个随机树种(TreePrototype)
|
||
int prototypeIndex = Random.Range(0, terrainData.treePrototypes.Length);
|
||
TreeInstance tree = new TreeInstance
|
||
{
|
||
position = new Vector3(normalizedPos.x, 0, normalizedPos.z),
|
||
prototypeIndex = prototypeIndex,
|
||
heightScale = 1f,
|
||
widthScale = 1f,
|
||
color = Color.white,
|
||
lightmapColor = Color.white
|
||
};
|
||
|
||
newTrees.Add(tree);
|
||
Undo.DestroyObjectImmediate(obj);
|
||
count++;
|
||
}
|
||
}
|
||
}
|
||
|
||
terrainData.treeInstances = newTrees.ToArray();
|
||
Debug.Log($"✅ 替换完成,处理了 {count} 个实例。添加到 Terrain 的 Tree 中。");
|
||
}
|
||
}
|