821 lines
41 KiB
C#
821 lines
41 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 Lab3SceneBuilder
|
|
{
|
|
private const string ScriptsPath = "Assets/_Scripts";
|
|
private const string DataPath = "Assets/_Data";
|
|
private const string ItemsPath = "Assets/_Data/Items";
|
|
private const string RecipesPath = "Assets/_Data/Recipes";
|
|
private const string PrefabsPath = "Assets/_Prefabs";
|
|
private const string ScenesPath = "Assets/_Scenes";
|
|
private const string MaterialsPath = "Assets/_Materials";
|
|
private const string FontsPath = "Assets/_Fonts";
|
|
private const string EditorPath = "Assets/Editor";
|
|
private const string ScenePath = "Assets/_Scenes/Lab03_CraftingSystem.unity";
|
|
private const string RegularFontPath = "Assets/_Fonts/Ubuntu-Regular.ttf";
|
|
private const string BoldFontPath = "Assets/_Fonts/Ubuntu-Bold.ttf";
|
|
|
|
[MenuItem("Tools/Technical Game Design/Lab3/Create Crafting System Scene")]
|
|
public static void CreateCraftingSystemScene()
|
|
{
|
|
CreateFolders();
|
|
Font uiFont = InstallUbuntuFont();
|
|
Dictionary<string, Material> materials = CreateMaterials();
|
|
Dictionary<string, ItemData> items = CreateItems();
|
|
List<RecipeData> recipes = CreateRecipes(items);
|
|
|
|
GameObject recipeButtonPrefab = CreateRecipeButtonPrefab(uiFont);
|
|
GameObject slotPrefab = CreateInventorySlotPrefab(uiFont);
|
|
GameObject hotbarSlotPrefab = CreateHotbarSlotPrefab(uiFont);
|
|
|
|
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
|
scene.name = "Lab03_CraftingSystem";
|
|
|
|
CreateWorld(materials, items, uiFont);
|
|
CreateCameraAndLight();
|
|
CreateSystems(items, recipes, materials, uiFont, recipeButtonPrefab, slotPrefab, hotbarSlotPrefab);
|
|
|
|
EditorSceneManager.SaveScene(scene, ScenePath);
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
Debug.Log("Lab03 Crafting System scene created: " + ScenePath);
|
|
}
|
|
|
|
private static void CreateFolders()
|
|
{
|
|
string[] folders =
|
|
{
|
|
ScriptsPath,
|
|
DataPath,
|
|
ItemsPath,
|
|
RecipesPath,
|
|
PrefabsPath,
|
|
ScenesPath,
|
|
MaterialsPath,
|
|
FontsPath,
|
|
EditorPath
|
|
};
|
|
|
|
for (int i = 0; i < folders.Length; i++)
|
|
{
|
|
if (!AssetDatabase.IsValidFolder(folders[i]))
|
|
{
|
|
Directory.CreateDirectory(folders[i]);
|
|
}
|
|
}
|
|
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
private static Font InstallUbuntuFont()
|
|
{
|
|
string regularSource = FindFontFile(new[]
|
|
{
|
|
"/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf",
|
|
"/usr/share/fonts/truetype/ubuntu/Ubuntu-Regular.ttf",
|
|
"/usr/share/fonts/TTF/Ubuntu-R.ttf",
|
|
"/usr/share/fonts/TTF/Ubuntu-Regular.ttf"
|
|
}, "Ubuntu-R*.ttf", "Ubuntu-Regular*.ttf");
|
|
|
|
string boldSource = FindFontFile(new[]
|
|
{
|
|
"/usr/share/fonts/truetype/ubuntu/Ubuntu-B.ttf",
|
|
"/usr/share/fonts/truetype/ubuntu/Ubuntu-Bold.ttf",
|
|
"/usr/share/fonts/TTF/Ubuntu-B.ttf",
|
|
"/usr/share/fonts/TTF/Ubuntu-Bold.ttf"
|
|
}, "Ubuntu-B*.ttf", "Ubuntu-Bold*.ttf");
|
|
|
|
if (!string.IsNullOrEmpty(regularSource))
|
|
{
|
|
File.Copy(regularSource, RegularFontPath, true);
|
|
AssetDatabase.ImportAsset(RegularFontPath);
|
|
Debug.Log("Ubuntu regular font copied to " + RegularFontPath);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("Ubuntu regular font was not found in system font folders. UI will use built-in Arial fallback.");
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(boldSource))
|
|
{
|
|
File.Copy(boldSource, BoldFontPath, true);
|
|
AssetDatabase.ImportAsset(BoldFontPath);
|
|
Debug.Log("Ubuntu bold font copied to " + BoldFontPath);
|
|
}
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
Font font = AssetDatabase.LoadAssetAtPath<Font>(RegularFontPath);
|
|
return font != null ? font : Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
|
}
|
|
|
|
private static string FindFontFile(string[] preferredPaths, params string[] patterns)
|
|
{
|
|
for (int i = 0; i < preferredPaths.Length; i++)
|
|
{
|
|
if (File.Exists(preferredPaths[i]))
|
|
{
|
|
return preferredPaths[i];
|
|
}
|
|
}
|
|
|
|
string[] roots =
|
|
{
|
|
"/usr/share/fonts/truetype/ubuntu",
|
|
"/usr/share/fonts/TTF",
|
|
"/usr/share/fonts"
|
|
};
|
|
|
|
for (int i = 0; i < roots.Length; i++)
|
|
{
|
|
if (!Directory.Exists(roots[i]))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for (int p = 0; p < patterns.Length; p++)
|
|
{
|
|
string[] files = Directory.GetFiles(roots[i], patterns[p], SearchOption.AllDirectories);
|
|
if (files.Length > 0)
|
|
{
|
|
return files[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static Dictionary<string, Material> CreateMaterials()
|
|
{
|
|
Dictionary<string, Color> materialColors = new Dictionary<string, Color>
|
|
{
|
|
{ "Mat_Floor", new Color(0.36f, 0.42f, 0.36f) },
|
|
{ "Mat_Workbench", new Color(0.42f, 0.25f, 0.12f) },
|
|
{ "Mat_Workbench_Dark", new Color(0.22f, 0.13f, 0.07f) },
|
|
{ "Mat_Wood", new Color(0.55f, 0.34f, 0.16f) },
|
|
{ "Mat_Stone", new Color(0.47f, 0.48f, 0.47f) },
|
|
{ "Mat_Iron", new Color(0.55f, 0.58f, 0.62f) },
|
|
{ "Mat_Fiber", new Color(0.48f, 0.66f, 0.34f) },
|
|
{ "Mat_Coal", new Color(0.05f, 0.05f, 0.05f) },
|
|
{ "Mat_Herb", new Color(0.18f, 0.62f, 0.25f) },
|
|
{ "Mat_Crystal", new Color(0.35f, 0.78f, 0.95f) },
|
|
{ "Mat_Player", new Color(0.20f, 0.44f, 0.82f) },
|
|
{ "Mat_Torch_Light", new Color(1.00f, 0.55f, 0.12f) }
|
|
};
|
|
|
|
Dictionary<string, Material> result = new Dictionary<string, Material>();
|
|
foreach (KeyValuePair<string, Color> pair in materialColors)
|
|
{
|
|
string path = MaterialsPath + "/" + pair.Key + ".mat";
|
|
Material material = AssetDatabase.LoadAssetAtPath<Material>(path);
|
|
if (material == null)
|
|
{
|
|
material = new Material(Shader.Find("Standard"));
|
|
AssetDatabase.CreateAsset(material, path);
|
|
}
|
|
|
|
material.color = pair.Value;
|
|
EditorUtility.SetDirty(material);
|
|
result[pair.Key] = material;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static Dictionary<string, ItemData> CreateItems()
|
|
{
|
|
ItemDefinition[] definitions =
|
|
{
|
|
new ItemDefinition("Wood", "wood", "Древесина", "Базовый строительный ресурс для рукоятей и простых инструментов.", 64, true, new Color(0.58f, 0.36f, 0.16f)),
|
|
new ItemDefinition("Stone", "stone", "Камень", "Твердый ресурс для лезвий и ударных частей инструментов.", 64, true, new Color(0.55f, 0.55f, 0.55f)),
|
|
new ItemDefinition("Stick", "stick", "Палка", "Готовая рукоять для простых рецептов.", 64, true, new Color(0.64f, 0.42f, 0.20f)),
|
|
new ItemDefinition("IronOre", "iron_ore", "Железная руда", "Металлическое сырье для прочных инструментов.", 64, true, new Color(0.56f, 0.58f, 0.64f)),
|
|
new ItemDefinition("Fiber", "fiber", "Волокно", "Гибкий материал для перевязки и связки деталей.", 64, true, new Color(0.72f, 0.78f, 0.48f)),
|
|
new ItemDefinition("Leather", "leather", "Кожа", "Прочный материал для креплений и украшений.", 32, true, new Color(0.45f, 0.25f, 0.12f)),
|
|
new ItemDefinition("Coal", "coal", "Уголь", "Горючий ресурс для факелов.", 64, true, new Color(0.08f, 0.08f, 0.08f)),
|
|
new ItemDefinition("Herb", "herb", "Трава", "Лечебное растение для простых расходников.", 64, true, new Color(0.20f, 0.66f, 0.24f)),
|
|
new ItemDefinition("Crystal", "crystal", "Кристалл", "Редкий магический ресурс.", 16, true, new Color(0.30f, 0.80f, 1.00f)),
|
|
new ItemDefinition("Axe", "axe", "Топор", "Инструмент для рубки древесины.", 1, false, new Color(0.76f, 0.72f, 0.62f)),
|
|
new ItemDefinition("Pickaxe", "pickaxe", "Кирка", "Инструмент для добычи камня и руды.", 1, false, new Color(0.65f, 0.68f, 0.72f)),
|
|
new ItemDefinition("Torch", "torch", "Факел", "Источник света, создается по две штуки за крафт.", 16, false, new Color(1.00f, 0.62f, 0.18f)),
|
|
new ItemDefinition("Bandage", "bandage", "Бинт", "Расходный предмет для восстановления здоровья.", 16, false, new Color(0.92f, 0.90f, 0.82f)),
|
|
new ItemDefinition("MagicAmulet", "magic_amulet", "Магический амулет", "Редкий предмет, усиливающий героя.", 1, false, new Color(0.55f, 0.35f, 0.95f))
|
|
};
|
|
|
|
Dictionary<string, ItemData> items = new Dictionary<string, ItemData>();
|
|
for (int i = 0; i < definitions.Length; i++)
|
|
{
|
|
ItemDefinition definition = definitions[i];
|
|
string path = ItemsPath + "/" + definition.assetName + ".asset";
|
|
ItemData item = AssetDatabase.LoadAssetAtPath<ItemData>(path);
|
|
if (item == null)
|
|
{
|
|
item = ScriptableObject.CreateInstance<ItemData>();
|
|
AssetDatabase.CreateAsset(item, path);
|
|
}
|
|
|
|
item.itemId = definition.itemId;
|
|
item.itemName = definition.itemName;
|
|
item.description = definition.description;
|
|
item.maxStack = definition.maxStack;
|
|
item.isResource = definition.isResource;
|
|
item.itemColor = definition.itemColor;
|
|
item.icon = null;
|
|
EditorUtility.SetDirty(item);
|
|
items[definition.assetName] = item;
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
return items;
|
|
}
|
|
|
|
private static List<RecipeData> CreateRecipes(Dictionary<string, ItemData> items)
|
|
{
|
|
RecipeDefinition[] definitions =
|
|
{
|
|
new RecipeDefinition("Recipe_Axe", "recipe_axe", "Топор", "Простой топор из древесины, палки и камня.", "Axe", 1, new[] { Pair("Wood", 2), Pair("Stick", 1), Pair("Stone", 1) }),
|
|
new RecipeDefinition("Recipe_Pickaxe", "recipe_pickaxe", "Кирка", "Прочная кирка для добычи твердых ресурсов.", "Pickaxe", 1, new[] { Pair("Wood", 2), Pair("Stick", 2), Pair("IronOre", 2) }),
|
|
new RecipeDefinition("Recipe_Torch", "recipe_torch", "Факел", "Два факела из палки, угля и волокна.", "Torch", 2, new[] { Pair("Stick", 1), Pair("Coal", 1), Pair("Fiber", 1) }),
|
|
new RecipeDefinition("Recipe_Bandage", "recipe_bandage", "Бинт", "Простая лечебная повязка из волокна и травы.", "Bandage", 1, new[] { Pair("Fiber", 2), Pair("Herb", 1) }),
|
|
new RecipeDefinition("Recipe_MagicAmulet", "recipe_magic_amulet", "Магический амулет", "Редкий амулет из кристаллов, кожи и железной руды.", "MagicAmulet", 1, new[] { Pair("Crystal", 2), Pair("Leather", 1), Pair("IronOre", 1) })
|
|
};
|
|
|
|
List<RecipeData> recipes = new List<RecipeData>();
|
|
for (int i = 0; i < definitions.Length; i++)
|
|
{
|
|
RecipeDefinition definition = definitions[i];
|
|
string path = RecipesPath + "/" + definition.assetName + ".asset";
|
|
RecipeData recipe = AssetDatabase.LoadAssetAtPath<RecipeData>(path);
|
|
if (recipe == null)
|
|
{
|
|
recipe = ScriptableObject.CreateInstance<RecipeData>();
|
|
AssetDatabase.CreateAsset(recipe, path);
|
|
}
|
|
|
|
recipe.recipeId = definition.recipeId;
|
|
recipe.recipeName = definition.recipeName;
|
|
recipe.description = definition.description;
|
|
recipe.result = items[definition.resultKey];
|
|
recipe.resultAmount = definition.resultAmount;
|
|
recipe.unlockedByDefault = true;
|
|
recipe.ingredients = new Ingredient[definition.ingredients.Length];
|
|
|
|
for (int ingredientIndex = 0; ingredientIndex < definition.ingredients.Length; ingredientIndex++)
|
|
{
|
|
RecipeIngredientDefinition ingredientDefinition = definition.ingredients[ingredientIndex];
|
|
recipe.ingredients[ingredientIndex] = new Ingredient
|
|
{
|
|
item = items[ingredientDefinition.itemKey],
|
|
amount = ingredientDefinition.amount
|
|
};
|
|
}
|
|
|
|
EditorUtility.SetDirty(recipe);
|
|
recipes.Add(recipe);
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
return recipes;
|
|
}
|
|
|
|
private static RecipeIngredientDefinition Pair(string itemKey, int amount)
|
|
{
|
|
return new RecipeIngredientDefinition(itemKey, amount);
|
|
}
|
|
|
|
private static void CreateWorld(Dictionary<string, Material> materials, Dictionary<string, ItemData> items, Font worldFont)
|
|
{
|
|
GameObject floor = GameObject.CreatePrimitive(PrimitiveType.Plane);
|
|
floor.name = "Floor";
|
|
floor.transform.localScale = new Vector3(2.8f, 1f, 2.2f);
|
|
SetMaterial(floor, materials["Mat_Floor"]);
|
|
|
|
GameObject tableTop = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
tableTop.name = "Crafting Workbench";
|
|
tableTop.transform.position = new Vector3(0f, 0.65f, 3.2f);
|
|
tableTop.transform.localScale = new Vector3(3.6f, 0.28f, 1.5f);
|
|
SetMaterial(tableTop, materials["Mat_Workbench"]);
|
|
|
|
CreateCube("Workbench Leg FL", new Vector3(-1.45f, 0.25f, 3.72f), new Vector3(0.22f, 0.55f, 0.22f), materials["Mat_Workbench_Dark"]);
|
|
CreateCube("Workbench Leg FR", new Vector3(1.45f, 0.25f, 3.72f), new Vector3(0.22f, 0.55f, 0.22f), materials["Mat_Workbench_Dark"]);
|
|
CreateCube("Workbench Leg BL", new Vector3(-1.45f, 0.25f, 2.68f), new Vector3(0.22f, 0.55f, 0.22f), materials["Mat_Workbench_Dark"]);
|
|
CreateCube("Workbench Leg BR", new Vector3(1.45f, 0.25f, 2.68f), new Vector3(0.22f, 0.55f, 0.22f), materials["Mat_Workbench_Dark"]);
|
|
|
|
CreateWorldLabel("Workbench Label", "Верстак: крафт через панель справа", new Vector3(0f, 1.25f, 3.2f), worldFont);
|
|
|
|
CreatePickup("Wood Pickup A", items["Wood"], 2, PrimitiveType.Cube, new Vector3(-5.5f, 0.35f, -2.8f), new Vector3(0.55f, 0.28f, 0.28f), materials["Mat_Wood"], worldFont);
|
|
CreatePickup("Wood Pickup B", items["Wood"], 3, PrimitiveType.Cube, new Vector3(-4.8f, 0.35f, 1.8f), new Vector3(0.55f, 0.28f, 0.28f), materials["Mat_Wood"], worldFont);
|
|
CreatePickup("Stone Pickup", items["Stone"], 3, PrimitiveType.Sphere, new Vector3(-2.9f, 0.35f, -4.2f), new Vector3(0.48f, 0.34f, 0.48f), materials["Mat_Stone"], worldFont);
|
|
CreatePickup("Stick Pickup", items["Stick"], 2, PrimitiveType.Cube, new Vector3(2.2f, 0.22f, -4.7f), new Vector3(0.75f, 0.14f, 0.14f), materials["Mat_Wood"], worldFont);
|
|
CreatePickup("Iron Ore Pickup", items["IronOre"], 2, PrimitiveType.Sphere, new Vector3(5.1f, 0.35f, -2.0f), new Vector3(0.45f, 0.34f, 0.45f), materials["Mat_Iron"], worldFont);
|
|
CreatePickup("Fiber Pickup", items["Fiber"], 3, PrimitiveType.Cube, new Vector3(-3.7f, 0.20f, 4.8f), new Vector3(0.6f, 0.12f, 0.3f), materials["Mat_Fiber"], worldFont);
|
|
CreatePickup("Leather Pickup", items["Leather"], 1, PrimitiveType.Cube, new Vector3(4.4f, 0.22f, 3.8f), new Vector3(0.55f, 0.12f, 0.42f), materials["Mat_Workbench"], worldFont);
|
|
CreatePickup("Coal Pickup", items["Coal"], 2, PrimitiveType.Sphere, new Vector3(5.6f, 0.30f, 1.1f), new Vector3(0.38f, 0.28f, 0.38f), materials["Mat_Coal"], worldFont);
|
|
CreatePickup("Herb Pickup", items["Herb"], 2, PrimitiveType.Cube, new Vector3(-0.5f, 0.20f, -5.0f), new Vector3(0.45f, 0.12f, 0.45f), materials["Mat_Herb"], worldFont);
|
|
CreatePickup("Crystal Pickup", items["Crystal"], 2, PrimitiveType.Cylinder, new Vector3(2.9f, 0.45f, 5.1f), new Vector3(0.24f, 0.55f, 0.24f), materials["Mat_Crystal"], worldFont);
|
|
}
|
|
|
|
private static void CreateCameraAndLight()
|
|
{
|
|
GameObject cameraObject = new GameObject("Main Camera");
|
|
Camera camera = cameraObject.AddComponent<Camera>();
|
|
cameraObject.tag = "MainCamera";
|
|
cameraObject.transform.position = new Vector3(0f, 8f, -7f);
|
|
cameraObject.transform.rotation = Quaternion.Euler(58f, 0f, 0f);
|
|
camera.clearFlags = CameraClearFlags.SolidColor;
|
|
camera.backgroundColor = new Color(0.12f, 0.14f, 0.16f);
|
|
camera.fieldOfView = 48f;
|
|
|
|
GameObject lightObject = new GameObject("Directional Light");
|
|
Light light = lightObject.AddComponent<Light>();
|
|
light.type = LightType.Directional;
|
|
light.intensity = 1.05f;
|
|
lightObject.transform.rotation = Quaternion.Euler(50f, -30f, 0f);
|
|
}
|
|
|
|
private static void CreateSystems(Dictionary<string, ItemData> items, List<RecipeData> recipes, Dictionary<string, Material> materials, Font uiFont, GameObject recipeButtonPrefab, GameObject slotPrefab, GameObject hotbarSlotPrefab)
|
|
{
|
|
GameObject player = CreatePlayer(materials["Mat_Player"]);
|
|
Camera mainCamera = Camera.main;
|
|
if (mainCamera != null)
|
|
{
|
|
CameraFollow follow = mainCamera.gameObject.AddComponent<CameraFollow>();
|
|
follow.target = player.transform;
|
|
}
|
|
|
|
GameObject inventoryObject = new GameObject("Player Inventory");
|
|
Inventory inventory = inventoryObject.AddComponent<Inventory>();
|
|
inventory.maxSlots = 32;
|
|
inventory.testResources = new List<InventorySlot>
|
|
{
|
|
new InventorySlot(items["Wood"], 8),
|
|
new InventorySlot(items["Stone"], 6),
|
|
new InventorySlot(items["Stick"], 6),
|
|
new InventorySlot(items["IronOre"], 4),
|
|
new InventorySlot(items["Fiber"], 6),
|
|
new InventorySlot(items["Leather"], 2),
|
|
new InventorySlot(items["Coal"], 3),
|
|
new InventorySlot(items["Herb"], 3),
|
|
new InventorySlot(items["Crystal"], 2)
|
|
};
|
|
|
|
GameObject craftingObject = new GameObject("Crafting System");
|
|
CraftingSystem craftingSystem = craftingObject.AddComponent<CraftingSystem>();
|
|
craftingSystem.playerInventory = inventory;
|
|
craftingSystem.availableRecipes = recipes;
|
|
craftingSystem.lastMessage = "Собирайте ресурсы на карте, затем создавайте предметы справа.";
|
|
|
|
GameObject canvasObject = new GameObject("Canvas");
|
|
Canvas canvas = canvasObject.AddComponent<Canvas>();
|
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
CanvasScaler scaler = canvasObject.AddComponent<CanvasScaler>();
|
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
scaler.referenceResolution = new Vector2(1280f, 720f);
|
|
scaler.matchWidthOrHeight = 0.5f;
|
|
canvasObject.AddComponent<GraphicRaycaster>();
|
|
|
|
GameObject eventSystemObject = new GameObject("EventSystem");
|
|
eventSystemObject.AddComponent<EventSystem>();
|
|
eventSystemObject.AddComponent<StandaloneInputModule>();
|
|
|
|
RectTransform root = canvasObject.GetComponent<RectTransform>();
|
|
Text title = CreateText("Title", root, "Лабораторная работа №3 - Система крафта", uiFont, 22, FontStyle.Bold, TextAnchor.MiddleCenter, Color.white);
|
|
Anchor(title.rectTransform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -22f), new Vector2(720f, 36f));
|
|
|
|
Image inventoryPanel = CreatePanel("Inventory Panel", root, new Vector2(150f, -246f), new Vector2(272f, 374f), new Vector2(0f, 1f), new Color(0.055f, 0.070f, 0.085f, 0.97f));
|
|
Image recipePanel = CreatePanel("Recipe Panel", root, new Vector2(-196f, -246f), new Vector2(364f, 374f), new Vector2(1f, 1f), new Color(0.055f, 0.070f, 0.085f, 0.97f));
|
|
Image detailsPanel = CreatePanel("Recipe Details Panel", root, new Vector2(0f, 158f), new Vector2(500f, 116f), new Vector2(0.5f, 0f), new Color(0.055f, 0.070f, 0.085f, 0.96f));
|
|
Image hotbarPanel = CreatePanel("Hotbar Panel", root, new Vector2(0f, 42f), new Vector2(878f, 68f), new Vector2(0.5f, 0f), new Color(0.045f, 0.055f, 0.070f, 0.97f));
|
|
|
|
Text inventoryTitle = CreateText("Inventory Title", inventoryPanel.rectTransform, "Инвентарь", uiFont, 20, FontStyle.Bold, TextAnchor.MiddleLeft, Color.white);
|
|
Anchor(inventoryTitle.rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 160f), new Vector2(240f, 30f));
|
|
|
|
Transform slotContainer = CreateVerticalContainer("Inventory Slots", inventoryPanel.rectTransform, new Vector2(0f, 4f), new Vector2(248f, 270f), new Vector2(0.5f, 0.5f), 4f, TextAnchor.UpperCenter);
|
|
|
|
Text inventoryDebug = CreateText("Inventory Debug", inventoryPanel.rectTransform, "Ресурсов: 9", uiFont, 14, FontStyle.Normal, TextAnchor.LowerLeft, new Color(0.78f, 0.84f, 0.88f));
|
|
Anchor(inventoryDebug.rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -162f), new Vector2(240f, 24f));
|
|
|
|
Text recipeTitle = CreateText("Recipe Title", recipePanel.rectTransform, "Рецепты", uiFont, 20, FontStyle.Bold, TextAnchor.MiddleLeft, Color.white);
|
|
Anchor(recipeTitle.rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 160f), new Vector2(336f, 30f));
|
|
|
|
Transform recipeContainer = CreateRectContainer("Recipe Buttons", recipePanel.rectTransform, new Vector2(0f, -8f), new Vector2(336f, 286f), new Vector2(0.5f, 0.5f));
|
|
|
|
Text recipeDebug = CreateText("Recipe Debug", recipePanel.rectTransform, "Рецептов: 5", uiFont, 14, FontStyle.Normal, TextAnchor.LowerLeft, new Color(0.78f, 0.84f, 0.88f));
|
|
Anchor(recipeDebug.rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -162f), new Vector2(336f, 24f));
|
|
|
|
Text selectedRecipeText = CreateText("Selected Recipe Text", detailsPanel.rectTransform, "", uiFont, 12, FontStyle.Normal, TextAnchor.UpperLeft, new Color(0.88f, 0.92f, 0.95f));
|
|
Stretch(selectedRecipeText.rectTransform, 12f, 8f, 12f, 34f);
|
|
|
|
Text messageText = CreateText("Craft Message", detailsPanel.rectTransform, "Собирайте ресурсы на карте, затем создавайте предметы справа.", uiFont, 13, FontStyle.Bold, TextAnchor.MiddleLeft, new Color(0.74f, 0.95f, 0.70f));
|
|
Anchor(messageText.rectTransform, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(12f, 18f), new Vector2(-24f, 28f));
|
|
|
|
Text interactionText = CreateText("Interaction Text", root, "Подойдите к ресурсу и нажмите E", uiFont, 16, FontStyle.Bold, TextAnchor.MiddleCenter, new Color(1f, 0.92f, 0.62f));
|
|
Anchor(interactionText.rectTransform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -56f), new Vector2(540f, 28f));
|
|
|
|
Text hintText = CreateText("Hint Text", root, "WASD - движение | E - подобрать | 1-9/0 - слот | F - использовать | R - тестовые ресурсы | C - UI", uiFont, 13, FontStyle.Normal, TextAnchor.MiddleCenter, new Color(0.84f, 0.89f, 0.92f));
|
|
Anchor(hintText.rectTransform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -84f), new Vector2(850f, 24f));
|
|
|
|
Transform hotbarContainer = CreateHorizontalContainer("Hotbar Slots", hotbarPanel.rectTransform, new Vector2(0f, 0f), new Vector2(854f, 54f), new Vector2(0.5f, 0.5f), 6f, TextAnchor.MiddleCenter);
|
|
|
|
InventoryUI inventoryUI = inventoryPanel.gameObject.AddComponent<InventoryUI>();
|
|
inventoryUI.inventory = inventory;
|
|
inventoryUI.slotContainer = slotContainer;
|
|
inventoryUI.slotPrefab = slotPrefab;
|
|
|
|
CraftingUI craftingUI = recipePanel.gameObject.AddComponent<CraftingUI>();
|
|
craftingUI.craftingSystem = craftingSystem;
|
|
craftingUI.inventory = inventory;
|
|
craftingUI.recipeContainer = recipeContainer;
|
|
craftingUI.recipeButtonPrefab = recipeButtonPrefab;
|
|
craftingUI.messageText = messageText;
|
|
craftingUI.selectedRecipeText = selectedRecipeText;
|
|
craftingUI.uiFont = uiFont;
|
|
|
|
PlayerMovement movement = player.GetComponent<PlayerMovement>();
|
|
PlayerInteractor interactor = player.AddComponent<PlayerInteractor>();
|
|
interactor.inventory = inventory;
|
|
interactor.craftingSystem = craftingSystem;
|
|
interactor.interactionText = interactionText;
|
|
|
|
ItemUseSystem itemUseSystem = player.AddComponent<ItemUseSystem>();
|
|
itemUseSystem.inventory = inventory;
|
|
itemUseSystem.craftingSystem = craftingSystem;
|
|
itemUseSystem.playerMovement = movement;
|
|
itemUseSystem.playerTransform = player.transform;
|
|
itemUseSystem.torchLightMaterial = materials["Mat_Torch_Light"];
|
|
itemUseSystem.statusText = messageText;
|
|
itemUseSystem.selectableSlotCount = 10;
|
|
|
|
HotbarUI hotbarUI = hotbarPanel.gameObject.AddComponent<HotbarUI>();
|
|
hotbarUI.inventory = inventory;
|
|
hotbarUI.itemUseSystem = itemUseSystem;
|
|
hotbarUI.slotContainer = hotbarContainer;
|
|
hotbarUI.slotPrefab = hotbarSlotPrefab;
|
|
hotbarUI.slotCount = 10;
|
|
|
|
GameObject controllerObject = new GameObject("Crafting Demo Controller");
|
|
CraftingDemoController controller = controllerObject.AddComponent<CraftingDemoController>();
|
|
controller.inventory = inventory;
|
|
controller.craftingSystem = craftingSystem;
|
|
controller.craftingPanel = canvasObject;
|
|
controller.hintText = hintText;
|
|
controller.addStartingResources = false;
|
|
|
|
ApplyFontToAllText(canvasObject, uiFont);
|
|
}
|
|
|
|
private static GameObject CreateRecipeButtonPrefab(Font font)
|
|
{
|
|
GameObject root = new GameObject("RecipeButtonPrefab", typeof(RectTransform), typeof(Image), typeof(Button));
|
|
RectTransform rect = root.GetComponent<RectTransform>();
|
|
rect.sizeDelta = new Vector2(336f, 52f);
|
|
Image image = root.GetComponent<Image>();
|
|
image.color = new Color(0.13f, 0.18f, 0.20f, 0.98f);
|
|
Button button = root.GetComponent<Button>();
|
|
ColorBlock colors = button.colors;
|
|
colors.normalColor = Color.white;
|
|
colors.highlightedColor = new Color(0.90f, 0.96f, 1.00f, 1f);
|
|
colors.pressedColor = new Color(0.76f, 0.86f, 0.92f, 1f);
|
|
colors.disabledColor = new Color(0.70f, 0.70f, 0.70f, 1f);
|
|
button.colors = colors;
|
|
|
|
Image stateStripe = CreateImage("StateStripe", rect, new Color(0.24f, 0.68f, 0.36f, 1f));
|
|
Anchor(stateStripe.rectTransform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(3f, 0f), new Vector2(6f, 44f));
|
|
|
|
Text title = CreateText("Title", rect, "Recipe", font, 13, FontStyle.Bold, TextAnchor.UpperLeft, Color.white);
|
|
Anchor(title.rectTransform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(110f, -10f), new Vector2(190f, 20f));
|
|
|
|
Text result = CreateText("Result", rect, "Result", font, 12, FontStyle.Bold, TextAnchor.UpperRight, new Color(0.78f, 0.92f, 1f));
|
|
Anchor(result.rectTransform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-58f, -10f), new Vector2(100f, 20f));
|
|
|
|
Text ingredients = CreateText("Ingredients", rect, "Ingredients", font, 10, FontStyle.Normal, TextAnchor.LowerLeft, new Color(0.82f, 0.86f, 0.88f));
|
|
Anchor(ingredients.rectTransform, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(130f, 12f), new Vector2(230f, 20f));
|
|
|
|
Text status = CreateText("Status", rect, "Status", font, 10, FontStyle.Bold, TextAnchor.LowerRight, new Color(0.76f, 0.95f, 0.72f));
|
|
Anchor(status.rectTransform, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-46f, 12f), new Vector2(76f, 18f));
|
|
|
|
string path = PrefabsPath + "/RecipeButtonPrefab.prefab";
|
|
ApplyFontToAllText(root, font);
|
|
GameObject prefab = PrefabUtility.SaveAsPrefabAsset(root, path);
|
|
Object.DestroyImmediate(root);
|
|
return prefab;
|
|
}
|
|
|
|
private static GameObject CreateInventorySlotPrefab(Font font)
|
|
{
|
|
GameObject root = new GameObject("InventorySlotPrefab", typeof(RectTransform), typeof(Image));
|
|
RectTransform rect = root.GetComponent<RectTransform>();
|
|
rect.sizeDelta = new Vector2(248f, 26f);
|
|
Image image = root.GetComponent<Image>();
|
|
image.color = new Color(0.12f, 0.15f, 0.18f, 0.95f);
|
|
|
|
Image marker = CreateImage("ColorMarker", rect, Color.white);
|
|
Anchor(marker.rectTransform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(12f, 0f), new Vector2(12f, 16f));
|
|
|
|
Text label = CreateText("Label", rect, "Item x0", font, 12, FontStyle.Normal, TextAnchor.MiddleLeft, Color.white);
|
|
Anchor(label.rectTransform, new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(30f, 0f), new Vector2(-36f, 0f));
|
|
|
|
string path = PrefabsPath + "/InventorySlotPrefab.prefab";
|
|
ApplyFontToAllText(root, font);
|
|
GameObject prefab = PrefabUtility.SaveAsPrefabAsset(root, path);
|
|
Object.DestroyImmediate(root);
|
|
return prefab;
|
|
}
|
|
|
|
private static GameObject CreateHotbarSlotPrefab(Font font)
|
|
{
|
|
GameObject root = new GameObject("HotbarSlotPrefab", typeof(RectTransform), typeof(Image), typeof(Button));
|
|
RectTransform rect = root.GetComponent<RectTransform>();
|
|
rect.sizeDelta = new Vector2(78f, 50f);
|
|
root.GetComponent<Image>().color = new Color(0.10f, 0.12f, 0.15f, 0.92f);
|
|
|
|
Image marker = CreateImage("ColorMarker", rect, new Color(0.18f, 0.20f, 0.22f, 1f));
|
|
Anchor(marker.rectTransform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -10f), new Vector2(58f, 6f));
|
|
|
|
Text number = CreateText("Number", rect, "1", font, 12, FontStyle.Bold, TextAnchor.UpperLeft, new Color(0.95f, 0.90f, 0.72f));
|
|
Stretch(number.rectTransform, 6f, 4f, 6f, 4f);
|
|
|
|
Text label = CreateText("Label", rect, "Пусто", font, 10, FontStyle.Normal, TextAnchor.MiddleCenter, Color.white);
|
|
Anchor(label.rectTransform, new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, -6f), new Vector2(-8f, -16f));
|
|
|
|
string path = PrefabsPath + "/HotbarSlotPrefab.prefab";
|
|
ApplyFontToAllText(root, font);
|
|
GameObject prefab = PrefabUtility.SaveAsPrefabAsset(root, path);
|
|
Object.DestroyImmediate(root);
|
|
return prefab;
|
|
}
|
|
|
|
private static Image CreatePanel(string name, RectTransform parent, Vector2 anchoredPosition, Vector2 size, Vector2 anchor, Color color)
|
|
{
|
|
Image panel = CreateImage(name, parent, color);
|
|
Anchor(panel.rectTransform, anchor, anchor, anchoredPosition, size);
|
|
return panel;
|
|
}
|
|
|
|
private static Transform CreateVerticalContainer(string name, RectTransform parent, Vector2 anchoredPosition, Vector2 size, Vector2 anchor, float spacing, TextAnchor alignment)
|
|
{
|
|
GameObject container = new GameObject(name, typeof(RectTransform), typeof(VerticalLayoutGroup));
|
|
RectTransform rect = container.GetComponent<RectTransform>();
|
|
rect.SetParent(parent, false);
|
|
Anchor(rect, anchor, anchor, anchoredPosition, size);
|
|
|
|
VerticalLayoutGroup layout = container.GetComponent<VerticalLayoutGroup>();
|
|
layout.spacing = spacing;
|
|
layout.childAlignment = alignment;
|
|
layout.childControlWidth = true;
|
|
layout.childControlHeight = false;
|
|
layout.childForceExpandWidth = true;
|
|
layout.childForceExpandHeight = false;
|
|
|
|
return container.transform;
|
|
}
|
|
|
|
private static Transform CreateRectContainer(string name, RectTransform parent, Vector2 anchoredPosition, Vector2 size, Vector2 anchor)
|
|
{
|
|
GameObject container = new GameObject(name, typeof(RectTransform));
|
|
RectTransform rect = container.GetComponent<RectTransform>();
|
|
rect.SetParent(parent, false);
|
|
Anchor(rect, anchor, anchor, anchoredPosition, size);
|
|
return container.transform;
|
|
}
|
|
|
|
private static Transform CreateHorizontalContainer(string name, RectTransform parent, Vector2 anchoredPosition, Vector2 size, Vector2 anchor, float spacing, TextAnchor alignment)
|
|
{
|
|
GameObject container = new GameObject(name, typeof(RectTransform), typeof(HorizontalLayoutGroup));
|
|
RectTransform rect = container.GetComponent<RectTransform>();
|
|
rect.SetParent(parent, false);
|
|
Anchor(rect, anchor, anchor, anchoredPosition, size);
|
|
|
|
HorizontalLayoutGroup layout = container.GetComponent<HorizontalLayoutGroup>();
|
|
layout.spacing = spacing;
|
|
layout.childAlignment = alignment;
|
|
layout.childControlWidth = false;
|
|
layout.childControlHeight = false;
|
|
layout.childForceExpandWidth = false;
|
|
layout.childForceExpandHeight = false;
|
|
|
|
return container.transform;
|
|
}
|
|
|
|
private static Text CreateText(string name, RectTransform parent, string text, Font font, int fontSize, FontStyle style, TextAnchor alignment, Color color)
|
|
{
|
|
GameObject textObject = new GameObject(name, typeof(RectTransform), typeof(Text));
|
|
RectTransform rect = textObject.GetComponent<RectTransform>();
|
|
rect.SetParent(parent, false);
|
|
Text label = textObject.GetComponent<Text>();
|
|
label.text = text;
|
|
label.font = font;
|
|
label.fontSize = fontSize;
|
|
label.fontStyle = style;
|
|
label.alignment = alignment;
|
|
label.color = color;
|
|
label.horizontalOverflow = HorizontalWrapMode.Wrap;
|
|
label.verticalOverflow = VerticalWrapMode.Truncate;
|
|
return label;
|
|
}
|
|
|
|
private static Image CreateImage(string name, RectTransform parent, Color color)
|
|
{
|
|
GameObject imageObject = new GameObject(name, typeof(RectTransform), typeof(Image));
|
|
RectTransform rect = imageObject.GetComponent<RectTransform>();
|
|
rect.SetParent(parent, false);
|
|
Image image = imageObject.GetComponent<Image>();
|
|
image.color = color;
|
|
return image;
|
|
}
|
|
|
|
private static void Anchor(RectTransform rect, Vector2 anchorMin, Vector2 anchorMax, Vector2 anchoredPosition, Vector2 sizeDelta)
|
|
{
|
|
rect.anchorMin = anchorMin;
|
|
rect.anchorMax = anchorMax;
|
|
rect.pivot = new Vector2(0.5f, 0.5f);
|
|
rect.anchoredPosition = anchoredPosition;
|
|
rect.sizeDelta = sizeDelta;
|
|
}
|
|
|
|
private static void Stretch(RectTransform rect, float left, float top, float right, float bottom)
|
|
{
|
|
rect.anchorMin = Vector2.zero;
|
|
rect.anchorMax = Vector2.one;
|
|
rect.pivot = new Vector2(0.5f, 0.5f);
|
|
rect.offsetMin = new Vector2(left, bottom);
|
|
rect.offsetMax = new Vector2(-right, -top);
|
|
}
|
|
|
|
private static void ApplyFontToAllText(GameObject root, Font font)
|
|
{
|
|
Text[] texts = root.GetComponentsInChildren<Text>(true);
|
|
for (int i = 0; i < texts.Length; i++)
|
|
{
|
|
texts[i].font = font;
|
|
EditorUtility.SetDirty(texts[i]);
|
|
}
|
|
}
|
|
|
|
private static GameObject CreateCube(string name, Vector3 position, Vector3 scale, Material material)
|
|
{
|
|
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
cube.name = name;
|
|
cube.transform.position = position;
|
|
cube.transform.localScale = scale;
|
|
SetMaterial(cube, material);
|
|
return cube;
|
|
}
|
|
|
|
private static GameObject CreatePlayer(Material material)
|
|
{
|
|
GameObject player = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
|
player.name = "Player";
|
|
player.transform.position = new Vector3(0f, 0.55f, -2.2f);
|
|
player.transform.localScale = new Vector3(0.75f, 1f, 0.75f);
|
|
SetMaterial(player, material);
|
|
|
|
CapsuleCollider capsule = player.GetComponent<CapsuleCollider>();
|
|
if (capsule != null)
|
|
{
|
|
Object.DestroyImmediate(capsule);
|
|
}
|
|
|
|
CharacterController controller = player.AddComponent<CharacterController>();
|
|
controller.height = 1.9f;
|
|
controller.radius = 0.38f;
|
|
controller.center = new Vector3(0f, 0.95f, 0f);
|
|
|
|
PlayerMovement movement = player.AddComponent<PlayerMovement>();
|
|
movement.moveSpeed = 5.2f;
|
|
return player;
|
|
}
|
|
|
|
private static void CreatePickup(string name, ItemData item, int amount, PrimitiveType primitiveType, Vector3 position, Vector3 scale, Material material, Font labelFont)
|
|
{
|
|
GameObject pickup = GameObject.CreatePrimitive(primitiveType);
|
|
pickup.name = name;
|
|
pickup.transform.position = position;
|
|
pickup.transform.localScale = scale;
|
|
SetMaterial(pickup, material);
|
|
|
|
Collider collider = pickup.GetComponent<Collider>();
|
|
if (collider != null)
|
|
{
|
|
collider.isTrigger = true;
|
|
}
|
|
|
|
ResourcePickup resourcePickup = pickup.AddComponent<ResourcePickup>();
|
|
resourcePickup.item = item;
|
|
resourcePickup.amount = amount;
|
|
resourcePickup.respawnSeconds = 10f;
|
|
|
|
CreateWorldLabel(name + " Label", item.itemName + " x" + amount, position + Vector3.up * 0.85f, labelFont, pickup.transform);
|
|
}
|
|
|
|
private static void CreateWorldLabel(string name, string text, Vector3 position, Font font, Transform parent = null)
|
|
{
|
|
GameObject labelObject = new GameObject(name);
|
|
labelObject.transform.position = position;
|
|
if (parent != null)
|
|
{
|
|
labelObject.transform.SetParent(parent, true);
|
|
}
|
|
|
|
TextMesh textMesh = labelObject.AddComponent<TextMesh>();
|
|
textMesh.text = text;
|
|
textMesh.font = font;
|
|
textMesh.fontSize = 34;
|
|
textMesh.characterSize = 0.055f;
|
|
textMesh.anchor = TextAnchor.MiddleCenter;
|
|
textMesh.alignment = TextAlignment.Center;
|
|
textMesh.color = Color.white;
|
|
|
|
MeshRenderer renderer = labelObject.GetComponent<MeshRenderer>();
|
|
if (renderer != null && font != null)
|
|
{
|
|
renderer.sharedMaterial = font.material;
|
|
}
|
|
|
|
labelObject.transform.rotation = Quaternion.Euler(60f, 0f, 0f);
|
|
}
|
|
|
|
private static void CreateResourceDecoration(string name, PrimitiveType primitiveType, Vector3 position, Vector3 scale, Material material)
|
|
{
|
|
GameObject resource = GameObject.CreatePrimitive(primitiveType);
|
|
resource.name = name;
|
|
resource.transform.position = position;
|
|
resource.transform.localScale = scale;
|
|
SetMaterial(resource, material);
|
|
}
|
|
|
|
private static void SetMaterial(GameObject gameObject, Material material)
|
|
{
|
|
Renderer renderer = gameObject.GetComponent<Renderer>();
|
|
if (renderer != null)
|
|
{
|
|
renderer.sharedMaterial = material;
|
|
}
|
|
}
|
|
|
|
private struct ItemDefinition
|
|
{
|
|
public readonly string assetName;
|
|
public readonly string itemId;
|
|
public readonly string itemName;
|
|
public readonly string description;
|
|
public readonly int maxStack;
|
|
public readonly bool isResource;
|
|
public readonly Color itemColor;
|
|
|
|
public ItemDefinition(string assetName, string itemId, string itemName, string description, int maxStack, bool isResource, Color itemColor)
|
|
{
|
|
this.assetName = assetName;
|
|
this.itemId = itemId;
|
|
this.itemName = itemName;
|
|
this.description = description;
|
|
this.maxStack = maxStack;
|
|
this.isResource = isResource;
|
|
this.itemColor = itemColor;
|
|
}
|
|
}
|
|
|
|
private struct RecipeIngredientDefinition
|
|
{
|
|
public readonly string itemKey;
|
|
public readonly int amount;
|
|
|
|
public RecipeIngredientDefinition(string itemKey, int amount)
|
|
{
|
|
this.itemKey = itemKey;
|
|
this.amount = amount;
|
|
}
|
|
}
|
|
|
|
private struct RecipeDefinition
|
|
{
|
|
public readonly string assetName;
|
|
public readonly string recipeId;
|
|
public readonly string recipeName;
|
|
public readonly string description;
|
|
public readonly string resultKey;
|
|
public readonly int resultAmount;
|
|
public readonly RecipeIngredientDefinition[] ingredients;
|
|
|
|
public RecipeDefinition(string assetName, string recipeId, string recipeName, string description, string resultKey, int resultAmount, RecipeIngredientDefinition[] ingredients)
|
|
{
|
|
this.assetName = assetName;
|
|
this.recipeId = recipeId;
|
|
this.recipeName = recipeName;
|
|
this.description = description;
|
|
this.resultKey = resultKey;
|
|
this.resultAmount = resultAmount;
|
|
this.ingredients = ingredients;
|
|
}
|
|
}
|
|
}
|