Net.Like.Xue.Tokyo/Packages-Local/Net.BITKit.Bounds.Unity/ReplacePrefabsWithTerrainTr...

89 lines
3.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 中。");
}
}