Files
PIM_Laba4/Assets/Editor/Lab4SceneBuilder.cs
T
2026-05-25 23:53:50 +03:00

1148 lines
44 KiB
C#

using System.Collections.Generic;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Rendering;
using UnityEngine.UI;
public static class Lab4SceneBuilder
{
private const string ScenePath = "Assets/Scenes/Lab4_NarrativeExploration.unity";
private const string MaterialsFolder = "Assets/Materials/Lab4";
private sealed class BuilderAssets
{
public Font font;
public Material floorMaterial;
public Material wallMaterial;
public Material accentMaterial;
public Material woodMaterial;
public Material noteMaterial;
public Material highlightMaterial;
public Material npcMaterial;
public Material doorMaterial;
public Material decorMaterial;
}
private sealed class UIContext
{
public GameObject notePanel;
public Text noteTitleText;
public Text noteContentText;
public Button noteCloseButton;
public GameObject inventoryPanel;
public Transform inventoryContentRoot;
public Button inventoryButtonTemplate;
public Text inventoryEmptyText;
public Button inventoryCloseButton;
public GameObject dialoguePanel;
public Text dialogueNameText;
public Text dialogueBodyText;
public Transform dialogueOptionsRoot;
public Button dialogueOptionTemplate;
public Button dialogueCloseButton;
public GameObject promptPanel;
public Text promptText;
public Text questStatusText;
public GameObject questCompletePanel;
public Text questCompleteText;
public GameObject levelCompletePanel;
public Text levelCompleteText;
}
[MenuItem("Tools/Lab4/Create Full Test Scene")]
public static void CreateFullTestScene()
{
EnsureFolder("Assets/Materials");
EnsureFolder(MaterialsFolder);
EnsureFolder("Assets/Scenes");
EnsureTag("Player");
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
scene.name = "Lab4_NarrativeExploration";
var assets = CreateAssets();
ConfigureLightingAndEnvironment();
var root = new GameObject("Lab4_Root");
var environmentRoot = new GameObject("Environment");
environmentRoot.transform.SetParent(root.transform);
CreateDirectionalLight(root.transform);
CreateLevelGeometry(environmentRoot.transform, assets, out var exitDoor, out var exitTrigger);
CreateDecor(environmentRoot.transform, assets);
var ui = CreateUI(root.transform, assets);
CreateEventSystem(root.transform);
CreateGameSystems(root.transform, ui, exitDoor, exitTrigger);
CreatePlayer(root.transform);
CreateNotes(root.transform, assets);
CreateNpc(root.transform, assets);
EditorSceneManager.MarkSceneDirty(scene);
EditorSceneManager.SaveScene(scene, ScenePath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
var sceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(ScenePath);
if (sceneAsset != null)
{
EditorGUIUtility.PingObject(sceneAsset);
}
EditorUtility.DisplayDialog(
"Lab4 Scene Builder",
"Сцена Lab4_NarrativeExploration создана и сохранена в Assets/Scenes.",
"OK");
}
private static BuilderAssets CreateAssets()
{
return new BuilderAssets
{
font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf"),
floorMaterial = CreateOrUpdateMaterial($"{MaterialsFolder}/Floor.mat", new Color(0.34f, 0.38f, 0.42f), 0.05f),
wallMaterial = CreateOrUpdateMaterial($"{MaterialsFolder}/Wall.mat", new Color(0.75f, 0.71f, 0.62f), 0.12f),
accentMaterial = CreateOrUpdateMaterial($"{MaterialsFolder}/Accent.mat", new Color(0.22f, 0.47f, 0.49f), 0.15f),
woodMaterial = CreateOrUpdateMaterial($"{MaterialsFolder}/Wood.mat", new Color(0.44f, 0.29f, 0.18f), 0.18f),
noteMaterial = CreateOrUpdateMaterial($"{MaterialsFolder}/Note.mat", new Color(0.93f, 0.89f, 0.73f), 0.05f),
highlightMaterial = CreateOrUpdateMaterial($"{MaterialsFolder}/Highlight.mat", new Color(0.98f, 0.82f, 0.21f), 0.03f),
npcMaterial = CreateOrUpdateMaterial($"{MaterialsFolder}/NPC.mat", new Color(0.31f, 0.52f, 0.82f), 0.18f),
doorMaterial = CreateOrUpdateMaterial($"{MaterialsFolder}/Door.mat", new Color(0.58f, 0.17f, 0.16f), 0.2f),
decorMaterial = CreateOrUpdateMaterial($"{MaterialsFolder}/Decor.mat", new Color(0.52f, 0.56f, 0.35f), 0.08f)
};
}
private static void ConfigureLightingAndEnvironment()
{
RenderSettings.ambientMode = AmbientMode.Flat;
RenderSettings.ambientLight = new Color(0.62f, 0.65f, 0.7f);
RenderSettings.fog = true;
RenderSettings.fogColor = new Color(0.69f, 0.71f, 0.75f);
RenderSettings.fogDensity = 0.01f;
}
private static void CreateDirectionalLight(Transform parent)
{
var lightObject = new GameObject("Directional Light");
lightObject.transform.SetParent(parent);
lightObject.transform.rotation = Quaternion.Euler(50f, -30f, 0f);
var directionalLight = lightObject.AddComponent<Light>();
directionalLight.type = LightType.Directional;
directionalLight.intensity = 1.2f;
directionalLight.shadows = LightShadows.Soft;
}
private static void CreateLevelGeometry(Transform parent, BuilderAssets assets, out GameObject exitDoor, out GameObject exitTrigger)
{
CreatePlane("Floor", parent, Vector3.zero, new Vector3(3.2f, 1f, 3.2f), assets.floorMaterial);
CreateCube("NorthWall", parent, new Vector3(0f, 2f, 12f), new Vector3(24f, 4f, 0.5f), assets.wallMaterial);
CreateCube("SouthWall", parent, new Vector3(0f, 2f, -12f), new Vector3(24f, 4f, 0.5f), assets.wallMaterial);
CreateCube("WestWall", parent, new Vector3(-12f, 2f, 0f), new Vector3(0.5f, 4f, 24f), assets.wallMaterial);
CreateCube("EastWall", parent, new Vector3(12f, 2f, 0f), new Vector3(0.5f, 4f, 24f), assets.wallMaterial);
CreateCube("InnerWall_A1", parent, new Vector3(-4f, 2f, 8.5f), new Vector3(0.5f, 4f, 7f), assets.wallMaterial);
CreateCube("InnerWall_A2", parent, new Vector3(-4f, 2f, -6f), new Vector3(0.5f, 4f, 12f), assets.wallMaterial);
CreateCube("InnerWall_B1", parent, new Vector3(4f, 2f, 5f), new Vector3(0.5f, 4f, 14f), assets.wallMaterial);
CreateCube("InnerWall_B2", parent, new Vector3(4f, 2f, -10.5f), new Vector3(0.5f, 4f, 3f), assets.wallMaterial);
CreateCube("InnerWall_C1", parent, new Vector3(-7.5f, 2f, 0f), new Vector3(8f, 4f, 0.5f), assets.wallMaterial);
CreateCube("InnerWall_C2", parent, new Vector3(7.5f, 2f, 0f), new Vector3(7f, 4f, 0.5f), assets.wallMaterial);
CreateCube("InnerWall_D", parent, new Vector3(0f, 2f, 7f), new Vector3(11f, 4f, 0.5f), assets.wallMaterial);
CreateCube("AccentStrip_1", parent, new Vector3(-8f, 0.05f, 6f), new Vector3(6f, 0.1f, 4f), assets.accentMaterial);
CreateCube("AccentStrip_2", parent, new Vector3(7f, 0.05f, -6f), new Vector3(4f, 0.1f, 6f), assets.accentMaterial);
var exitRoot = new GameObject("Exit");
exitRoot.transform.SetParent(parent);
exitRoot.transform.position = new Vector3(11.5f, 0f, 6f);
CreateCube("ExitFrame_Left", exitRoot.transform, new Vector3(0f, 1.5f, -1.25f), new Vector3(0.5f, 3f, 0.5f), assets.woodMaterial);
CreateCube("ExitFrame_Right", exitRoot.transform, new Vector3(0f, 1.5f, 1.25f), new Vector3(0.5f, 3f, 0.5f), assets.woodMaterial);
CreateCube("ExitFrame_Top", exitRoot.transform, new Vector3(0f, 3.1f, 0f), new Vector3(0.5f, 0.35f, 3f), assets.woodMaterial);
exitDoor = CreateCube("ExitDoor", exitRoot.transform, new Vector3(0f, 1.5f, 0f), new Vector3(0.2f, 3f, 2.3f), assets.doorMaterial);
exitTrigger = new GameObject("ExitTrigger");
exitTrigger.transform.SetParent(exitRoot.transform);
exitTrigger.transform.localPosition = new Vector3(0.9f, 1.2f, 0f);
var triggerCollider = exitTrigger.AddComponent<BoxCollider>();
triggerCollider.isTrigger = true;
triggerCollider.size = new Vector3(2.2f, 2.4f, 2.6f);
exitTrigger.AddComponent<LevelExitTrigger>();
exitTrigger.SetActive(false);
}
private static void CreateDecor(Transform parent, BuilderAssets assets)
{
CreateTable(parent, new Vector3(-8f, 0f, 8f), assets.woodMaterial);
CreateTable(parent, new Vector3(-9f, 0f, -7f), assets.woodMaterial);
CreateTable(parent, new Vector3(0f, 0f, -7f), assets.woodMaterial);
CreateTable(parent, new Vector3(8f, 0f, 8f), assets.woodMaterial);
CreateCrate(parent, new Vector3(-8f, 0.5f, -2f), new Vector3(1.2f, 1.2f, 1.2f), assets.decorMaterial);
CreateCrate(parent, new Vector3(-6.3f, 0.4f, -2.3f), new Vector3(0.8f, 0.8f, 0.8f), assets.decorMaterial);
CreateCrate(parent, new Vector3(2.5f, 0.5f, -5f), new Vector3(1.2f, 1.2f, 1.2f), assets.decorMaterial);
CreateCrate(parent, new Vector3(3.7f, 1.1f, -4.3f), new Vector3(0.8f, 0.8f, 0.8f), assets.decorMaterial);
CreateCrate(parent, new Vector3(7f, 0.6f, 3f), new Vector3(1.3f, 1.3f, 1.3f), assets.decorMaterial);
CreateShelf(parent, new Vector3(8.5f, 0f, 9.8f), assets.woodMaterial, assets.decorMaterial);
CreateShelf(parent, new Vector3(-10.2f, 0f, 9.8f), assets.woodMaterial, assets.decorMaterial);
CreateBench(parent, new Vector3(1.5f, 0f, 9.2f), assets.woodMaterial);
CreateColumn(parent, new Vector3(-1f, 1.5f, 3f), assets.accentMaterial);
CreateColumn(parent, new Vector3(10f, 1.5f, -8f), assets.accentMaterial);
CreateSphere("MarkerOrb_1", parent, new Vector3(-10f, 0.8f, 4f), new Vector3(0.7f, 0.7f, 0.7f), assets.accentMaterial);
CreateSphere("MarkerOrb_2", parent, new Vector3(6f, 0.8f, -10f), new Vector3(0.7f, 0.7f, 0.7f), assets.npcMaterial);
}
private static UIContext CreateUI(Transform parent, BuilderAssets assets)
{
var context = new UIContext();
var canvasObject = new GameObject("Canvas");
canvasObject.transform.SetParent(parent);
var canvas = canvasObject.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
var scaler = canvasObject.AddComponent<CanvasScaler>();
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
scaler.referenceResolution = new Vector2(1920f, 1080f);
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
scaler.matchWidthOrHeight = 0.5f;
canvasObject.AddComponent<GraphicRaycaster>();
CreateControlHintPanel(canvasObject.transform, assets);
context.questStatusText = CreateQuestStatusPanel(canvasObject.transform, assets);
CreateInventoryPanel(canvasObject.transform, assets, context);
CreateNotePanel(canvasObject.transform, assets, context);
CreateDialoguePanel(canvasObject.transform, assets, context);
CreateInteractionPrompt(canvasObject.transform, assets, context);
CreateQuestCompletePanel(canvasObject.transform, assets, context);
return context;
}
private static void CreateControlHintPanel(Transform parent, BuilderAssets assets)
{
var panel = CreatePanel(
"ControlsPanel",
parent,
new Vector2(0f, 1f),
new Vector2(0f, 1f),
new Vector2(0f, 1f),
new Vector2(20f, -20f),
new Vector2(320f, 140f),
new Color(0.1f, 0.12f, 0.16f, 0.82f),
null);
CreateText(
"ControlsText",
panel.transform,
"WASD — движение\nМышь — обзор\nE — взаимодействовать\nI — инвентарь",
assets.font,
24,
TextAnchor.UpperLeft,
new Vector2(0f, 0f),
new Vector2(1f, 1f),
new Vector2(8f, -8f),
new Vector2(-16f, -16f),
Color.white);
}
private static Text CreateQuestStatusPanel(Transform parent, BuilderAssets assets)
{
var panel = CreatePanel(
"QuestStatusPanel",
parent,
new Vector2(1f, 1f),
new Vector2(1f, 1f),
new Vector2(1f, 1f),
new Vector2(-20f, -20f),
new Vector2(360f, 140f),
new Color(0.08f, 0.18f, 0.2f, 0.86f),
null);
return CreateText(
"QuestStatusText",
panel.transform,
"Записки: 0/3\nДиалог с NPC: ✗\nСтатус: исследуйте уровень",
assets.font,
24,
TextAnchor.UpperLeft,
new Vector2(0f, 0f),
new Vector2(1f, 1f),
new Vector2(12f, -12f),
new Vector2(-24f, -24f),
Color.white);
}
private static void CreateInventoryPanel(Transform parent, BuilderAssets assets, UIContext context)
{
var panel = CreatePanel(
"InventoryPanel",
parent,
new Vector2(0.5f, 0.5f),
new Vector2(0.5f, 0.5f),
new Vector2(0.5f, 0.5f),
Vector2.zero,
new Vector2(760f, 560f),
new Color(0.12f, 0.13f, 0.18f, 0.96f),
null);
context.inventoryPanel = panel;
panel.SetActive(false);
CreateText(
"InventoryTitle",
panel.transform,
"Инвентарь записок",
assets.font,
34,
TextAnchor.MiddleLeft,
new Vector2(0f, 1f),
new Vector2(1f, 1f),
new Vector2(28f, -18f),
new Vector2(-180f, 54f),
Color.white);
context.inventoryCloseButton = CreateButton(
"CloseInventoryButton",
panel.transform,
"Закрыть",
assets,
new Vector2(1f, 1f),
new Vector2(1f, 1f),
new Vector2(-30f, -24f),
new Vector2(150f, 48f),
new Color(0.57f, 0.24f, 0.2f, 1f));
CreatePanel(
"InventoryBody",
panel.transform,
new Vector2(0f, 0f),
new Vector2(1f, 1f),
new Vector2(0.5f, 0.5f),
new Vector2(0f, -20f),
new Vector2(-50f, -120f),
new Color(0.18f, 0.19f, 0.24f, 0.92f),
null);
var scrollView = new GameObject("InventoryScrollView");
scrollView.transform.SetParent(panel.transform, false);
var scrollRectTransform = scrollView.AddComponent<RectTransform>();
scrollRectTransform.anchorMin = new Vector2(0f, 0f);
scrollRectTransform.anchorMax = new Vector2(1f, 1f);
scrollRectTransform.offsetMin = new Vector2(28f, 28f);
scrollRectTransform.offsetMax = new Vector2(-28f, -92f);
var scrollImage = scrollView.AddComponent<Image>();
scrollImage.sprite = null;
scrollImage.type = Image.Type.Simple;
scrollImage.color = new Color(0.14f, 0.15f, 0.2f, 0.92f);
var scrollRect = scrollView.AddComponent<ScrollRect>();
scrollRect.horizontal = false;
scrollRect.scrollSensitivity = 25f;
var viewport = new GameObject("Viewport");
viewport.transform.SetParent(scrollView.transform, false);
var viewportRect = viewport.AddComponent<RectTransform>();
viewportRect.anchorMin = Vector2.zero;
viewportRect.anchorMax = Vector2.one;
viewportRect.offsetMin = Vector2.zero;
viewportRect.offsetMax = Vector2.zero;
var viewportImage = viewport.AddComponent<Image>();
viewportImage.sprite = null;
viewportImage.type = Image.Type.Simple;
viewportImage.color = new Color(0.08f, 0.09f, 0.12f, 0.04f);
viewport.AddComponent<Mask>().showMaskGraphic = false;
var content = new GameObject("Content");
content.transform.SetParent(viewport.transform, false);
var contentRect = content.AddComponent<RectTransform>();
contentRect.anchorMin = new Vector2(0f, 1f);
contentRect.anchorMax = new Vector2(1f, 1f);
contentRect.pivot = new Vector2(0.5f, 1f);
contentRect.offsetMin = new Vector2(16f, 0f);
contentRect.offsetMax = new Vector2(-16f, 0f);
var layout = content.AddComponent<VerticalLayoutGroup>();
layout.padding = new RectOffset(0, 0, 12, 12);
layout.spacing = 12f;
layout.childControlHeight = true;
layout.childControlWidth = true;
layout.childForceExpandHeight = false;
layout.childForceExpandWidth = true;
content.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
scrollRect.viewport = viewportRect;
scrollRect.content = contentRect;
context.inventoryContentRoot = content.transform;
context.inventoryEmptyText = CreateText(
"EmptyInventoryText",
content.transform,
"Пока что здесь пусто. Найдите записки на уровне.",
assets.font,
24,
TextAnchor.MiddleCenter,
new Vector2(0f, 0f),
new Vector2(1f, 0f),
new Vector2(12f, -20f),
new Vector2(-12f, 40f),
new Color(0.86f, 0.87f, 0.91f));
SetVerticalLayoutItem(context.inventoryEmptyText.gameObject, 96f);
context.inventoryButtonTemplate = CreateButton(
"InventoryNoteButtonTemplate",
content.transform,
"Записка",
assets,
new Vector2(0f, 1f),
new Vector2(1f, 1f),
Vector2.zero,
new Vector2(0f, 56f),
new Color(0.12f, 0.28f, 0.42f, 1f));
ConfigureLayoutButton(context.inventoryButtonTemplate, 56f);
context.inventoryButtonTemplate.gameObject.SetActive(false);
}
private static void CreateNotePanel(Transform parent, BuilderAssets assets, UIContext context)
{
var panel = CreatePanel(
"NotePanel",
parent,
new Vector2(0.5f, 0.5f),
new Vector2(0.5f, 0.5f),
new Vector2(0.5f, 0.5f),
Vector2.zero,
new Vector2(760f, 620f),
new Color(0.16f, 0.15f, 0.12f, 0.97f),
null);
context.notePanel = panel;
panel.SetActive(false);
context.noteTitleText = CreateText(
"NoteTitle",
panel.transform,
"Заголовок",
assets.font,
36,
TextAnchor.MiddleLeft,
new Vector2(0f, 1f),
new Vector2(1f, 1f),
new Vector2(28f, -22f),
new Vector2(-180f, 58f),
new Color(1f, 0.96f, 0.86f));
context.noteCloseButton = CreateButton(
"CloseNoteButton",
panel.transform,
"Закрыть",
assets,
new Vector2(1f, 1f),
new Vector2(1f, 1f),
new Vector2(-30f, -26f),
new Vector2(150f, 50f),
new Color(0.48f, 0.22f, 0.18f, 1f));
var bodyPanel = CreatePanel(
"NoteBody",
panel.transform,
new Vector2(0f, 0f),
new Vector2(1f, 1f),
new Vector2(0.5f, 0.5f),
new Vector2(0f, -30f),
new Vector2(-50f, -120f),
new Color(0.94f, 0.9f, 0.76f, 0.98f),
null);
context.noteContentText = CreateText(
"NoteContent",
bodyPanel.transform,
"Текст записки",
assets.font,
26,
TextAnchor.UpperLeft,
new Vector2(0f, 0f),
new Vector2(1f, 1f),
new Vector2(20f, -20f),
new Vector2(-40f, -40f),
new Color(0.16f, 0.13f, 0.09f));
context.noteContentText.horizontalOverflow = HorizontalWrapMode.Wrap;
context.noteContentText.verticalOverflow = VerticalWrapMode.Overflow;
}
private static void CreateDialoguePanel(Transform parent, BuilderAssets assets, UIContext context)
{
var panel = CreatePanel(
"DialoguePanel",
parent,
new Vector2(0.5f, 0f),
new Vector2(0.5f, 0f),
new Vector2(0.5f, 0f),
new Vector2(0f, 24f),
new Vector2(960f, 330f),
new Color(0.08f, 0.1f, 0.12f, 0.95f),
null);
context.dialoguePanel = panel;
panel.SetActive(false);
context.dialogueNameText = CreateText(
"DialogueName",
panel.transform,
"NPC",
assets.font,
32,
TextAnchor.MiddleLeft,
new Vector2(0f, 1f),
new Vector2(1f, 1f),
new Vector2(26f, -20f),
new Vector2(-180f, 52f),
new Color(0.73f, 0.89f, 1f));
context.dialogueCloseButton = CreateButton(
"CloseDialogueButton",
panel.transform,
"Закрыть",
assets,
new Vector2(1f, 1f),
new Vector2(1f, 1f),
new Vector2(-28f, -24f),
new Vector2(150f, 48f),
new Color(0.47f, 0.22f, 0.18f, 1f));
context.dialogueBodyText = CreateText(
"DialogueBody",
panel.transform,
"Текст диалога",
assets.font,
26,
TextAnchor.UpperLeft,
new Vector2(0f, 0.46f),
new Vector2(1f, 0.86f),
new Vector2(26f, -10f),
new Vector2(-52f, -12f),
Color.white);
var optionsRoot = new GameObject("OptionsRoot");
optionsRoot.transform.SetParent(panel.transform, false);
var optionsRect = optionsRoot.AddComponent<RectTransform>();
optionsRect.anchorMin = new Vector2(0f, 0f);
optionsRect.anchorMax = new Vector2(1f, 0.42f);
optionsRect.offsetMin = new Vector2(26f, 22f);
optionsRect.offsetMax = new Vector2(-26f, -10f);
var optionsLayout = optionsRoot.AddComponent<VerticalLayoutGroup>();
optionsLayout.padding = new RectOffset(0, 0, 8, 8);
optionsLayout.spacing = 10f;
optionsLayout.childControlHeight = true;
optionsLayout.childControlWidth = true;
optionsLayout.childForceExpandHeight = false;
optionsLayout.childForceExpandWidth = true;
optionsRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
context.dialogueOptionsRoot = optionsRoot.transform;
context.dialogueOptionTemplate = CreateButton(
"DialogueOptionTemplate",
optionsRoot.transform,
"Ответ игрока",
assets,
new Vector2(0f, 1f),
new Vector2(1f, 1f),
Vector2.zero,
new Vector2(0f, 54f),
new Color(0.11f, 0.3f, 0.39f, 1f));
ConfigureLayoutButton(context.dialogueOptionTemplate, 54f);
context.dialogueOptionTemplate.gameObject.SetActive(false);
}
private static void CreateInteractionPrompt(Transform parent, BuilderAssets assets, UIContext context)
{
var panel = CreatePanel(
"InteractionPrompt",
parent,
new Vector2(0.5f, 0f),
new Vector2(0.5f, 0f),
new Vector2(0.5f, 0f),
new Vector2(0f, 170f),
new Vector2(280f, 60f),
new Color(0.94f, 0.8f, 0.18f, 0.95f),
null);
context.promptPanel = panel;
panel.SetActive(false);
context.promptText = CreateText(
"PromptText",
panel.transform,
"Нажмите E",
assets.font,
28,
TextAnchor.MiddleCenter,
Vector2.zero,
Vector2.one,
Vector2.zero,
Vector2.zero,
new Color(0.18f, 0.14f, 0.06f));
}
private static void CreateQuestCompletePanel(Transform parent, BuilderAssets assets, UIContext context)
{
var panel = CreatePanel(
"QuestCompletePanel",
parent,
new Vector2(0.5f, 1f),
new Vector2(0.5f, 1f),
new Vector2(0.5f, 1f),
new Vector2(0f, -30f),
new Vector2(440f, 100f),
new Color(0.18f, 0.42f, 0.22f, 0.92f),
null);
context.questCompletePanel = panel;
panel.SetActive(false);
context.questCompleteText = CreateText(
"QuestCompleteText",
panel.transform,
"Квест выполнен!",
assets.font,
32,
TextAnchor.MiddleCenter,
Vector2.zero,
Vector2.one,
Vector2.zero,
Vector2.zero,
Color.white);
var levelPanel = CreatePanel(
"LevelCompletePanel",
parent,
new Vector2(0.5f, 0.5f),
new Vector2(0.5f, 0.5f),
new Vector2(0.5f, 0.5f),
Vector2.zero,
new Vector2(760f, 220f),
new Color(0.08f, 0.1f, 0.14f, 0.94f),
null);
context.levelCompletePanel = levelPanel;
levelPanel.SetActive(false);
context.levelCompleteText = CreateText(
"LevelCompleteText",
levelPanel.transform,
"Уровень завершен!",
assets.font,
38,
TextAnchor.MiddleCenter,
Vector2.zero,
Vector2.one,
new Vector2(30f, 30f),
new Vector2(-30f, -30f),
Color.white);
}
private static void CreateEventSystem(Transform parent)
{
var eventSystem = new GameObject("EventSystem");
eventSystem.transform.SetParent(parent);
eventSystem.AddComponent<EventSystem>();
eventSystem.AddComponent<StandaloneInputModule>();
}
private static void CreateGameSystems(Transform parent, UIContext ui, GameObject exitDoor, GameObject exitTrigger)
{
var systems = new GameObject("GameSystems");
systems.transform.SetParent(parent);
var prompt = systems.AddComponent<InteractionPromptUI>();
prompt.Configure(ui.promptPanel, ui.promptText);
var noteUI = systems.AddComponent<NoteUI>();
noteUI.Configure(ui.notePanel, ui.noteTitleText, ui.noteContentText, ui.noteCloseButton);
var inventory = systems.AddComponent<Inventory>();
inventory.Configure(
ui.inventoryPanel,
ui.inventoryContentRoot,
ui.inventoryButtonTemplate,
ui.inventoryEmptyText,
ui.inventoryCloseButton);
var dialogueUI = systems.AddComponent<DialogueUI>();
dialogueUI.Configure(
ui.dialoguePanel,
ui.dialogueNameText,
ui.dialogueBodyText,
ui.dialogueOptionsRoot,
ui.dialogueOptionTemplate,
ui.dialogueCloseButton);
var questManager = systems.AddComponent<QuestManager>();
questManager.Configure(
ui.questStatusText,
ui.questCompletePanel,
ui.questCompleteText,
exitDoor,
exitTrigger,
ui.levelCompletePanel,
ui.levelCompleteText,
3);
}
private static void CreatePlayer(Transform parent)
{
var player = GameObject.CreatePrimitive(PrimitiveType.Capsule);
player.name = "Player";
player.transform.SetParent(parent);
player.transform.position = new Vector3(-9f, 0.1f, -9f);
player.tag = "Player";
var renderer = player.GetComponent<Renderer>();
if (renderer != null)
{
renderer.enabled = false;
}
var primitiveCollider = player.GetComponent<CapsuleCollider>();
if (primitiveCollider != null)
{
Object.DestroyImmediate(primitiveCollider);
}
var controller = player.AddComponent<CharacterController>();
controller.center = new Vector3(0f, 1f, 0f);
controller.height = 2f;
controller.radius = 0.35f;
controller.stepOffset = 0.3f;
var cameraObject = new GameObject("PlayerCamera");
cameraObject.transform.SetParent(player.transform);
cameraObject.transform.localPosition = new Vector3(0f, 1.6f, 0f);
cameraObject.transform.localRotation = Quaternion.identity;
var camera = cameraObject.AddComponent<Camera>();
camera.fieldOfView = 70f;
camera.nearClipPlane = 0.01f;
camera.farClipPlane = 100f;
cameraObject.AddComponent<AudioListener>();
var controllerScript = player.AddComponent<SimpleFPSController>();
controllerScript.Configure(camera);
}
private static void CreateNotes(Transform parent, BuilderAssets assets)
{
var notesRoot = new GameObject("Notes");
notesRoot.transform.SetParent(parent);
CreateNote(
notesRoot.transform,
"Записка 1",
"Вчерашняя разведка подтверждает: в архивах спрятаны три части истории этого места.",
new Vector3(-8f, 1.05f, 8f),
assets.noteMaterial,
assets.highlightMaterial);
CreateNote(
notesRoot.transform,
"Записка 2",
"Смотритель знает больше, чем говорит. Но он заговорит только после того, как увидит найденные записи.",
new Vector3(3.2f, 1.35f, -4.8f),
assets.noteMaterial,
assets.highlightMaterial);
CreateNote(
notesRoot.transform,
"Записка 3",
"Если собрать все фрагменты и поговорить со смотрителем, путь к выходу из сектора откроется.",
new Vector3(8.5f, 1.7f, 9.6f),
assets.noteMaterial,
assets.highlightMaterial);
}
private static void CreateNpc(Transform parent, BuilderAssets assets)
{
var npcRoot = new GameObject("NPC_Smotritel");
npcRoot.transform.SetParent(parent);
npcRoot.transform.position = new Vector3(8.5f, 0f, -8.5f);
var body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
body.name = "Body";
body.transform.SetParent(npcRoot.transform);
body.transform.localPosition = new Vector3(0f, 1f, 0f);
body.transform.localRotation = Quaternion.identity;
body.transform.localScale = new Vector3(1f, 1f, 1f);
var bodyRenderer = body.GetComponent<Renderer>();
bodyRenderer.sharedMaterial = assets.npcMaterial;
var npc = npcRoot.AddComponent<NPC>();
npc.Configure(
"Смотритель",
"Ты уже собрал все улики? Мне нужно понять, можно ли тебе доверять.",
bodyRenderer,
assets.npcMaterial,
assets.highlightMaterial,
new List<NPC.DialogueOption>
{
new NPC.DialogueOption
{
playerReply = "Я собрал все записки. Что теперь?",
npcReply = "Теперь всё ясно. История восстановлена, а дверь к выходу больше не должна тебя удерживать.",
closeAfterSelection = false,
requiresAllNotes = true,
unavailableReply = "Нет, ты ещё не собрал все записки. Вернись, когда восстановишь всю историю."
},
new NPC.DialogueOption
{
playerReply = "Пока просто осматриваюсь.",
npcReply = string.Empty,
closeAfterSelection = true
}
});
var triggerObject = new GameObject("InteractionTrigger");
triggerObject.transform.SetParent(npcRoot.transform);
triggerObject.transform.localPosition = new Vector3(0f, 1.1f, 0f);
var sphereCollider = triggerObject.AddComponent<SphereCollider>();
sphereCollider.isTrigger = true;
sphereCollider.radius = 2.4f;
var triggerRelay = triggerObject.AddComponent<NPCTriggerRelay>();
triggerRelay.Initialize(npc);
}
private static void CreateNote(
Transform parent,
string title,
string content,
Vector3 position,
Material noteMaterial,
Material highlightMaterial)
{
var noteRoot = new GameObject(title);
noteRoot.transform.SetParent(parent);
noteRoot.transform.position = position;
var boxCollider = noteRoot.AddComponent<BoxCollider>();
boxCollider.isTrigger = true;
boxCollider.size = new Vector3(2.2f, 1.4f, 2.2f);
boxCollider.center = new Vector3(0f, 0.35f, 0f);
var visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
visual.name = "Visual";
visual.transform.SetParent(noteRoot.transform);
visual.transform.localPosition = new Vector3(0f, 0f, 0f);
visual.transform.localScale = new Vector3(0.55f, 0.06f, 0.75f);
var visualCollider = visual.GetComponent<BoxCollider>();
if (visualCollider != null)
{
Object.DestroyImmediate(visualCollider);
}
var renderer = visual.GetComponent<Renderer>();
renderer.sharedMaterial = noteMaterial;
var note = noteRoot.AddComponent<Note>();
note.Configure(title, content, renderer, noteMaterial, highlightMaterial);
}
private static void CreateTable(Transform parent, Vector3 position, Material material)
{
var tableRoot = new GameObject("Table");
tableRoot.transform.SetParent(parent);
tableRoot.transform.position = position;
CreateCube("Top", tableRoot.transform, new Vector3(0f, 0.95f, 0f), new Vector3(2f, 0.12f, 1.2f), material);
CreateCube("Leg_A", tableRoot.transform, new Vector3(-0.8f, 0.45f, -0.45f), new Vector3(0.12f, 0.9f, 0.12f), material);
CreateCube("Leg_B", tableRoot.transform, new Vector3(0.8f, 0.45f, -0.45f), new Vector3(0.12f, 0.9f, 0.12f), material);
CreateCube("Leg_C", tableRoot.transform, new Vector3(-0.8f, 0.45f, 0.45f), new Vector3(0.12f, 0.9f, 0.12f), material);
CreateCube("Leg_D", tableRoot.transform, new Vector3(0.8f, 0.45f, 0.45f), new Vector3(0.12f, 0.9f, 0.12f), material);
}
private static void CreateCrate(Transform parent, Vector3 position, Vector3 scale, Material material)
{
CreateCube("Crate", parent, position, scale, material);
}
private static void CreateShelf(Transform parent, Vector3 position, Material woodMaterial, Material fillMaterial)
{
var shelfRoot = new GameObject("Shelf");
shelfRoot.transform.SetParent(parent);
shelfRoot.transform.position = position;
CreateCube("Side_Left", shelfRoot.transform, new Vector3(-0.8f, 1.2f, 0f), new Vector3(0.14f, 2.4f, 0.6f), woodMaterial);
CreateCube("Side_Right", shelfRoot.transform, new Vector3(0.8f, 1.2f, 0f), new Vector3(0.14f, 2.4f, 0.6f), woodMaterial);
CreateCube("Top", shelfRoot.transform, new Vector3(0f, 2.35f, 0f), new Vector3(1.8f, 0.14f, 0.6f), woodMaterial);
CreateCube("Bottom", shelfRoot.transform, new Vector3(0f, 0.15f, 0f), new Vector3(1.8f, 0.14f, 0.6f), woodMaterial);
CreateCube("Middle_1", shelfRoot.transform, new Vector3(0f, 0.85f, 0f), new Vector3(1.8f, 0.1f, 0.6f), woodMaterial);
CreateCube("Middle_2", shelfRoot.transform, new Vector3(0f, 1.55f, 0f), new Vector3(1.8f, 0.1f, 0.6f), woodMaterial);
CreateCube("Storage", shelfRoot.transform, new Vector3(0f, 1.2f, -0.2f), new Vector3(1.45f, 2f, 0.12f), fillMaterial);
}
private static void CreateBench(Transform parent, Vector3 position, Material material)
{
var benchRoot = new GameObject("Bench");
benchRoot.transform.SetParent(parent);
benchRoot.transform.position = position;
CreateCube("Seat", benchRoot.transform, new Vector3(0f, 0.55f, 0f), new Vector3(2.2f, 0.14f, 0.65f), material);
CreateCube("Leg_A", benchRoot.transform, new Vector3(-0.9f, 0.25f, 0f), new Vector3(0.12f, 0.5f, 0.12f), material);
CreateCube("Leg_B", benchRoot.transform, new Vector3(0.9f, 0.25f, 0f), new Vector3(0.12f, 0.5f, 0.12f), material);
}
private static void CreateColumn(Transform parent, Vector3 position, Material material)
{
CreateCube("Column", parent, position, new Vector3(0.8f, 3f, 0.8f), material);
}
private static GameObject CreatePlane(string name, Transform parent, Vector3 position, Vector3 scale, Material material)
{
var plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
plane.name = name;
plane.transform.SetParent(parent);
plane.transform.position = position;
plane.transform.localScale = scale;
plane.GetComponent<Renderer>().sharedMaterial = material;
return plane;
}
private static GameObject CreateCube(string name, Transform parent, Vector3 position, Vector3 scale, Material material)
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name = name;
cube.transform.SetParent(parent);
cube.transform.localPosition = position;
cube.transform.localScale = scale;
cube.GetComponent<Renderer>().sharedMaterial = material;
return cube;
}
private static GameObject CreateSphere(string name, Transform parent, Vector3 position, Vector3 scale, Material material)
{
var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.name = name;
sphere.transform.SetParent(parent);
sphere.transform.localPosition = position;
sphere.transform.localScale = scale;
sphere.GetComponent<Renderer>().sharedMaterial = material;
return sphere;
}
private static GameObject CreatePanel(
string name,
Transform parent,
Vector2 anchorMin,
Vector2 anchorMax,
Vector2 pivot,
Vector2 anchoredPosition,
Vector2 sizeDelta,
Color color,
Sprite sprite)
{
var panel = new GameObject(name);
panel.transform.SetParent(parent, false);
var rectTransform = panel.AddComponent<RectTransform>();
rectTransform.anchorMin = anchorMin;
rectTransform.anchorMax = anchorMax;
rectTransform.pivot = pivot;
rectTransform.anchoredPosition = anchoredPosition;
rectTransform.sizeDelta = sizeDelta;
var image = panel.AddComponent<Image>();
image.sprite = sprite;
image.type = Image.Type.Simple;
image.color = color;
return panel;
}
private static Text CreateText(
string name,
Transform parent,
string value,
Font font,
int fontSize,
TextAnchor alignment,
Vector2 anchorMin,
Vector2 anchorMax,
Vector2 offsetMin,
Vector2 offsetMax,
Color color)
{
var textObject = new GameObject(name);
textObject.transform.SetParent(parent, false);
var rectTransform = textObject.AddComponent<RectTransform>();
rectTransform.anchorMin = anchorMin;
rectTransform.anchorMax = anchorMax;
rectTransform.offsetMin = offsetMin;
rectTransform.offsetMax = offsetMax;
var text = textObject.AddComponent<Text>();
text.font = font;
text.text = value;
text.fontSize = fontSize;
text.alignment = alignment;
text.color = color;
text.supportRichText = true;
text.horizontalOverflow = HorizontalWrapMode.Wrap;
text.verticalOverflow = VerticalWrapMode.Truncate;
return text;
}
private static Button CreateButton(
string name,
Transform parent,
string label,
BuilderAssets assets,
Vector2 anchorMin,
Vector2 anchorMax,
Vector2 anchoredPosition,
Vector2 sizeDelta,
Color color)
{
var buttonObject = new GameObject(name);
buttonObject.transform.SetParent(parent, false);
var rectTransform = buttonObject.AddComponent<RectTransform>();
rectTransform.anchorMin = anchorMin;
rectTransform.anchorMax = anchorMax;
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.anchoredPosition = anchoredPosition;
rectTransform.sizeDelta = sizeDelta;
var image = buttonObject.AddComponent<Image>();
image.sprite = null;
image.type = Image.Type.Simple;
image.color = color;
var button = buttonObject.AddComponent<Button>();
var colors = button.colors;
colors.normalColor = color;
colors.highlightedColor = color * 1.08f;
colors.pressedColor = color * 0.92f;
colors.selectedColor = color * 1.05f;
colors.disabledColor = new Color(color.r, color.g, color.b, 0.5f);
button.colors = colors;
CreateText(
"Label",
buttonObject.transform,
label,
assets.font,
24,
TextAnchor.MiddleCenter,
Vector2.zero,
Vector2.one,
Vector2.zero,
Vector2.zero,
Color.white);
return button;
}
private static void ConfigureLayoutButton(Button button, float preferredHeight)
{
if (button == null)
{
return;
}
var rectTransform = button.GetComponent<RectTransform>();
rectTransform.anchorMin = new Vector2(0f, 1f);
rectTransform.anchorMax = new Vector2(1f, 1f);
rectTransform.pivot = new Vector2(0.5f, 1f);
rectTransform.anchoredPosition = Vector2.zero;
rectTransform.sizeDelta = new Vector2(0f, preferredHeight);
SetVerticalLayoutItem(button.gameObject, preferredHeight);
}
private static void SetVerticalLayoutItem(GameObject target, float preferredHeight)
{
if (target == null)
{
return;
}
var layoutElement = target.GetComponent<LayoutElement>();
if (layoutElement == null)
{
layoutElement = target.AddComponent<LayoutElement>();
}
layoutElement.minHeight = preferredHeight;
layoutElement.preferredHeight = preferredHeight;
layoutElement.flexibleHeight = 0f;
}
private static Material CreateOrUpdateMaterial(string path, Color color, float smoothness)
{
var material = AssetDatabase.LoadAssetAtPath<Material>(path);
if (material == null)
{
material = new Material(Shader.Find("Standard"));
AssetDatabase.CreateAsset(material, path);
}
material.color = color;
material.SetFloat("_Glossiness", smoothness);
EditorUtility.SetDirty(material);
return material;
}
private static void EnsureFolder(string path)
{
var parts = path.Split('/');
var current = parts[0];
for (var i = 1; i < parts.Length; i++)
{
var next = $"{current}/{parts[i]}";
if (!AssetDatabase.IsValidFolder(next))
{
AssetDatabase.CreateFolder(current, parts[i]);
}
current = next;
}
}
private static void EnsureTag(string tag)
{
var tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
var tagsProperty = tagManager.FindProperty("tags");
for (var i = 0; i < tagsProperty.arraySize; i++)
{
if (tagsProperty.GetArrayElementAtIndex(i).stringValue == tag)
{
return;
}
}
tagsProperty.InsertArrayElementAtIndex(tagsProperty.arraySize);
tagsProperty.GetArrayElementAtIndex(tagsProperty.arraySize - 1).stringValue = tag;
tagManager.ApplyModifiedProperties();
AssetDatabase.SaveAssets();
}
}