Примечание. Я разработал эту систему для работы с Unity, но с некоторыми изменениями она должна работать с любым движком, использующим C#.
Интересно, что это? Введение.
Как вы, возможно, знаете, сделать игру модифицируемой — непростая задача. После того, как вы скомпилировали свою игру, трудно включить в нее внешние элементы. Более того, системы, позволяющие моддинг, обычно приходится создавать с нуля. В этом уроке я покажу вам, как вы можете создать модульную, модифицируемую систему инвентаризации с нуля в Unity.
В этой части руководства мы создадим сценарии инвентаря и данных игрока. Даже если у вас уже есть система инвентаризации, я бы посоветовал прочитать эту статью, так как вам может потребоваться модифицировать вашу систему для работы с моей.
Создание класса запасов
Прежде всего, нам нужно создать класс инвентаря. В редакторе Unity создайте новый скрипт. Мы назовем этот скрипт Inventory. Мы хотим, чтобы этот скрипт был статическим классом, а не моноповедением, поэтому вам нужно удалить тег : MonoBehaviour и функции запуска и обновления. Вам также потребуется изменить инвентарь открытого класса на инвентарь открытого статического класса. Наконец, вам нужно добавить два тега using в начало документа: using System.IO; и используя System.Reflection. Мы также пометим его как [System.Serializable]. На этом этапе ваш код должен выглядеть так:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using System.Reflection; [System.Serializable] public static class Inventory { }
Теперь мы хотим добавить некоторые переменные, которые помогут нам ограничить размер нашего инвентаря. Я собираюсь добавить несколько разных способов ограничить размер инвентаря, но вы можете выбрать те, которые вам больше нравятся, и использовать их. Я решил добавить два целых числа, называемых InventorySlots и StackSize, и несколько чисел с плавающей запятой, называемых MaxWeight, MaxVolume, Weight и Volume. Я также добавил логические значения UseWeight, UseVolume и UseSlots, чтобы контролировать, какие из них используются кодом для ограничения размера инвентаря. Вот как должен выглядеть ваш код:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using System.Reflection; [System.Serializable] public static class Inventory { public static int InventorySlots; public static int StackSize; public static float MaxWeight; public static float MaxVolume; public static float Weight; public static float Volume; public static bool UseWeight; public static bool UseVolume; public static bool UseSlots; }
Теперь пришло время добавить объекты в наш класс Inventory. Для этого нам нужно создать вложенный класс Object, который будет содержать всю информацию о различных объектах и их эффектах. Это то, что моддеры изменят. В этом классе объектов мы создадим строку с именем ObjectName. Мы также создадим четыре массива строк с именами EffectTypes, EffectNames, EffectValues и Components. Наконец, мы создадим четыре целых числа с именами MaxDurability, Durability, Volume и Weight.
Далее нам нужно добавить еще один небольшой класс в класс Inventory. Этот класс будет содержать только 2 переменные: целое число с именем NumberOfObjects и объект с именем ObjectInStack.
Наконец, нам нужно добавить два списка в наш класс Inventory: список объектов инвентаря с именем Objects и список объектов с именем PossibleObjects, который мы установим в новый список объектов. Вау, это было много. Вот пример того, как должен выглядеть ваш код, если я ничего не пропустил:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using System.Reflection; [System.Serializable] public static class Inventory { public static int InventorySlots; public static int StackSize; public static float MaxWeight; public static float MaxVolume; public static float Weight; public static float Volume; public static bool UseWeight; public static bool UseVolume; public static bool UseSlots; public static List<InventoryObject> Objects; public static List<Object> PossibleObjects = new List<Object> { }; public class InventoryObject { public int NumberOfObjects; public Object ObjectInStack; } public class Object { public string ObjectName; public string[] EffectTypes; public string[] EffectNames; public string[] EffectValues; public string[] Components; public int Volume; public int Weight; public int MaxDurability; public int Durability; } }
Создание класса PlayerData
Теперь пришло время создать наш класс PlayerData. Этот класс будет содержать все переменные, на которые могут влиять объекты в нашем инвентаре. Вернувшись в редактор Unity, мы начнем с создания нового сценария C#, который назовем PlayerData. Далее мы удалим тег : MonoBehaviour и функции запуска и обновления. Мы также сделаем скрипт статическим классом. Последнее, что нам нужно сделать, это добавить целые числа голода и здоровья. По умолчанию мы установим их равными 5 и 10 соответственно. Вот как это должно выглядеть:
using System.Collections; using System.Collections.Generic; using UnityEngine; public static class PlayerData { public static int Hunger = 5; public static int Health = 10; }
Наконец, пришло время создать наш последний скрипт для следующих нескольких частей руководства. Вернувшись в редактор Unity, мы создадим новый скрипт, который назовем Mods. Как и в других сценариях, мы удалим тег : MonoBehaviour и сделаем его статическим классом. Роль этого скрипта будет заключаться в хранении экземпляров вложенного класса Mod, который поможет нам контролировать, какие моды активны в данный момент.
Наконец, мы создадим вложенный класс Mod и добавим в него три строки: Name, Description и Path. Мы также добавим логическое значение IsActive. Чтобы закончить этот урок, мы добавим список модов в наш класс Mods, который называется mods. На этом этапе ваш код должен выглядеть так:
using System.Collections; using System.Collections.Generic; using UnityEngine; public static class Mods { public static List<Mod> mods; public class Mod { public string Name; public string Description; public string Path; public bool IsActive; } }
Это конец первой части этого урока. Во второй части мы начнем настраивать некоторые полезные функции для дальнейшей разработки. Я должен предупредить вас, если вы нашли эту часть запутанной, возможно, это руководство не для вас. Я не лучший учитель, и в части 3 мы начнем с Reflection, который намного сложнее, чем все, что мы делали сегодня (вот посмотрите на часть скрипта инвентаризации, которая делает это).
Если вы решите, что это слишком сложно для вас, в конце этого проекта я выложу код на GitHub и напишу статью, объясняющую, как все сделать. В противном случае увидимся во второй части, которую выпущу в течение недели.
Другие части из этой серии:
"Введение"
"Часть 2"