using System.Linq; using System.Text; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; /// /// Nests the authored A-scheme battlefield under the live battle prefab. /// Gameplay actors stay on PrototypeArena; the primitive ground is turned off. /// public static class AttachGreenfield { const string Arena = "Assets/Bundles/Scenes/Prototype/PrototypeArena.prefab"; const string Battlefield = "Assets/Bundles/Scenes/Prototype/Battlefield/Battlefield_Greenfield.prefab"; public static string Build() { if (EditorApplication.isPlaying) throw new System.Exception("Attach the battlefield in Edit Mode."); var battlefield = AssetDatabase.LoadAssetAtPath(Battlefield); if (battlefield == null) throw new System.Exception("Missing " + Battlefield); var root = PrefabUtility.LoadPrefabContents(Arena); try { var previous = root.transform.Find("Greenfield"); if (previous != null) Object.DestroyImmediate(previous.gameObject); var instance = (GameObject)PrefabUtility.InstantiatePrefab(battlefield, root.transform); instance.name = "Greenfield"; instance.transform.SetSiblingIndex(0); foreach (var transform in instance.GetComponentsInChildren(true)) transform.gameObject.layer = 30; foreach (Transform child in root.transform) { if (child == instance.transform) continue; if (child.name == "Ground" || child.name == "Lane" || child.name == "LeftBorder" || child.name == "RightBorder" || child.name == "BattleLight") child.gameObject.SetActive(false); } PrefabUtility.SaveAsPrefabAsset(root, Arena); } finally { PrefabUtility.UnloadPrefabContents(root); } AssetDatabase.SaveAssets(); return Verify(); } public static string Verify() { var prefab = AssetDatabase.LoadAssetAtPath(Arena); if (prefab == null) throw new System.Exception("Missing arena prefab."); var scene = EditorSceneManager.NewPreviewScene(); var instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab, scene); try { var report = new StringBuilder(); var greenfield = instance.transform.Find("Greenfield"); if (greenfield == null || !greenfield.gameObject.activeSelf) throw new System.Exception("Greenfield is missing."); Require(greenfield, "Ground/GroundMesh"); Require(greenfield, "Routes/Lane0"); Require(greenfield, "Routes/Lane1"); Require(greenfield, "Routes/Lane2"); Require(greenfield, "Lighting/Sun"); if (greenfield.Find("Decorations/bridge") != null || greenfield.Find("Decorations/bridgeLeft") != null || greenfield.Find("Decorations/bridgeRight") != null) throw new System.Exception("Bridge is still placed in the battle arena."); var badLayer = greenfield.GetComponentsInChildren(true).FirstOrDefault(r => r.gameObject.layer != 30); if (badLayer != null) throw new System.Exception("Greenfield renderer not on layer 30: " + badLayer.name); foreach (string name in new[] { "Heroes", "Enemies", "Projectiles", "DeploymentMarkers", "SkillEffects", "BattleCamera", "DefenceLine" }) { var node = instance.transform.Find(name); if (node == null || !node.gameObject.activeSelf) throw new System.Exception(name + " must stay active."); } foreach (Transform child in instance.transform) { if (child.name == "Ground" || child.name == "Lane" || child.name == "LeftBorder" || child.name == "RightBorder" || child.name == "BattleLight") { if (child.gameObject.activeSelf) throw new System.Exception(child.name + " primitive is still active."); } } var mesh = greenfield.Find("Ground/GroundMesh").GetComponentInChildren(); if (mesh == null || mesh.sharedMaterial == null || mesh.sharedMaterial.shader.name != "Test/XPbr") throw new System.Exception("Greenfield ground shader is not Test/XPbr."); report.Append("PASS nested Greenfield; primitives hidden; gameplay nodes kept."); return report.ToString(); } finally { Object.DestroyImmediate(instance); EditorSceneManager.ClosePreviewScene(scene); } } static void Require(Transform root, string path) { var node = root.Find(path); if (node == null) throw new System.Exception("Missing " + path); } public static string FramePrefabStage() { var stage = PrefabStageUtility.OpenPrefab(Arena); var view = SceneView.lastActiveSceneView; if (view == null) throw new System.Exception("No Scene View."); view.LookAt(new Vector3(0, 0, 3.5f), Quaternion.Euler(38, -35, 0), 22f); view.orthographic = false; view.Repaint(); return stage.assetPath; } public static string ClosePrefabStage() { StageUtility.GoToMainStage(); return "Closed prefab stage"; } }