Add TownSquare scene assets, resource production docs, and model pipeline updates.

Bring in plaza props/prefabs, ZhaoYun source GLB, design originals, and Hunyuan/Blender tooling used to produce them.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-09-28 14:28:46 +08:00
co-authored by Cursor
parent 5f8cb890c8
commit 9793d8581d
273 changed files with 10388 additions and 34 deletions
@@ -0,0 +1,64 @@
using UnityEngine;
namespace HotUpdate
{
/// <summary>
/// 用地表 MeshCollider 的碰撞高度作为放置 Y。原点在底面中点的物件直接用该值。
/// </summary>
public static class GroundSit
{
const float RayStartY = 80f;
const float RayLength = 160f;
public static float Height(Vector3 xz, Transform searchRoot = null, float fallback = 0f)
{
Physics.SyncTransforms();
var ray = new Ray(new Vector3(xz.x, RayStartY, xz.z), Vector3.down);
var bestDist = float.MaxValue;
var y = fallback;
var hitAny = false;
foreach (var col in Collect(searchRoot))
{
if (col == null || !col.enabled) continue;
if (!IsGroundCollider(col)) continue;
if (!col.Raycast(ray, out var hit, RayLength)) continue;
if (hit.distance >= bestDist) continue;
bestDist = hit.distance;
y = hit.point.y;
hitAny = true;
}
if (hitAny) return y;
foreach (var col in Collect(searchRoot))
{
if (col == null || !col.enabled) continue;
if (!col.Raycast(ray, out var hit, RayLength)) continue;
if (hit.distance >= bestDist) continue;
bestDist = hit.distance;
y = hit.point.y;
hitAny = true;
}
return hitAny ? y : fallback;
}
static MeshCollider[] Collect(Transform searchRoot)
{
if (searchRoot != null)
return searchRoot.GetComponentsInChildren<MeshCollider>();
return Object.FindObjectsByType<MeshCollider>(FindObjectsSortMode.None);
}
static bool IsGroundCollider(MeshCollider col)
{
for (var t = col.transform; t != null; t = t.parent)
{
if (t.name.IndexOf("ground", System.StringComparison.OrdinalIgnoreCase) >= 0)
return true;
}
return false;
}
}
}