Add prototype gameplay loop with character/battlefield assets and server game APIs.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user