#if UNITY_EDITOR using System.IO; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.Rendering; /// /// 历史 Explorer / LmCat 观察场景,保留旧 -Z 资产及相机方向;项目新资源采用 +Z 正面。 /// unity command run_script --file AgentScripts/BuildModelView.cs --entry BuildModelView.Run /// 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/Explorer/Explorer.prefab"; const string CatPath = "Assets/Bundles/Characters/Animal/LmCat/LmCat.prefab"; public static string Run() { var girl = AssetDatabase.LoadAssetAtPath(GirlPath); var cat = AssetDatabase.LoadAssetAtPath(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.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(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().sharedMaterial = groundMat; var houses = PlaceHouses(); var girlGo = (GameObject)PrefabUtility.InstantiatePrefab(girl); girlGo.name = "Explorer"; 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(); 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(); 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 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(); 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(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()) { 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