Примечание. Я разработал эту систему для работы с 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"