Files
Net.Like.Xue.Tokyo/Packages-Local/Net.BITKit.Bounds.Unity/ReplacePrefabsWithTerrainTrees.cs

89 lines
3.0 KiB
C#
Raw Normal View History

2025-06-24 23:49:13 +08:00
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 中。");
}
}