Files
AIGame/AIClient/AgentScripts/BuildModelView.cs
T

148 lines
5.8 KiB
C#

#if UNITY_EDITOR
using System.IO;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.Rendering;
/// <summary>
/// 历史 LmGirl / LmCat 观察场景,保留旧 -Z 资产及相机方向;项目新资源采用 +Z 正面。
/// unity command run_script --file AgentScripts/BuildModelView.cs --entry BuildModelView.Run
/// </summary>
public static class BuildModelView
{
const string SceneDir = "Assets/Bundles/Scenes/Test/ModelView";
const string ScenePath = SceneDir + "/ModelView.unity";
const string GroundMatPath = SceneDir + "/Ground.mat";
const string GirlPath = "Assets/Bundles/Characters/Human/LmGirl/LmGirl.prefab";
const string CatPath = "Assets/Bundles/Characters/Animal/LmCat/LmCat.prefab";
public static string Run()
{
var girl = AssetDatabase.LoadAssetAtPath<GameObject>(GirlPath);
var cat = AssetDatabase.LoadAssetAtPath<GameObject>(CatPath);
if (girl == null)
return "missing " + GirlPath;
if (cat == null)
return "missing " + CatPath;
Directory.CreateDirectory(SceneDir);
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
var lightGo = new GameObject("Directional Light");
var light = lightGo.AddComponent<Light>();
light.type = LightType.Directional;
light.color = new Color(1f, 0.96f, 0.9f);
light.intensity = 1.2f;
light.shadows = LightShadows.Soft;
lightGo.transform.rotation = Quaternion.Euler(48f, -25f, 0f);
var groundMat = AssetDatabase.LoadAssetAtPath<Material>(GroundMatPath);
if (groundMat == null)
{
var shader = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard");
groundMat = new Material(shader);
groundMat.color = new Color(0.82f, 0.84f, 0.86f);
AssetDatabase.CreateAsset(groundMat, GroundMatPath);
}
var ground = GameObject.CreatePrimitive(PrimitiveType.Plane);
ground.name = "Ground";
ground.transform.localScale = new Vector3(14f, 1f, 14f);
ground.GetComponent<MeshRenderer>().sharedMaterial = groundMat;
var houses = PlaceHouses();
var girlGo = (GameObject)PrefabUtility.InstantiatePrefab(girl);
girlGo.name = "LmGirl";
girlGo.transform.SetPositionAndRotation(new Vector3(-1.6f, 0f, -36f), Quaternion.identity);
var catGo = (GameObject)PrefabUtility.InstantiatePrefab(cat);
catGo.name = "LmCat";
catGo.transform.SetPositionAndRotation(new Vector3(1.6f, 0f, -36f), Quaternion.identity);
var bounds = RendererBounds(girlGo);
bounds.Encapsulate(RendererBounds(catGo));
foreach (var house in houses)
bounds.Encapsulate(RendererBounds(house));
var camGo = new GameObject("Main Camera");
camGo.tag = "MainCamera";
var cam = camGo.AddComponent<Camera>();
cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = new Color(0.93f, 0.94f, 0.95f);
cam.fieldOfView = 32f;
cam.nearClipPlane = 0.1f;
cam.farClipPlane = 250f;
camGo.AddComponent<AudioListener>();
var center = bounds.center;
var halfFov = cam.fieldOfView * 0.5f * Mathf.Deg2Rad;
var distY = bounds.size.y / (2f * Mathf.Tan(halfFov) * 0.62f);
var aspect = 16f / 9f;
var halfFovX = Mathf.Atan(Mathf.Tan(halfFov) * aspect);
var distX = bounds.size.x / (2f * Mathf.Tan(halfFovX) * 0.72f);
var dist = Mathf.Max(distY, distX);
var camPos = center + new Vector3(0f, bounds.size.z * 0.36f, -dist * 1.08f);
camGo.transform.position = camPos;
camGo.transform.LookAt(center);
RenderSettings.ambientMode = AmbientMode.Trilight;
RenderSettings.ambientSkyColor = new Color(0.55f, 0.58f, 0.62f);
RenderSettings.ambientEquatorColor = new Color(0.42f, 0.42f, 0.42f);
RenderSettings.ambientGroundColor = new Color(0.28f, 0.28f, 0.28f);
EditorSceneManager.SaveScene(scene, ScenePath);
return $"scene={ScenePath} houses={houses.Count} girlH={Height(girlGo):F2} catH={Height(catGo):F2} cam={camPos}";
}
static System.Collections.Generic.List<GameObject> PlaceHouses()
{
var names = new[]
{
"cream_tile", "cream_red", "white_balcony", "brown_wood",
"cream_porch", "stone_balcony", "thatched", "white_blue",
"wood_fence", "shop_awning", "picket", "gate",
};
var placed = new System.Collections.Generic.List<GameObject>();
const float gap = 22f;
for (var i = 0; i < names.Length; i++)
{
var path = $"Assets/Bundles/Scenes/Test/LmHouses/{names[i]}/{names[i]}.prefab";
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (prefab == null)
continue;
var col = i % 4;
var row = i / 4;
var go = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
go.name = names[i];
go.transform.SetPositionAndRotation(
new Vector3((col - 1.5f) * gap, 0f, (row - 1f) * gap),
Quaternion.identity);
placed.Add(go);
}
return placed;
}
static Bounds RendererBounds(GameObject root)
{
Bounds bounds = default;
var has = false;
foreach (var r in root.GetComponentsInChildren<Renderer>())
{
if (!has)
{
bounds = r.bounds;
has = true;
}
else bounds.Encapsulate(r.bounds);
}
return has ? bounds : new Bounds(root.transform.position, Vector3.one);
}
static float Height(GameObject root)
{
return RendererBounds(root).size.y;
}
}
#endif