1118 lines
48 KiB
C#
1118 lines
48 KiB
C#
|
|
using System.Collections.Generic;
|
||
|
|
using System.IO;
|
||
|
|
using UnityEditor;
|
||
|
|
using UnityEditor.SceneManagement;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.EventSystems;
|
||
|
|
using UnityEngine.SceneManagement;
|
||
|
|
using UnityEngine.UI;
|
||
|
|
|
||
|
|
public static class Lab5SceneBuilder
|
||
|
|
{
|
||
|
|
private const string ScenePath = "Assets/_Scenes/Lab05_QuestSystem.unity";
|
||
|
|
private static readonly Color DarkPanel = new Color(0.04f, 0.045f, 0.055f, 0.82f);
|
||
|
|
private static readonly Color Gold = new Color(1f, 0.73f, 0.24f, 1f);
|
||
|
|
private static readonly Color LightText = new Color(0.93f, 0.91f, 0.84f, 1f);
|
||
|
|
|
||
|
|
[MenuItem("Tools/Technical Game Design/Lab5/Create Quest System Scene")]
|
||
|
|
public static void CreateQuestSystemScene()
|
||
|
|
{
|
||
|
|
EnsureFolders();
|
||
|
|
Font uiFont = ImportUbuntuFont();
|
||
|
|
Dictionary<string, Material> materials = CreateMaterials();
|
||
|
|
|
||
|
|
ItemData wood = CreateItem("Wood", "Древесина", "Пучок сухих веток и брёвен для лесоруба.", 20);
|
||
|
|
ItemData stone = CreateItem("Stone", "Stone", "Камень из каменоломни.", 20);
|
||
|
|
ItemData goldOre = CreateItem("GoldOre", "GoldOre", "Редкая золотая руда.", 10);
|
||
|
|
|
||
|
|
QuestData woodQuest = CreateQuest(
|
||
|
|
"quest_help_lumberjack",
|
||
|
|
"Помощь лесорубу",
|
||
|
|
"Соберите 5 древесины.",
|
||
|
|
new QuestGoal
|
||
|
|
{
|
||
|
|
goalType = QuestGoalType.CollectItem,
|
||
|
|
targetItem = wood,
|
||
|
|
requiredAmount = 5
|
||
|
|
},
|
||
|
|
goldOre,
|
||
|
|
3);
|
||
|
|
|
||
|
|
QuestData goblinQuest = CreateQuest(
|
||
|
|
"quest_clear_camp",
|
||
|
|
"Очистка лагеря",
|
||
|
|
"Уничтожьте 3 гоблинов.",
|
||
|
|
new QuestGoal
|
||
|
|
{
|
||
|
|
goalType = QuestGoalType.KillEnemy,
|
||
|
|
enemyType = "Goblin",
|
||
|
|
requiredAmount = 3
|
||
|
|
},
|
||
|
|
stone,
|
||
|
|
5);
|
||
|
|
|
||
|
|
DialogueData elderDialogue = CreateElderDialogue(woodQuest, goblinQuest);
|
||
|
|
|
||
|
|
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
||
|
|
scene.name = "Lab05_QuestSystem";
|
||
|
|
|
||
|
|
CreateLighting();
|
||
|
|
CreateGround(materials);
|
||
|
|
CreateZones(materials, uiFont);
|
||
|
|
|
||
|
|
Camera camera = CreateCamera();
|
||
|
|
GameObject playerPrefab = CreatePlayerPrefab(materials);
|
||
|
|
GameObject elderPrefab = CreateNpcPrefab(materials, elderDialogue);
|
||
|
|
GameObject goblinPrefab = CreateGoblinPrefab(materials);
|
||
|
|
GameObject woodPrefab = CreateResourcePrefab("Wood Resource", PrimitiveType.Cylinder, materials["Wood"], wood);
|
||
|
|
GameObject stonePrefab = CreateResourcePrefab("Stone Resource", PrimitiveType.Sphere, materials["Stone"], stone);
|
||
|
|
GameObject goldPrefab = CreateResourcePrefab("GoldOre Resource", PrimitiveType.Sphere, materials["Gold"], goldOre);
|
||
|
|
|
||
|
|
InstantiatePrefab(playerPrefab, new Vector3(0f, 1f, -5f), Quaternion.identity, "Player");
|
||
|
|
InstantiatePrefab(elderPrefab, new Vector3(0f, 1f, 3f), Quaternion.Euler(0f, 180f, 0f), "NPC Староста");
|
||
|
|
PlaceResources(woodPrefab, stonePrefab, goldPrefab);
|
||
|
|
PlaceGoblins(goblinPrefab);
|
||
|
|
CreateEnvironmentProps(materials);
|
||
|
|
CreateSystems(new[] { woodQuest, goblinQuest });
|
||
|
|
CreateCanvas(uiFont);
|
||
|
|
|
||
|
|
EditorSceneManager.MarkSceneDirty(scene);
|
||
|
|
EditorSceneManager.SaveScene(scene, ScenePath);
|
||
|
|
AddSceneToBuildSettings(ScenePath);
|
||
|
|
|
||
|
|
AssetDatabase.SaveAssets();
|
||
|
|
AssetDatabase.Refresh();
|
||
|
|
Debug.Log($"Lab05 quest system scene created: {ScenePath}");
|
||
|
|
}
|
||
|
|
|
||
|
|
[MenuItem("Tools/Technical Game Design/Lab5/Validate Quest System Scene")]
|
||
|
|
public static void ValidateGeneratedScene()
|
||
|
|
{
|
||
|
|
if (!File.Exists(ScenePath))
|
||
|
|
{
|
||
|
|
throw new System.Exception($"Scene does not exist: {ScenePath}");
|
||
|
|
}
|
||
|
|
|
||
|
|
Scene scene = EditorSceneManager.OpenScene(ScenePath, OpenSceneMode.Single);
|
||
|
|
int missingScripts = CountMissingScripts(scene);
|
||
|
|
if (missingScripts > 0)
|
||
|
|
{
|
||
|
|
throw new System.Exception($"Missing scripts found: {missingScripts}");
|
||
|
|
}
|
||
|
|
|
||
|
|
Require(Object.FindObjectOfType<QuestManager>() != null, "QuestManager is missing");
|
||
|
|
Require(Object.FindObjectOfType<Inventory>() != null, "Inventory is missing");
|
||
|
|
Require(Object.FindObjectOfType<QuestLogUI>() != null, "QuestLogUI is missing");
|
||
|
|
Require(Object.FindObjectOfType<QuestTrackerUI>() != null, "QuestTrackerUI is missing");
|
||
|
|
Require(Object.FindObjectOfType<InventoryUI>() != null, "InventoryUI is missing");
|
||
|
|
Require(Object.FindObjectOfType<NotificationUI>() != null, "NotificationUI is missing");
|
||
|
|
Require(Object.FindObjectOfType<InteractionPromptUI>() != null, "InteractionPromptUI is missing");
|
||
|
|
Require(Object.FindObjectOfType<DialogueUI>() != null, "DialogueUI is missing");
|
||
|
|
Require(Object.FindObjectOfType<EventSystem>() != null, "EventSystem is missing");
|
||
|
|
Require(Object.FindObjectOfType<StandaloneInputModule>() != null, "StandaloneInputModule is missing");
|
||
|
|
Require(Object.FindObjectOfType<NPCDialogue>() != null, "NPC dialogue is missing");
|
||
|
|
Require(GameObject.FindGameObjectWithTag("Player") != null, "Player tag object is missing");
|
||
|
|
|
||
|
|
Require(Object.FindObjectsOfType<Enemy>().Length >= 5, "At least 5 goblins are required");
|
||
|
|
Require(CountResources("Wood") >= 5, "Wood resources are missing");
|
||
|
|
Require(CountResources("Stone") >= 1, "Stone resources are missing");
|
||
|
|
Require(CountResources("GoldOre") >= 1, "GoldOre resources are missing");
|
||
|
|
|
||
|
|
Require(AssetDatabase.LoadAssetAtPath<ItemData>("Assets/_Data/Items/Wood.asset") != null, "Wood ItemData is missing");
|
||
|
|
Require(AssetDatabase.LoadAssetAtPath<ItemData>("Assets/_Data/Items/Stone.asset") != null, "Stone ItemData is missing");
|
||
|
|
Require(AssetDatabase.LoadAssetAtPath<ItemData>("Assets/_Data/Items/GoldOre.asset") != null, "GoldOre ItemData is missing");
|
||
|
|
Require(AssetDatabase.LoadAssetAtPath<QuestData>("Assets/_Data/Quests/quest_help_lumberjack.asset") != null, "Quest 1 asset is missing");
|
||
|
|
Require(AssetDatabase.LoadAssetAtPath<QuestData>("Assets/_Data/Quests/quest_clear_camp.asset") != null, "Quest 2 asset is missing");
|
||
|
|
Font ubuntuFont = AssetDatabase.LoadAssetAtPath<Font>("Assets/_Fonts/Ubuntu-R.ttf");
|
||
|
|
Require(ubuntuFont != null, "Ubuntu font asset is missing");
|
||
|
|
ValidateSceneFonts(scene, ubuntuFont);
|
||
|
|
|
||
|
|
ValidateQuest(AssetDatabase.LoadAssetAtPath<QuestData>("Assets/_Data/Quests/quest_help_lumberjack.asset"), "Помощь лесорубу");
|
||
|
|
ValidateQuest(AssetDatabase.LoadAssetAtPath<QuestData>("Assets/_Data/Quests/quest_clear_camp.asset"), "Очистка лагеря");
|
||
|
|
|
||
|
|
Debug.Log("Lab05 validation passed: scene, UI, quests, rewards, resources, goblins and Ubuntu font are present.");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void Require(bool condition, string message)
|
||
|
|
{
|
||
|
|
if (!condition)
|
||
|
|
{
|
||
|
|
throw new System.Exception(message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int CountMissingScripts(Scene scene)
|
||
|
|
{
|
||
|
|
int count = 0;
|
||
|
|
foreach (GameObject root in scene.GetRootGameObjects())
|
||
|
|
{
|
||
|
|
count += CountMissingScriptsRecursive(root);
|
||
|
|
}
|
||
|
|
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int CountMissingScriptsRecursive(GameObject gameObject)
|
||
|
|
{
|
||
|
|
int count = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(gameObject);
|
||
|
|
foreach (Transform child in gameObject.transform)
|
||
|
|
{
|
||
|
|
count += CountMissingScriptsRecursive(child.gameObject);
|
||
|
|
}
|
||
|
|
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int CountResources(string itemId)
|
||
|
|
{
|
||
|
|
int count = 0;
|
||
|
|
foreach (ResourceNode node in Object.FindObjectsOfType<ResourceNode>())
|
||
|
|
{
|
||
|
|
if (node.itemData != null && node.itemData.itemId == itemId)
|
||
|
|
{
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void ValidateQuest(QuestData quest, string expectedName)
|
||
|
|
{
|
||
|
|
Require(quest != null, $"{expectedName} is missing");
|
||
|
|
Require(quest.questName == expectedName, $"{expectedName} has wrong name");
|
||
|
|
Require(quest.goals != null && quest.goals.Count > 0, $"{expectedName} has no goals");
|
||
|
|
Require(quest.rewardItem != null && quest.rewardAmount > 0, $"{expectedName} reward is not configured");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void ValidateSceneFonts(Scene scene, Font expectedFont)
|
||
|
|
{
|
||
|
|
foreach (Text text in Resources.FindObjectsOfTypeAll<Text>())
|
||
|
|
{
|
||
|
|
if (text.gameObject.scene == scene)
|
||
|
|
{
|
||
|
|
Require(text.font == expectedFont, $"Text object does not use Ubuntu Font: {text.name}");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (TextMesh textMesh in Resources.FindObjectsOfTypeAll<TextMesh>())
|
||
|
|
{
|
||
|
|
if (textMesh.gameObject.scene == scene)
|
||
|
|
{
|
||
|
|
Require(textMesh.font == expectedFont, $"TextMesh object does not use Ubuntu Font: {textMesh.name}");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (InventoryUI inventoryUI in Resources.FindObjectsOfTypeAll<InventoryUI>())
|
||
|
|
{
|
||
|
|
if (inventoryUI.gameObject.scene == scene)
|
||
|
|
{
|
||
|
|
Require(inventoryUI.uiFont == expectedFont, "InventoryUI does not use Ubuntu Font");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (QuestTrackerUI trackerUI in Resources.FindObjectsOfTypeAll<QuestTrackerUI>())
|
||
|
|
{
|
||
|
|
if (trackerUI.gameObject.scene == scene)
|
||
|
|
{
|
||
|
|
Require(trackerUI.uiFont == expectedFont, "QuestTrackerUI does not use Ubuntu Font");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (QuestLogUI questLogUI in Resources.FindObjectsOfTypeAll<QuestLogUI>())
|
||
|
|
{
|
||
|
|
if (questLogUI.gameObject.scene == scene)
|
||
|
|
{
|
||
|
|
Require(questLogUI.uiFont == expectedFont, "QuestLogUI does not use Ubuntu Font");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void EnsureFolders()
|
||
|
|
{
|
||
|
|
string[] folders =
|
||
|
|
{
|
||
|
|
"Assets/_Scenes",
|
||
|
|
"Assets/_Scripts",
|
||
|
|
"Assets/_Scripts/QuestSystem",
|
||
|
|
"Assets/_Scripts/Dialogue",
|
||
|
|
"Assets/_Scripts/Inventory",
|
||
|
|
"Assets/_Scripts/UI",
|
||
|
|
"Assets/_Scripts/Gameplay",
|
||
|
|
"Assets/_Data",
|
||
|
|
"Assets/_Data/Quests",
|
||
|
|
"Assets/_Data/Items",
|
||
|
|
"Assets/_Data/Enemies",
|
||
|
|
"Assets/_Prefabs",
|
||
|
|
"Assets/_Materials",
|
||
|
|
"Assets/_Fonts",
|
||
|
|
"Assets/Editor"
|
||
|
|
};
|
||
|
|
|
||
|
|
foreach (string folder in folders)
|
||
|
|
{
|
||
|
|
CreateFolderRecursive(folder);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateFolderRecursive(string folder)
|
||
|
|
{
|
||
|
|
if (AssetDatabase.IsValidFolder(folder))
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
string parent = Path.GetDirectoryName(folder)?.Replace("\\", "/");
|
||
|
|
string name = Path.GetFileName(folder);
|
||
|
|
if (!string.IsNullOrEmpty(parent))
|
||
|
|
{
|
||
|
|
CreateFolderRecursive(parent);
|
||
|
|
AssetDatabase.CreateFolder(parent, name);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Font ImportUbuntuFont()
|
||
|
|
{
|
||
|
|
string destination = "Assets/_Fonts/Ubuntu-R.ttf";
|
||
|
|
string source = FindUbuntuFont();
|
||
|
|
|
||
|
|
if (!string.IsNullOrEmpty(source))
|
||
|
|
{
|
||
|
|
if (!File.Exists(destination))
|
||
|
|
{
|
||
|
|
FileUtil.CopyFileOrDirectory(source, destination);
|
||
|
|
}
|
||
|
|
|
||
|
|
AssetDatabase.ImportAsset(destination, ImportAssetOptions.ForceUpdate);
|
||
|
|
Font ubuntu = AssetDatabase.LoadAssetAtPath<Font>(destination);
|
||
|
|
if (ubuntu != null)
|
||
|
|
{
|
||
|
|
return ubuntu;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||
|
|
}
|
||
|
|
|
||
|
|
private static string FindUbuntuFont()
|
||
|
|
{
|
||
|
|
string[] roots =
|
||
|
|
{
|
||
|
|
"/usr/share/fonts/truetype/ubuntu",
|
||
|
|
"/usr/share/fonts/TTF",
|
||
|
|
"/usr/share/fonts"
|
||
|
|
};
|
||
|
|
|
||
|
|
foreach (string root in roots)
|
||
|
|
{
|
||
|
|
if (!Directory.Exists(root))
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
string[] regular = Directory.GetFiles(root, "Ubuntu-R.ttf", SearchOption.AllDirectories);
|
||
|
|
if (regular.Length > 0)
|
||
|
|
{
|
||
|
|
return regular[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
string[] anyUbuntu = Directory.GetFiles(root, "*Ubuntu*.ttf", SearchOption.AllDirectories);
|
||
|
|
if (anyUbuntu.Length > 0)
|
||
|
|
{
|
||
|
|
return anyUbuntu[0];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return string.Empty;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Dictionary<string, Material> CreateMaterials()
|
||
|
|
{
|
||
|
|
return new Dictionary<string, Material>
|
||
|
|
{
|
||
|
|
["Ground"] = CreateMaterial("M_Ground_Grass", new Color(0.22f, 0.45f, 0.22f)),
|
||
|
|
["Square"] = CreateMaterial("M_Central_Square", new Color(0.42f, 0.38f, 0.32f)),
|
||
|
|
["Forest"] = CreateMaterial("M_Forest_Dark", new Color(0.08f, 0.3f, 0.12f)),
|
||
|
|
["Quarry"] = CreateMaterial("M_Quarry_Stone", new Color(0.45f, 0.43f, 0.4f)),
|
||
|
|
["Camp"] = CreateMaterial("M_Goblin_Camp", new Color(0.32f, 0.2f, 0.14f)),
|
||
|
|
["Wood"] = CreateMaterial("M_Wood", new Color(0.47f, 0.27f, 0.13f)),
|
||
|
|
["Leaves"] = CreateMaterial("M_Leaves", new Color(0.09f, 0.42f, 0.16f)),
|
||
|
|
["Stone"] = CreateMaterial("M_Stone", new Color(0.55f, 0.55f, 0.58f)),
|
||
|
|
["Gold"] = CreateMaterial("M_GoldOre", new Color(1f, 0.72f, 0.22f)),
|
||
|
|
["Player"] = CreateMaterial("M_Player", new Color(0.18f, 0.36f, 0.8f)),
|
||
|
|
["Npc"] = CreateMaterial("M_Elder", new Color(0.72f, 0.64f, 0.52f)),
|
||
|
|
["Goblin"] = CreateMaterial("M_Goblin", new Color(0.24f, 0.62f, 0.18f)),
|
||
|
|
["Tent"] = CreateMaterial("M_Tent_Red", new Color(0.5f, 0.12f, 0.08f)),
|
||
|
|
["Accent"] = CreateMaterial("M_Gold_Accent", Gold)
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Material CreateMaterial(string name, Color color)
|
||
|
|
{
|
||
|
|
string path = $"Assets/_Materials/{name}.mat";
|
||
|
|
Material material = AssetDatabase.LoadAssetAtPath<Material>(path);
|
||
|
|
if (material == null)
|
||
|
|
{
|
||
|
|
material = new Material(Shader.Find("Standard"));
|
||
|
|
AssetDatabase.CreateAsset(material, path);
|
||
|
|
}
|
||
|
|
|
||
|
|
material.color = color;
|
||
|
|
EditorUtility.SetDirty(material);
|
||
|
|
return material;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static ItemData CreateItem(string id, string displayName, string description, int maxStack)
|
||
|
|
{
|
||
|
|
string path = $"Assets/_Data/Items/{id}.asset";
|
||
|
|
ItemData item = AssetDatabase.LoadAssetAtPath<ItemData>(path);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
item = ScriptableObject.CreateInstance<ItemData>();
|
||
|
|
AssetDatabase.CreateAsset(item, path);
|
||
|
|
}
|
||
|
|
|
||
|
|
item.itemId = id;
|
||
|
|
item.itemName = displayName;
|
||
|
|
item.description = description;
|
||
|
|
item.maxStack = maxStack;
|
||
|
|
EditorUtility.SetDirty(item);
|
||
|
|
return item;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static QuestData CreateQuest(string id, string name, string description, QuestGoal goal, ItemData rewardItem, int rewardAmount)
|
||
|
|
{
|
||
|
|
string path = $"Assets/_Data/Quests/{id}.asset";
|
||
|
|
QuestData quest = AssetDatabase.LoadAssetAtPath<QuestData>(path);
|
||
|
|
if (quest == null)
|
||
|
|
{
|
||
|
|
quest = ScriptableObject.CreateInstance<QuestData>();
|
||
|
|
AssetDatabase.CreateAsset(quest, path);
|
||
|
|
}
|
||
|
|
|
||
|
|
quest.questId = id;
|
||
|
|
quest.questName = name;
|
||
|
|
quest.description = description;
|
||
|
|
quest.goals.Clear();
|
||
|
|
quest.goals.Add(goal);
|
||
|
|
quest.rewardItem = rewardItem;
|
||
|
|
quest.rewardAmount = rewardAmount;
|
||
|
|
EditorUtility.SetDirty(quest);
|
||
|
|
return quest;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static DialogueData CreateElderDialogue(QuestData woodQuest, QuestData goblinQuest)
|
||
|
|
{
|
||
|
|
string path = "Assets/_Data/VillageElderDialogue.asset";
|
||
|
|
DialogueData dialogue = AssetDatabase.LoadAssetAtPath<DialogueData>(path);
|
||
|
|
if (dialogue == null)
|
||
|
|
{
|
||
|
|
dialogue = ScriptableObject.CreateInstance<DialogueData>();
|
||
|
|
AssetDatabase.CreateAsset(dialogue, path);
|
||
|
|
}
|
||
|
|
|
||
|
|
dialogue.npcName = "Староста";
|
||
|
|
dialogue.greeting = "Добро пожаловать на площадь. Работы много, выбирайте задание.";
|
||
|
|
dialogue.responses.Clear();
|
||
|
|
dialogue.responses.Add(new DialogueResponse { text = "Нужна работа.", questToStart = woodQuest });
|
||
|
|
dialogue.responses.Add(new DialogueResponse { text = "Есть ещё задания?", questToStart = goblinQuest });
|
||
|
|
dialogue.responses.Add(new DialogueResponse { text = "До свидания.", questToStart = null });
|
||
|
|
EditorUtility.SetDirty(dialogue);
|
||
|
|
return dialogue;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateLighting()
|
||
|
|
{
|
||
|
|
GameObject lightObject = new GameObject("Directional Light");
|
||
|
|
Light light = lightObject.AddComponent<Light>();
|
||
|
|
light.type = LightType.Directional;
|
||
|
|
light.intensity = 1.1f;
|
||
|
|
lightObject.transform.rotation = Quaternion.Euler(50f, -35f, 0f);
|
||
|
|
|
||
|
|
RenderSettings.ambientLight = new Color(0.45f, 0.48f, 0.52f);
|
||
|
|
RenderSettings.fog = true;
|
||
|
|
RenderSettings.fogColor = new Color(0.55f, 0.62f, 0.58f);
|
||
|
|
RenderSettings.fogDensity = 0.012f;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateGround(Dictionary<string, Material> materials)
|
||
|
|
{
|
||
|
|
GameObject ground = GameObject.CreatePrimitive(PrimitiveType.Plane);
|
||
|
|
ground.name = "RPG Polygon Ground";
|
||
|
|
ground.transform.localScale = new Vector3(5.4f, 1f, 5.4f);
|
||
|
|
AssignMaterial(ground, materials["Ground"]);
|
||
|
|
|
||
|
|
CreateFlatZone("Центральная площадь", new Vector3(0f, 0.03f, 0f), new Vector3(12f, 0.08f, 12f), materials["Square"]);
|
||
|
|
CreateFlatZone("Лес", new Vector3(-17f, 0.04f, 2f), new Vector3(15f, 0.08f, 17f), materials["Forest"]);
|
||
|
|
CreateFlatZone("Каменоломня", new Vector3(17f, 0.04f, 1f), new Vector3(15f, 0.08f, 17f), materials["Quarry"]);
|
||
|
|
CreateFlatZone("Лагерь гоблинов", new Vector3(0f, 0.04f, 20f), new Vector3(18f, 0.08f, 14f), materials["Camp"]);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateFlatZone(string name, Vector3 position, Vector3 scale, Material material)
|
||
|
|
{
|
||
|
|
GameObject zone = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||
|
|
zone.name = name;
|
||
|
|
zone.transform.position = position;
|
||
|
|
zone.transform.localScale = scale;
|
||
|
|
AssignMaterial(zone, material);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateZones(Dictionary<string, Material> materials, Font font)
|
||
|
|
{
|
||
|
|
CreateWorldLabel("Центральная площадь", new Vector3(-4f, 0.2f, -4f), font);
|
||
|
|
CreateWorldLabel("Лес", new Vector3(-18f, 0.2f, -7f), font);
|
||
|
|
CreateWorldLabel("Каменоломня", new Vector3(14f, 0.2f, -7f), font);
|
||
|
|
CreateWorldLabel("Лагерь гоблинов", new Vector3(-5f, 0.2f, 14f), font);
|
||
|
|
|
||
|
|
for (int i = 0; i < 18; i++)
|
||
|
|
{
|
||
|
|
float x = -23f + (i % 6) * 3.2f;
|
||
|
|
float z = -6f + (i / 6) * 5.1f;
|
||
|
|
CreateTree(new Vector3(x, 0f, z), materials["Wood"], materials["Leaves"]);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < 14; i++)
|
||
|
|
{
|
||
|
|
float x = 13f + (i % 5) * 2.2f;
|
||
|
|
float z = -7f + (i / 5) * 4.2f;
|
||
|
|
CreateRock(new Vector3(x, 0.45f, z), materials["Stone"], 0.8f + i % 3 * 0.25f);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateWorldLabel(string text, Vector3 position, Font font)
|
||
|
|
{
|
||
|
|
GameObject label = new GameObject($"Label {text}", typeof(TextMesh));
|
||
|
|
label.transform.position = position;
|
||
|
|
label.transform.rotation = Quaternion.Euler(75f, 0f, 0f);
|
||
|
|
|
||
|
|
TextMesh mesh = label.GetComponent<TextMesh>();
|
||
|
|
mesh.text = text;
|
||
|
|
mesh.font = font;
|
||
|
|
mesh.fontSize = 32;
|
||
|
|
mesh.characterSize = 0.18f;
|
||
|
|
mesh.anchor = TextAnchor.MiddleCenter;
|
||
|
|
mesh.color = Gold;
|
||
|
|
|
||
|
|
MeshRenderer renderer = label.GetComponent<MeshRenderer>();
|
||
|
|
if (font != null)
|
||
|
|
{
|
||
|
|
renderer.sharedMaterial = font.material;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateTree(Vector3 position, Material wood, Material leaves)
|
||
|
|
{
|
||
|
|
GameObject trunk = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||
|
|
trunk.name = "Tree Trunk";
|
||
|
|
trunk.transform.position = position + Vector3.up * 1f;
|
||
|
|
trunk.transform.localScale = new Vector3(0.35f, 1f, 0.35f);
|
||
|
|
AssignMaterial(trunk, wood);
|
||
|
|
|
||
|
|
GameObject crown = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||
|
|
crown.name = "Tree Crown";
|
||
|
|
crown.transform.position = position + Vector3.up * 2.35f;
|
||
|
|
crown.transform.localScale = new Vector3(1.7f, 1.35f, 1.7f);
|
||
|
|
AssignMaterial(crown, leaves);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateRock(Vector3 position, Material material, float scale)
|
||
|
|
{
|
||
|
|
GameObject rock = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||
|
|
rock.name = "Quarry Rock";
|
||
|
|
rock.transform.position = position;
|
||
|
|
rock.transform.localScale = new Vector3(scale * 1.25f, scale * 0.65f, scale);
|
||
|
|
AssignMaterial(rock, material);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Camera CreateCamera()
|
||
|
|
{
|
||
|
|
GameObject cameraObject = new GameObject("Main Camera", typeof(Camera), typeof(AudioListener));
|
||
|
|
cameraObject.tag = "MainCamera";
|
||
|
|
Camera camera = cameraObject.GetComponent<Camera>();
|
||
|
|
camera.fieldOfView = 62f;
|
||
|
|
camera.nearClipPlane = 0.08f;
|
||
|
|
camera.transform.position = new Vector3(0f, 5f, -10f);
|
||
|
|
camera.transform.rotation = Quaternion.Euler(20f, 0f, 0f);
|
||
|
|
return camera;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreatePlayerPrefab(Dictionary<string, Material> materials)
|
||
|
|
{
|
||
|
|
GameObject player = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||
|
|
player.name = "Player";
|
||
|
|
player.tag = "Player";
|
||
|
|
player.transform.position = new Vector3(0f, 1f, -5f);
|
||
|
|
AssignMaterial(player, materials["Player"]);
|
||
|
|
Object.DestroyImmediate(player.GetComponent<CapsuleCollider>());
|
||
|
|
|
||
|
|
CharacterController controller = player.AddComponent<CharacterController>();
|
||
|
|
controller.height = 2f;
|
||
|
|
controller.radius = 0.45f;
|
||
|
|
controller.center = Vector3.zero;
|
||
|
|
|
||
|
|
SimplePlayerController movement = player.AddComponent<SimplePlayerController>();
|
||
|
|
|
||
|
|
GameObject pivot = new GameObject("Camera Pivot");
|
||
|
|
pivot.transform.SetParent(player.transform);
|
||
|
|
pivot.transform.localPosition = new Vector3(0f, 1.35f, 0f);
|
||
|
|
movement.cameraPivot = pivot.transform;
|
||
|
|
player.AddComponent<PlayerCombat>();
|
||
|
|
|
||
|
|
GameObject prefab = SavePrefab(player, "Assets/_Prefabs/Player.prefab");
|
||
|
|
Object.DestroyImmediate(player);
|
||
|
|
return prefab;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateNpcPrefab(Dictionary<string, Material> materials, DialogueData dialogue)
|
||
|
|
{
|
||
|
|
GameObject npc = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||
|
|
npc.name = "NPC Староста";
|
||
|
|
npc.transform.position = new Vector3(0f, 1f, 3f);
|
||
|
|
AssignMaterial(npc, materials["Npc"]);
|
||
|
|
|
||
|
|
NPCDialogue npcDialogue = npc.AddComponent<NPCDialogue>();
|
||
|
|
npcDialogue.npcId = "VillageElder";
|
||
|
|
npcDialogue.dialogueData = dialogue;
|
||
|
|
|
||
|
|
GameObject marker = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||
|
|
marker.name = "Quest Marker";
|
||
|
|
marker.transform.SetParent(npc.transform);
|
||
|
|
marker.transform.localPosition = new Vector3(0f, 1.45f, 0f);
|
||
|
|
marker.transform.localScale = Vector3.one * 0.28f;
|
||
|
|
AssignMaterial(marker, materials["Accent"]);
|
||
|
|
|
||
|
|
GameObject prefab = SavePrefab(npc, "Assets/_Prefabs/NPC_Starosta.prefab");
|
||
|
|
Object.DestroyImmediate(npc);
|
||
|
|
return prefab;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateGoblinPrefab(Dictionary<string, Material> materials)
|
||
|
|
{
|
||
|
|
GameObject goblin = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||
|
|
goblin.name = "Goblin";
|
||
|
|
goblin.transform.position = Vector3.up;
|
||
|
|
goblin.transform.localScale = new Vector3(0.85f, 0.85f, 0.85f);
|
||
|
|
AssignMaterial(goblin, materials["Goblin"]);
|
||
|
|
|
||
|
|
Enemy enemy = goblin.AddComponent<Enemy>();
|
||
|
|
enemy.enemyType = "Goblin";
|
||
|
|
enemy.health = 100;
|
||
|
|
|
||
|
|
GameObject head = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||
|
|
head.name = "Goblin Head";
|
||
|
|
head.transform.SetParent(goblin.transform);
|
||
|
|
head.transform.localPosition = new Vector3(0f, 0.75f, 0f);
|
||
|
|
head.transform.localScale = Vector3.one * 0.55f;
|
||
|
|
AssignMaterial(head, materials["Goblin"]);
|
||
|
|
|
||
|
|
GameObject prefab = SavePrefab(goblin, "Assets/_Prefabs/Goblin.prefab");
|
||
|
|
Object.DestroyImmediate(goblin);
|
||
|
|
return prefab;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateResourcePrefab(string name, PrimitiveType primitive, Material material, ItemData item)
|
||
|
|
{
|
||
|
|
GameObject resource = GameObject.CreatePrimitive(primitive);
|
||
|
|
resource.name = name;
|
||
|
|
resource.transform.position = Vector3.up * 0.5f;
|
||
|
|
resource.transform.localScale = name.StartsWith("Wood") ? new Vector3(0.45f, 1.1f, 0.45f) : Vector3.one * 0.8f;
|
||
|
|
AssignMaterial(resource, material);
|
||
|
|
|
||
|
|
ResourceNode node = resource.AddComponent<ResourceNode>();
|
||
|
|
node.itemData = item;
|
||
|
|
node.amount = 1;
|
||
|
|
|
||
|
|
GameObject prefab = SavePrefab(resource, $"Assets/_Prefabs/{name.Replace(" ", "_")}.prefab");
|
||
|
|
Object.DestroyImmediate(resource);
|
||
|
|
return prefab;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void PlaceResources(GameObject woodPrefab, GameObject stonePrefab, GameObject goldPrefab)
|
||
|
|
{
|
||
|
|
Vector3[] woodPositions =
|
||
|
|
{
|
||
|
|
new Vector3(-14f, 0.55f, -1f), new Vector3(-17f, 0.55f, 3f), new Vector3(-20f, 0.55f, 6f),
|
||
|
|
new Vector3(-12f, 0.55f, 6f), new Vector3(-18f, 0.55f, 10f), new Vector3(-22f, 0.55f, 0f)
|
||
|
|
};
|
||
|
|
|
||
|
|
Vector3[] stonePositions =
|
||
|
|
{
|
||
|
|
new Vector3(14f, 0.6f, -2f), new Vector3(18f, 0.6f, 1f), new Vector3(21f, 0.6f, 5f),
|
||
|
|
new Vector3(15f, 0.6f, 7f), new Vector3(22f, 0.6f, -5f)
|
||
|
|
};
|
||
|
|
|
||
|
|
Vector3[] goldPositions =
|
||
|
|
{
|
||
|
|
new Vector3(18f, 0.6f, 9f), new Vector3(23f, 0.6f, 2f), new Vector3(12f, 0.6f, 4f)
|
||
|
|
};
|
||
|
|
|
||
|
|
foreach (Vector3 position in woodPositions)
|
||
|
|
{
|
||
|
|
InstantiatePrefab(woodPrefab, position, Quaternion.identity, "Wood");
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (Vector3 position in stonePositions)
|
||
|
|
{
|
||
|
|
InstantiatePrefab(stonePrefab, position, Quaternion.identity, "Stone");
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (Vector3 position in goldPositions)
|
||
|
|
{
|
||
|
|
InstantiatePrefab(goldPrefab, position, Quaternion.identity, "GoldOre");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void PlaceGoblins(GameObject goblinPrefab)
|
||
|
|
{
|
||
|
|
Vector3[] positions =
|
||
|
|
{
|
||
|
|
new Vector3(-5f, 0.9f, 18f), new Vector3(0f, 0.9f, 20f), new Vector3(5f, 0.9f, 18f),
|
||
|
|
new Vector3(-3f, 0.9f, 24f), new Vector3(4f, 0.9f, 25f)
|
||
|
|
};
|
||
|
|
|
||
|
|
foreach (Vector3 position in positions)
|
||
|
|
{
|
||
|
|
InstantiatePrefab(goblinPrefab, position, Quaternion.identity, "Goblin");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateEnvironmentProps(Dictionary<string, Material> materials)
|
||
|
|
{
|
||
|
|
for (int i = 0; i < 3; i++)
|
||
|
|
{
|
||
|
|
GameObject tent = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||
|
|
tent.name = "Goblin Tent";
|
||
|
|
tent.transform.position = new Vector3(-6f + i * 6f, 0.65f, 26f);
|
||
|
|
tent.transform.localScale = new Vector3(1.7f, 0.65f, 1.7f);
|
||
|
|
AssignMaterial(tent, materials["Tent"]);
|
||
|
|
}
|
||
|
|
|
||
|
|
GameObject fire = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||
|
|
fire.name = "Campfire";
|
||
|
|
fire.transform.position = new Vector3(0f, 0.35f, 18f);
|
||
|
|
fire.transform.localScale = new Vector3(0.75f, 0.35f, 0.75f);
|
||
|
|
AssignMaterial(fire, materials["Accent"]);
|
||
|
|
|
||
|
|
PointLight("Campfire Light", new Vector3(0f, 1.7f, 18f), new Color(1f, 0.45f, 0.14f), 2.5f, 8f);
|
||
|
|
PointLight("Square Lantern", new Vector3(2f, 3.2f, 2f), Gold, 1.2f, 10f);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void PointLight(string name, Vector3 position, Color color, float intensity, float range)
|
||
|
|
{
|
||
|
|
GameObject lightObject = new GameObject(name);
|
||
|
|
lightObject.transform.position = position;
|
||
|
|
Light light = lightObject.AddComponent<Light>();
|
||
|
|
light.type = LightType.Point;
|
||
|
|
light.color = color;
|
||
|
|
light.intensity = intensity;
|
||
|
|
light.range = range;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateSystems(IEnumerable<QuestData> quests)
|
||
|
|
{
|
||
|
|
GameObject systems = new GameObject("Systems");
|
||
|
|
QuestManager questManager = systems.AddComponent<QuestManager>();
|
||
|
|
questManager.SetAvailableQuests(quests);
|
||
|
|
systems.AddComponent<Inventory>();
|
||
|
|
EditorUtility.SetDirty(questManager);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateCanvas(Font font)
|
||
|
|
{
|
||
|
|
CreateEventSystem();
|
||
|
|
|
||
|
|
GameObject canvasObject = new GameObject("Canvas", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
|
||
|
|
Canvas canvas = canvasObject.GetComponent<Canvas>();
|
||
|
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||
|
|
|
||
|
|
CanvasScaler scaler = canvasObject.GetComponent<CanvasScaler>();
|
||
|
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||
|
|
scaler.referenceResolution = new Vector2(1920f, 1080f);
|
||
|
|
scaler.matchWidthOrHeight = 0.5f;
|
||
|
|
|
||
|
|
CreateQuestTracker(canvasObject.transform, font);
|
||
|
|
CreateInventoryPanel(canvasObject.transform, font);
|
||
|
|
CreateNotificationPanel(canvasObject.transform, font);
|
||
|
|
CreateInteractionPrompt(canvasObject.transform, font);
|
||
|
|
CreateQuestLog(canvasObject.transform, font);
|
||
|
|
CreateDialoguePanel(canvasObject.transform, font);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateEventSystem()
|
||
|
|
{
|
||
|
|
GameObject eventSystemObject = new GameObject("EventSystem", typeof(EventSystem), typeof(StandaloneInputModule));
|
||
|
|
EventSystem eventSystem = eventSystemObject.GetComponent<EventSystem>();
|
||
|
|
eventSystem.sendNavigationEvents = true;
|
||
|
|
|
||
|
|
StandaloneInputModule inputModule = eventSystemObject.GetComponent<StandaloneInputModule>();
|
||
|
|
inputModule.horizontalAxis = "Horizontal";
|
||
|
|
inputModule.verticalAxis = "Vertical";
|
||
|
|
inputModule.submitButton = "Submit";
|
||
|
|
inputModule.cancelButton = "Cancel";
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateQuestTracker(Transform parent, Font font)
|
||
|
|
{
|
||
|
|
GameObject panel = CreatePanel("Active Quests Panel", parent, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(18f, -18f), new Vector2(380f, 220f), new Vector2(0f, 1f));
|
||
|
|
CreateText("Активные квесты", panel.transform, font, 20, Gold, FontStyle.Bold, new Vector2(14f, -12f), new Vector2(350f, 30f), new Vector2(0f, 1f));
|
||
|
|
Text output = CreateText("Нет активных квестов", panel.transform, font, 16, LightText, FontStyle.Normal, new Vector2(14f, -54f), new Vector2(350f, 142f), new Vector2(0f, 1f));
|
||
|
|
output.lineSpacing = 1.12f;
|
||
|
|
output.alignment = TextAnchor.UpperLeft;
|
||
|
|
RectTransform content = CreateVerticalContent("Active Quest Content Legacy", panel.transform, new Vector2(14f, -50f), new Vector2(350f, 150f), new Vector2(0f, 1f));
|
||
|
|
content.gameObject.SetActive(false);
|
||
|
|
|
||
|
|
QuestTrackerUI tracker = panel.AddComponent<QuestTrackerUI>();
|
||
|
|
tracker.content = content;
|
||
|
|
tracker.outputText = output;
|
||
|
|
tracker.uiFont = font;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateInventoryPanel(Transform parent, Font font)
|
||
|
|
{
|
||
|
|
GameObject panel = CreatePanel("Inventory Panel", parent, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-18f, -18f), new Vector2(330f, 220f), new Vector2(1f, 1f));
|
||
|
|
CreateText("Инвентарь", panel.transform, font, 20, Gold, FontStyle.Bold, new Vector2(-14f, -12f), new Vector2(300f, 30f), new Vector2(1f, 1f));
|
||
|
|
Text output = CreateText("Пусто", panel.transform, font, 16, LightText, FontStyle.Normal, new Vector2(-14f, -54f), new Vector2(300f, 142f), new Vector2(1f, 1f));
|
||
|
|
output.lineSpacing = 1.12f;
|
||
|
|
output.alignment = TextAnchor.UpperLeft;
|
||
|
|
RectTransform content = CreateVerticalContent("Inventory Content Legacy", panel.transform, new Vector2(-14f, -50f), new Vector2(300f, 150f), new Vector2(1f, 1f));
|
||
|
|
content.gameObject.SetActive(false);
|
||
|
|
|
||
|
|
InventoryUI inventoryUI = panel.AddComponent<InventoryUI>();
|
||
|
|
inventoryUI.content = content;
|
||
|
|
inventoryUI.outputText = output;
|
||
|
|
inventoryUI.uiFont = font;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateNotificationPanel(Transform parent, Font font)
|
||
|
|
{
|
||
|
|
GameObject panel = CreatePanel("Notification Panel", parent, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 42f), new Vector2(620f, 96f), new Vector2(0.5f, 0f));
|
||
|
|
CanvasGroup group = panel.AddComponent<CanvasGroup>();
|
||
|
|
Text message = CreateText(string.Empty, panel.transform, font, 22, LightText, FontStyle.Bold, Vector2.zero, new Vector2(570f, 74f), new Vector2(0.5f, 0.5f));
|
||
|
|
message.alignment = TextAnchor.MiddleCenter;
|
||
|
|
|
||
|
|
NotificationUI notification = panel.AddComponent<NotificationUI>();
|
||
|
|
notification.messageText = message;
|
||
|
|
notification.canvasGroup = group;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateInteractionPrompt(Transform parent, Font font)
|
||
|
|
{
|
||
|
|
GameObject root = CreatePanel("Interaction Prompt", parent, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 172f), new Vector2(360f, 46f), new Vector2(0.5f, 0f));
|
||
|
|
root.GetComponent<Image>().color = new Color(0.035f, 0.04f, 0.045f, 0.9f);
|
||
|
|
|
||
|
|
Outline outline = root.AddComponent<Outline>();
|
||
|
|
outline.effectColor = new Color(1f, 0.73f, 0.24f, 0.55f);
|
||
|
|
outline.effectDistance = new Vector2(1f, -1f);
|
||
|
|
|
||
|
|
Text text = CreateText("E Поговорить", root.transform, font, 18, LightText, FontStyle.Bold, Vector2.zero, new Vector2(320f, 34f), new Vector2(0.5f, 0.5f));
|
||
|
|
text.alignment = TextAnchor.MiddleCenter;
|
||
|
|
|
||
|
|
InteractionPromptUI prompt = parent.gameObject.AddComponent<InteractionPromptUI>();
|
||
|
|
prompt.root = root;
|
||
|
|
prompt.promptText = text;
|
||
|
|
root.SetActive(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateQuestLog(Transform parent, Font font)
|
||
|
|
{
|
||
|
|
GameObject root = CreatePanel("Quest Log Panel", parent, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(760f, 650f), new Vector2(0.5f, 0.5f));
|
||
|
|
CreateText("Журнал квестов", root.transform, font, 28, Gold, FontStyle.Bold, new Vector2(0f, -24f), new Vector2(700f, 42f), new Vector2(0.5f, 1f));
|
||
|
|
|
||
|
|
GameObject scrollObject = new GameObject("Scroll View", typeof(RectTransform), typeof(ScrollRect), typeof(Image));
|
||
|
|
scrollObject.transform.SetParent(root.transform, false);
|
||
|
|
RectTransform scrollRectTransform = scrollObject.GetComponent<RectTransform>();
|
||
|
|
scrollRectTransform.anchorMin = new Vector2(0.5f, 0.5f);
|
||
|
|
scrollRectTransform.anchorMax = new Vector2(0.5f, 0.5f);
|
||
|
|
scrollRectTransform.pivot = new Vector2(0.5f, 0.5f);
|
||
|
|
scrollRectTransform.anchoredPosition = new Vector2(0f, -34f);
|
||
|
|
scrollRectTransform.sizeDelta = new Vector2(700f, 540f);
|
||
|
|
scrollObject.GetComponent<Image>().color = new Color(0f, 0f, 0f, 0.18f);
|
||
|
|
|
||
|
|
GameObject viewport = new GameObject("Viewport", typeof(RectTransform), typeof(Image), typeof(Mask));
|
||
|
|
viewport.transform.SetParent(scrollObject.transform, false);
|
||
|
|
RectTransform viewportRect = Stretch(viewport);
|
||
|
|
viewport.GetComponent<Image>().color = new Color(0f, 0f, 0f, 0.08f);
|
||
|
|
viewport.GetComponent<Mask>().showMaskGraphic = false;
|
||
|
|
|
||
|
|
GameObject contentObject = new GameObject("Content", typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter));
|
||
|
|
contentObject.transform.SetParent(viewport.transform, false);
|
||
|
|
RectTransform content = contentObject.GetComponent<RectTransform>();
|
||
|
|
content.anchorMin = new Vector2(0f, 1f);
|
||
|
|
content.anchorMax = new Vector2(1f, 1f);
|
||
|
|
content.pivot = new Vector2(0.5f, 1f);
|
||
|
|
content.anchoredPosition = Vector2.zero;
|
||
|
|
content.sizeDelta = new Vector2(0f, 0f);
|
||
|
|
VerticalLayoutGroup layout = contentObject.GetComponent<VerticalLayoutGroup>();
|
||
|
|
layout.padding = new RectOffset(18, 18, 18, 18);
|
||
|
|
layout.spacing = 3f;
|
||
|
|
layout.childForceExpandWidth = true;
|
||
|
|
layout.childForceExpandHeight = false;
|
||
|
|
ContentSizeFitter fitter = contentObject.GetComponent<ContentSizeFitter>();
|
||
|
|
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||
|
|
|
||
|
|
ScrollRect scroll = scrollObject.GetComponent<ScrollRect>();
|
||
|
|
scroll.viewport = viewportRect;
|
||
|
|
scroll.content = content;
|
||
|
|
scroll.horizontal = false;
|
||
|
|
|
||
|
|
QuestLogUI questLog = parent.gameObject.AddComponent<QuestLogUI>();
|
||
|
|
questLog.root = root;
|
||
|
|
questLog.content = content;
|
||
|
|
questLog.uiFont = font;
|
||
|
|
root.SetActive(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateDialoguePanel(Transform parent, Font font)
|
||
|
|
{
|
||
|
|
GameObject root = CreatePanel("Dialogue Panel", parent, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 38f), new Vector2(980f, 250f), new Vector2(0.5f, 0f));
|
||
|
|
root.GetComponent<Image>().color = new Color(0.04f, 0.04f, 0.04f, 0.93f);
|
||
|
|
|
||
|
|
Outline rootOutline = root.AddComponent<Outline>();
|
||
|
|
rootOutline.effectColor = new Color(1f, 0.73f, 0.24f, 0.24f);
|
||
|
|
rootOutline.effectDistance = new Vector2(1f, -1f);
|
||
|
|
|
||
|
|
GameObject npcColumn = CreateAnchoredPanel("NPC Dialogue Copy", root.transform, new Vector2(0f, 1f), new Vector2(24f, -24f), new Vector2(590f, 198f), new Vector2(0f, 1f), new Color(0f, 0f, 0f, 0.16f));
|
||
|
|
Text nameText = CreateText("Староста", npcColumn.transform, font, 25, Gold, FontStyle.Bold, new Vector2(18f, -16f), new Vector2(540f, 36f), new Vector2(0f, 1f));
|
||
|
|
Text bodyText = CreateText(string.Empty, npcColumn.transform, font, 18, LightText, FontStyle.Normal, new Vector2(18f, -64f), new Vector2(540f, 100f), new Vector2(0f, 1f));
|
||
|
|
bodyText.lineSpacing = 1.08f;
|
||
|
|
|
||
|
|
GameObject responseArea = CreateAnchoredPanel("Dialogue Responses", root.transform, new Vector2(1f, 1f), new Vector2(-24f, -24f), new Vector2(340f, 198f), new Vector2(1f, 1f), new Color(0f, 0f, 0f, 0.2f));
|
||
|
|
CreateText("Ответы", responseArea.transform, font, 15, Gold, FontStyle.Bold, new Vector2(16f, -10f), new Vector2(300f, 24f), new Vector2(0f, 1f));
|
||
|
|
|
||
|
|
GameObject responseViewport = CreateAnchoredPanel("Response Button Stack", responseArea.transform, new Vector2(0f, 1f), new Vector2(14f, -44f), new Vector2(312f, 142f), new Vector2(0f, 1f), new Color(0f, 0f, 0f, 0f));
|
||
|
|
RectTransform responseContainer = CreateStretchVerticalContent("Responses", responseViewport.transform, new RectOffset(0, 0, 0, 0));
|
||
|
|
Button template = CreateResponseButton("Response Button Template", responseContainer, font);
|
||
|
|
template.gameObject.SetActive(false);
|
||
|
|
|
||
|
|
DialogueUI dialogueUI = parent.gameObject.AddComponent<DialogueUI>();
|
||
|
|
dialogueUI.root = root;
|
||
|
|
dialogueUI.nameText = nameText;
|
||
|
|
dialogueUI.bodyText = bodyText;
|
||
|
|
dialogueUI.responseContainer = responseContainer;
|
||
|
|
dialogueUI.responseButtonTemplate = template;
|
||
|
|
root.SetActive(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreatePanel(string name, Transform parent, Vector2 anchorMin, Vector2 anchorMax, Vector2 anchoredPosition, Vector2 size, Vector2 pivot)
|
||
|
|
{
|
||
|
|
GameObject panel = new GameObject(name, typeof(RectTransform), typeof(Image));
|
||
|
|
panel.transform.SetParent(parent, false);
|
||
|
|
RectTransform rect = panel.GetComponent<RectTransform>();
|
||
|
|
rect.anchorMin = anchorMin;
|
||
|
|
rect.anchorMax = anchorMax;
|
||
|
|
rect.pivot = pivot;
|
||
|
|
rect.anchoredPosition = anchoredPosition;
|
||
|
|
rect.sizeDelta = size;
|
||
|
|
Image image = panel.GetComponent<Image>();
|
||
|
|
image.color = DarkPanel;
|
||
|
|
return panel;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateInsetPanel(string name, Transform parent, Vector2 offsetMin, Vector2 offsetMax, Color color)
|
||
|
|
{
|
||
|
|
GameObject panel = new GameObject(name, typeof(RectTransform), typeof(Image));
|
||
|
|
panel.transform.SetParent(parent, false);
|
||
|
|
RectTransform rect = panel.GetComponent<RectTransform>();
|
||
|
|
rect.anchorMin = Vector2.zero;
|
||
|
|
rect.anchorMax = Vector2.one;
|
||
|
|
rect.offsetMin = offsetMin;
|
||
|
|
rect.offsetMax = offsetMax;
|
||
|
|
|
||
|
|
Image image = panel.GetComponent<Image>();
|
||
|
|
image.color = color;
|
||
|
|
return panel;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject CreateAnchoredPanel(string name, Transform parent, Vector2 anchor, Vector2 anchoredPosition, Vector2 size, Vector2 pivot, Color color)
|
||
|
|
{
|
||
|
|
GameObject panel = new GameObject(name, typeof(RectTransform), typeof(Image));
|
||
|
|
panel.transform.SetParent(parent, false);
|
||
|
|
RectTransform rect = panel.GetComponent<RectTransform>();
|
||
|
|
rect.anchorMin = anchor;
|
||
|
|
rect.anchorMax = anchor;
|
||
|
|
rect.pivot = pivot;
|
||
|
|
rect.anchoredPosition = anchoredPosition;
|
||
|
|
rect.sizeDelta = size;
|
||
|
|
|
||
|
|
Image image = panel.GetComponent<Image>();
|
||
|
|
image.color = color;
|
||
|
|
return panel;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Text CreateText(string value, Transform parent, Font font, int size, Color color, FontStyle style, Vector2 anchoredPosition, Vector2 rectSize, Vector2 pivot)
|
||
|
|
{
|
||
|
|
GameObject textObject = new GameObject("Text", typeof(RectTransform), typeof(Text));
|
||
|
|
textObject.transform.SetParent(parent, false);
|
||
|
|
RectTransform rect = textObject.GetComponent<RectTransform>();
|
||
|
|
rect.anchorMin = pivot;
|
||
|
|
rect.anchorMax = pivot;
|
||
|
|
rect.pivot = pivot;
|
||
|
|
rect.anchoredPosition = anchoredPosition;
|
||
|
|
rect.sizeDelta = rectSize;
|
||
|
|
|
||
|
|
Text text = textObject.GetComponent<Text>();
|
||
|
|
text.font = font != null ? font : Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||
|
|
text.text = value;
|
||
|
|
text.fontSize = size;
|
||
|
|
text.fontStyle = style;
|
||
|
|
text.color = color;
|
||
|
|
text.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||
|
|
text.verticalOverflow = VerticalWrapMode.Overflow;
|
||
|
|
return text;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static RectTransform CreateVerticalContent(string name, Transform parent, Vector2 anchoredPosition, Vector2 size, Vector2 pivot)
|
||
|
|
{
|
||
|
|
GameObject contentObject = new GameObject(name, typeof(RectTransform), typeof(VerticalLayoutGroup));
|
||
|
|
contentObject.transform.SetParent(parent, false);
|
||
|
|
RectTransform rect = contentObject.GetComponent<RectTransform>();
|
||
|
|
rect.anchorMin = pivot;
|
||
|
|
rect.anchorMax = pivot;
|
||
|
|
rect.pivot = pivot;
|
||
|
|
rect.anchoredPosition = anchoredPosition;
|
||
|
|
rect.sizeDelta = size;
|
||
|
|
|
||
|
|
VerticalLayoutGroup layout = contentObject.GetComponent<VerticalLayoutGroup>();
|
||
|
|
layout.spacing = 2f;
|
||
|
|
layout.childForceExpandWidth = true;
|
||
|
|
layout.childForceExpandHeight = false;
|
||
|
|
return rect;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static RectTransform CreateStretchVerticalContent(string name, Transform parent, RectOffset padding)
|
||
|
|
{
|
||
|
|
GameObject contentObject = new GameObject(name, typeof(RectTransform), typeof(VerticalLayoutGroup));
|
||
|
|
contentObject.transform.SetParent(parent, false);
|
||
|
|
RectTransform rect = contentObject.GetComponent<RectTransform>();
|
||
|
|
rect.anchorMin = Vector2.zero;
|
||
|
|
rect.anchorMax = Vector2.one;
|
||
|
|
rect.offsetMin = Vector2.zero;
|
||
|
|
rect.offsetMax = Vector2.zero;
|
||
|
|
|
||
|
|
VerticalLayoutGroup layout = contentObject.GetComponent<VerticalLayoutGroup>();
|
||
|
|
layout.padding = padding;
|
||
|
|
layout.spacing = 8f;
|
||
|
|
layout.childAlignment = TextAnchor.UpperLeft;
|
||
|
|
layout.childControlWidth = true;
|
||
|
|
layout.childControlHeight = true;
|
||
|
|
layout.childForceExpandWidth = true;
|
||
|
|
layout.childForceExpandHeight = false;
|
||
|
|
return rect;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Button CreateResponseButton(string name, Transform parent, Font font)
|
||
|
|
{
|
||
|
|
GameObject buttonObject = new GameObject(name, typeof(RectTransform), typeof(Image), typeof(Button), typeof(LayoutElement), typeof(Outline));
|
||
|
|
buttonObject.transform.SetParent(parent, false);
|
||
|
|
RectTransform rect = buttonObject.GetComponent<RectTransform>();
|
||
|
|
rect.anchorMin = new Vector2(0f, 1f);
|
||
|
|
rect.anchorMax = new Vector2(1f, 1f);
|
||
|
|
rect.pivot = new Vector2(0.5f, 1f);
|
||
|
|
rect.sizeDelta = new Vector2(0f, 40f);
|
||
|
|
|
||
|
|
LayoutElement layoutElement = buttonObject.GetComponent<LayoutElement>();
|
||
|
|
layoutElement.minHeight = 40f;
|
||
|
|
layoutElement.preferredHeight = 40f;
|
||
|
|
layoutElement.flexibleWidth = 1f;
|
||
|
|
|
||
|
|
Image image = buttonObject.GetComponent<Image>();
|
||
|
|
image.color = new Color(0.12f, 0.1f, 0.075f, 0.98f);
|
||
|
|
|
||
|
|
Outline outline = buttonObject.GetComponent<Outline>();
|
||
|
|
outline.effectColor = new Color(1f, 0.73f, 0.24f, 0.45f);
|
||
|
|
outline.effectDistance = new Vector2(1f, -1f);
|
||
|
|
|
||
|
|
Button button = buttonObject.GetComponent<Button>();
|
||
|
|
ColorBlock colors = button.colors;
|
||
|
|
colors.normalColor = image.color;
|
||
|
|
colors.highlightedColor = new Color(0.24f, 0.18f, 0.09f, 1f);
|
||
|
|
colors.pressedColor = new Color(0.42f, 0.29f, 0.1f, 1f);
|
||
|
|
colors.selectedColor = colors.highlightedColor;
|
||
|
|
colors.fadeDuration = 0.08f;
|
||
|
|
button.colors = colors;
|
||
|
|
|
||
|
|
GameObject accent = new GameObject("Accent", typeof(RectTransform), typeof(Image));
|
||
|
|
accent.transform.SetParent(buttonObject.transform, false);
|
||
|
|
RectTransform accentRect = accent.GetComponent<RectTransform>();
|
||
|
|
accentRect.anchorMin = new Vector2(0f, 0f);
|
||
|
|
accentRect.anchorMax = new Vector2(0f, 1f);
|
||
|
|
accentRect.pivot = new Vector2(0f, 0.5f);
|
||
|
|
accentRect.anchoredPosition = Vector2.zero;
|
||
|
|
accentRect.sizeDelta = new Vector2(4f, 0f);
|
||
|
|
accent.GetComponent<Image>().color = Gold;
|
||
|
|
|
||
|
|
Text label = CreateStretchText("Response", buttonObject.transform, font, 17, LightText, FontStyle.Normal, new Vector2(18f, 0f), new Vector2(-14f, 0f));
|
||
|
|
label.alignment = TextAnchor.MiddleLeft;
|
||
|
|
return button;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Text CreateStretchText(string value, Transform parent, Font font, int size, Color color, FontStyle style, Vector2 offsetMin, Vector2 offsetMax)
|
||
|
|
{
|
||
|
|
GameObject textObject = new GameObject("Text", typeof(RectTransform), typeof(Text));
|
||
|
|
textObject.transform.SetParent(parent, false);
|
||
|
|
RectTransform rect = textObject.GetComponent<RectTransform>();
|
||
|
|
rect.anchorMin = Vector2.zero;
|
||
|
|
rect.anchorMax = Vector2.one;
|
||
|
|
rect.offsetMin = offsetMin;
|
||
|
|
rect.offsetMax = offsetMax;
|
||
|
|
|
||
|
|
Text text = textObject.GetComponent<Text>();
|
||
|
|
text.font = font != null ? font : Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||
|
|
text.text = value;
|
||
|
|
text.fontSize = size;
|
||
|
|
text.fontStyle = style;
|
||
|
|
text.color = color;
|
||
|
|
text.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||
|
|
text.verticalOverflow = VerticalWrapMode.Truncate;
|
||
|
|
return text;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static RectTransform Stretch(GameObject gameObject)
|
||
|
|
{
|
||
|
|
RectTransform rect = gameObject.GetComponent<RectTransform>();
|
||
|
|
rect.anchorMin = Vector2.zero;
|
||
|
|
rect.anchorMax = Vector2.one;
|
||
|
|
rect.offsetMin = Vector2.zero;
|
||
|
|
rect.offsetMax = Vector2.zero;
|
||
|
|
return rect;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject SavePrefab(GameObject source, string path)
|
||
|
|
{
|
||
|
|
GameObject prefab = PrefabUtility.SaveAsPrefabAsset(source, path);
|
||
|
|
AssetDatabase.ImportAsset(path);
|
||
|
|
return prefab != null ? prefab : AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static GameObject InstantiatePrefab(GameObject prefab, Vector3 position, Quaternion rotation, string name)
|
||
|
|
{
|
||
|
|
GameObject instance = prefab != null
|
||
|
|
? (GameObject)PrefabUtility.InstantiatePrefab(prefab)
|
||
|
|
: new GameObject(name);
|
||
|
|
|
||
|
|
instance.name = name;
|
||
|
|
instance.transform.position = position;
|
||
|
|
instance.transform.rotation = rotation;
|
||
|
|
return instance;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void AssignMaterial(GameObject gameObject, Material material)
|
||
|
|
{
|
||
|
|
Renderer renderer = gameObject.GetComponent<Renderer>();
|
||
|
|
if (renderer != null)
|
||
|
|
{
|
||
|
|
renderer.sharedMaterial = material;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void AddSceneToBuildSettings(string scenePath)
|
||
|
|
{
|
||
|
|
List<EditorBuildSettingsScene> scenes = new List<EditorBuildSettingsScene>(EditorBuildSettings.scenes);
|
||
|
|
if (!scenes.Exists(scene => scene.path == scenePath))
|
||
|
|
{
|
||
|
|
scenes.Add(new EditorBuildSettingsScene(scenePath, true));
|
||
|
|
EditorBuildSettings.scenes = scenes.ToArray();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|