83 lines
2.9 KiB
C#
83 lines
2.9 KiB
C#
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// 把 CaoCao Prefab 摆到当前场景广场中心,Y 取地表碰撞高度。不保存进 TownSquare.prefab。
|
|
/// </summary>
|
|
public static class PlaceCaoCao
|
|
{
|
|
const string PrefabPath = "Assets/Bundles/Characters/Human/CaoCao/CaoCao.prefab";
|
|
|
|
public static string Run()
|
|
{
|
|
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PrefabPath);
|
|
if (prefab == null)
|
|
return "missing " + PrefabPath;
|
|
|
|
var existing = GameObject.Find("CaoCao_Preview");
|
|
if (existing != null)
|
|
Object.DestroyImmediate(existing);
|
|
|
|
var go = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
|
|
go.name = "CaoCao_Preview";
|
|
|
|
Physics.SyncTransforms();
|
|
var y = SampleGroundY(0f, 0f, out var sitInfo);
|
|
go.transform.position = new Vector3(0f, y, 0f);
|
|
go.transform.rotation = Quaternion.identity;
|
|
|
|
var bounds = default(Bounds);
|
|
var has = false;
|
|
foreach (var r in go.GetComponentsInChildren<Renderer>())
|
|
{
|
|
if (!has) { bounds = r.bounds; has = true; }
|
|
else bounds.Encapsulate(r.bounds);
|
|
}
|
|
return $"pos={go.transform.position} h={(has ? bounds.size.y : 0f):F3} groundY={y:F3} {sitInfo}";
|
|
}
|
|
|
|
static float SampleGroundY(float x, float z, out string info)
|
|
{
|
|
var plaza = GameObject.Find("TownSquare");
|
|
var cols = plaza != null
|
|
? plaza.GetComponentsInChildren<MeshCollider>()
|
|
: Object.FindObjectsByType<MeshCollider>(FindObjectsSortMode.None);
|
|
var y = 0f;
|
|
var hitAny = false;
|
|
var best = float.MaxValue;
|
|
var meshName = "";
|
|
var boundsTop = 0f;
|
|
foreach (var col in cols)
|
|
{
|
|
if (col == null || !col.enabled) continue;
|
|
meshName = col.sharedMesh != null ? col.sharedMesh.name : "null";
|
|
boundsTop = col.bounds.max.y;
|
|
var origins = new[]
|
|
{
|
|
new Vector3(x, 80f, z),
|
|
new Vector3(col.bounds.center.x, col.bounds.max.y + 8f, col.bounds.center.z),
|
|
new Vector3(x + 0.35f, 80f, z + 0.35f),
|
|
};
|
|
foreach (var origin in origins)
|
|
{
|
|
var ray = new Ray(origin, Vector3.down);
|
|
if (!col.Raycast(ray, out var hit, 160f)) continue;
|
|
if (hit.distance >= best) continue;
|
|
best = hit.distance;
|
|
y = hit.point.y;
|
|
hitAny = true;
|
|
}
|
|
}
|
|
if (!hitAny && boundsTop > 0.01f)
|
|
{
|
|
y = boundsTop;
|
|
info = $"fallbackBoundsTop={y:F3} mesh={meshName} cols={cols.Length}";
|
|
return y;
|
|
}
|
|
info = $"plaza={(plaza != null ? plaza.name : "null")} cols={cols.Length} mesh={meshName} meshHit={hitAny}";
|
|
return hitAny ? y : 0f;
|
|
}
|
|
}
|
|
#endif
|