Add prototype gameplay loop with character/battlefield assets and server game APIs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-10-20 18:50:00 +08:00
co-authored by Cursor
parent 79369e4473
commit 6c64210331
833 changed files with 998079 additions and 1042 deletions
+82
View File
@@ -0,0 +1,82 @@
#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