Гибкая/модульная система базы данных для RPG(не RPG)

Программирование на Юнити.

Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение KoteKotovK 28 окт 2017, 12:58

Долгое время ломаю голову как сделать удобную и гибкую базу данных для объектов игрового мира (Игра - реалистичное выживание, типа DayZSA). Есть простая система где объекты присваиваются к какой-то группе (классу), например так -
Синтаксис:
Используется csharp
public class Player : MonoBehaviour //Типа игрок
{
    public float Hunger = 100;
    public float Thirst = 100;

    void Update ()
    {
        Hunger -= 0.01f;
        Thirst -= 0.01f;

        Hunger = Mathf.Clamp(Hunger, 0, 100);
        Thirst = Mathf.Clamp(Thirst, 0, 100);

        if(Hunger == 0)
            print("Умираю с голода");
        if(Thirst == 0)
            print("Умираю с жажды");
    }
}

public class Food //Типа еда
{
    public float SetHunger;
    public float SetThirst;
}
 

Далее существует функция для использования данных переменных -
Синтаксис:
Используется csharp
void Eating (Food food) //Типа кушаем еду
{
    Hunger += food.SetHunger;
    Thirst += food.SetThirst;
}
 

В общем все нормально, но мне не нравится что может существовать пустая переменная. Представим что из еды у меня *вода, которая утоляет только *жажду, переменная SetHunger - пустая, но ладно в этом предмете у меня всего-лишь 2 переменные, если представить другие объекты, например оружие, то там может быть намного больше пустых переменных, которые могут мешать работе с настройкой. Я знаю что можно сделать стандартные настройки или в будущем проверки в функциях, но это какие-то костыли?
Далее перейдем к неким локальным переменных, даже скорее динамичным. Представим что у нас еда не просто в одном экземпляре (одноразовая), а определенное её кол-во (многоразовая).
Синтаксис:
Используется csharp
public class Food //Типа еда с доп настройками
{
    public string Name;

    public float SetHunger;
    public float SetThirst;

    public float MaxHunger;
    public float MaxThirst;

    public Food(string n, float sh, float st, float mh, float mt)
    {
        Name = n;
        SetHunger = sh;
        SetThirst = st;
        MaxHunger = mh;
        MaxThirst = mt;
    }
}

public Food[] DataBaseFoods = new Food[]() //Типа база данных всех ед
{
    new Food("Waterbottle", 0, 10, 0, 40),
};
 

Как-то так. Теперь скрипт который лежит на объектах сцены.
Синтаксис:
Используется csharp
public class FoodScript : MonoBehaviour //Типа скрипт который весит на объекте сцены и является носителем локальных динамичных переменных
{
    public int ID;

    public float NowHunger = DataBaseFoods[ID].MaxHunger;
    public float NowThirst = DataBaseFoods[ID].MaxThirst;
}
 

Ну и типа когда кушаем, еда тратится и восполняет нам значения, когда она закончится можем её уничтожить, либо в самой игре обыграть как-нибудь, например как использование в виде сырья (крафт).
Общую картину описал. А теперь вопрос, можно ли избежать повторений ненужных переменных? Ладно для компуктера - ок, но человеку же не так удобно с эти всем работать. Да, конечно есть вариант с базой данных через XML, но не является ли это некими костылями?
Если что, я опираюсь на игру DayZSA, у игры система спрятана от чужих глаз, но мне очень нравится насколько там все выглядит гибким для настроек, типа вот тебе и предмет, который является как инструментом, так и оружием, и возможным сырьем (это моё воображение, возможно там не так, но в общем предметы имеют не просто один точный класс (тип), будто какая-то крутецкая модульная система).
Могу рассказать как я пытался реализовать сам такую систему, но все провалилось из-за проблем с реализацией функций объектов, да и ошибок там, наверно, много (особенно с оптимизацией).
KoteKotovK
UNITрон
 
Сообщения: 267
Зарегистрирован: 20 июн 2014, 06:41

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение Anonymyx 28 окт 2017, 13:14

Вы наверное неверно строите архитектуру.
Используйте наследование.
Есть базовый абстрактный класс, типа Item, там переменные только общие для всех вещей, ID и тип допустим... От него наследуются уже все остальные классы. .
Есть абстрактный класс Food, наследуется от Item, у него есть виртуальный метод, Eat И свои переменные общие для всей жратвы. У этого класса в свою очередь еще наследники - одноразовая еда, многоразовая еда. у них метод Eat переопределен, т.е. у каждого своя реализация.

Так же можно использовать интерфейсы. IEatable, допустим. И сделать пару классов для разных типов еды со своими переменными, и реализовать свой метод Eat для каждой еды.
В классе игрока вообще не должно быть ничего про еду.
Аватара пользователя
Anonymyx
Адепт
 
Сообщения: 1973
Зарегистрирован: 05 апр 2015, 15:55

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение KoteKotovK 28 окт 2017, 13:21

Anonymyx писал(а):Вы наверное неверно строите архитектуру.
Используйте наследование.
Есть базовый абстрактный класс, типа Item, там переменные только общие для всех вещей, ID и тип допустим... От него наследуются уже все остальные классы. .
Есть абстрактный класс Food, наследуется от Item, у него есть виртуальный метод, Eat И свои переменные общие для всей жратвы. У этого класса в свою очередь еще наследники - одноразовая еда, многоразовая еда. у них метод Eat переопределен, т.е. у каждого своя реализация.

Так же можно использовать интерфейсы. IEatable, допустим. И сделать пару классов для разных типов еды со своими переменными, и реализовать свой метод Eat для каждой еды.

Если говорить грубей, что-то на подобии группа-подгруппа-подгруппа подгруппы и т.д. Кучка разных разделяющих типов и баз данных для них. Да, я вас вполне понял, уже так и хотел начать делать, но вот я боялся нагромождения переменных и массивов, но ничего, буду подключать XML для полного удобства.
KoteKotovK
UNITрон
 
Сообщения: 267
Зарегистрирован: 20 июн 2014, 06:41

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение Anonymyx 28 окт 2017, 13:30

Ну, наверное... Можно и не разделять, так как все хранится как Item и у него есть ID, по ID получаем вещь, неважно какая она.

Т.е. в инвентаре у нас все хранится как Item, у него есть интерфейс IInteractable. И когда мы жмем использовать этот предмет, вызывается метод Interact из интерфейса IInteractablе, который вызывает нужный метод, для еды - Eat, для аптечки - Heal, и т.д.

Это так, чтобы еще понятнее было...
Аватара пользователя
Anonymyx
Адепт
 
Сообщения: 1973
Зарегистрирован: 05 апр 2015, 15:55

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение KoteKotovK 28 окт 2017, 13:38

Anonymyx писал(а):Ну, наверное... Можно и не разделять, так как все хранится как Item и у него есть ID, по ID получаем вещь, неважно какая она.

Т.е. в инвентаре у нас все хранится как Item, у него есть интерфейс IInteractable. И когда мы жмем использовать этот предмет, вызывается метод Interact из интерфейса IInteractablе, который вызывает нужный метод, для еды - Eat, для аптечки - Heal, и т.д.

Это так, чтобы еще понятнее было...

=)
Отличие в том что уровень проработки должен быть глубже. Объект необязательно должен быть присвоен к одному типу, можно будет подключить к нему, как модуль, и другие типы. Структура такой систему очень сложна, нужно будет много чего продумать, но теперь буду придерживаться именно этого направления. Если напишу эту систему, скину её сюда же, может кому пригодится.
KoteKotovK
UNITрон
 
Сообщения: 267
Зарегистрирован: 20 июн 2014, 06:41

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение Anonymyx 28 окт 2017, 17:31

Видимо я неверно понял чего вы хотите...
Но все ровно как-то мудрено все у вас, лишние переменные в классе быть не должны.
Аватара пользователя
Anonymyx
Адепт
 
Сообщения: 1973
Зарегистрирован: 05 апр 2015, 15:55

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение KoteKotovK 29 окт 2017, 15:48

Anonymyx писал(а):Видимо я неверно понял чего вы хотите...
Но все ровно как-то мудрено все у вас, лишние переменные в классе быть не должны.

Да, я в общем тоже попал впросак.
Короче, идея такая. Представим что есть объект - "Монтировка", теоретически этому предмету присваивается класс "Инструмент", класс "Холодное оружие" ну и по возможности класс "Сырьё", ну и другие. У каждого класса свои переменные и функции, плюс ещё могут существовать подклассы, например не "Холодное оружие" и "Огнестрельное оружие", а класс "Оружие" и у него подклассы "Огнестрельное", "Холодное", ну и в таком темпе для удобства. Я же не могу придумать, как это все можно прописать. Если у вас есть на примете RPG игры с открытым исходным кодом, где можно что-нибудь подцепить для себя, то было бы круто, но в этом я не уверен.
Кстати, давненько играл в игрушку 7 Days To Die, там походу у каждого объекта просто свой единственный класс (Еда, холодное оружие, огнестрельное оружие и т.д.), а если переменные не используются, то и пофигу, они просто пустые и занимают место, а значения всех этих предметов прописываются в XML файле. Могу ошибаться, но что-то мне подсказывает что там такая себе система, просто все нагромождено в один скрипт, хотя возможно нет.
KoteKotovK
UNITрон
 
Сообщения: 267
Зарегистрирован: 20 июн 2014, 06:41

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение Anonymyx 29 окт 2017, 16:38

Мне кажется вам нужно использовать интерфейсы... У каждого будет своя реализация со своими полями...
Аватара пользователя
Anonymyx
Адепт
 
Сообщения: 1973
Зарегистрирован: 05 апр 2015, 15:55

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение KoteKotovK 29 окт 2017, 16:57

Anonymyx писал(а):Мне кажется вам нужно использовать интерфейсы... У каждого будет своя реализация со своими полями...

Блин, весело получается, недавно шерстил Unity документацию (обучающие материалы) и ведь немного не дошел до интерфейсов https://unity3d.com/ru/learn/tutorials/topics/scripting/interfaces?playlist=17117
А ведь это и вправду решает многие мои проблемы, спасибо вам за наводку!
KoteKotovK
UNITрон
 
Сообщения: 267
Зарегистрирован: 20 июн 2014, 06:41

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение KoteKotovK 29 окт 2017, 17:03

Ещё и Inheritance мне может помочь, короче остановил просмотр я не вовремя, попозже изучу всё что упустил, а то даже забыл про эти пункты.
KoteKotovK
UNITрон
 
Сообщения: 267
Зарегистрирован: 20 июн 2014, 06:41

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение Anonymyx 29 окт 2017, 17:22

Inheritance это наследование. Я вам про это сразу вначале говорил.
Аватара пользователя
Anonymyx
Адепт
 
Сообщения: 1973
Зарегистрирован: 05 апр 2015, 15:55

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение KoteKotovK 29 окт 2017, 18:14

Anonymyx писал(а):Inheritance это наследование. Я вам про это сразу вначале говорил.

Да, я вот не знал об этом (вообще не знал про наследование и другие штучки-дрючки, т.к я - быдлокодер), поэтому не получилось увидеть меж строк. Да и английский язык никак руки не дойдут изучить, чтобы хотя бы слова понимать, для этого ведь нужно много тренировок и повторений/закреплений, просто выучить (заучить наизусть) это все никак не получится, нужен опыт, как и везде в общем-то (да-да и программирование тоже никак не дойдут руки, и русский язык тоже, чертовы знаки препинания), а для получения опыта нужно время, в свою очередь его нету из-за навязанных систем ценностей нашего мира.
Что-то я разошёлся, но в общем это объясняет почему я такой неопытный в этой области. Просто чтобы вы не думали что я совсем какой-то дурачок. У всего есть свои причины, а вот доказать важность этих причин, это уже некое мастерство красноречия. Я же изучу все эти штучки, повторное вам спасибо за помощь.
KoteKotovK
UNITрон
 
Сообщения: 267
Зарегистрирован: 20 июн 2014, 06:41

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение KoteKotovK 01 ноя 2017, 09:21

Хорошо. Я изучил интерфейсы, абстрактные классы, наследственность классов и наследственность интерфейсов, но не могу понять как это можно использовать в моей системе. Если брать интерфейс, то мне всегда придется его получать через GetComponent? При чем самих видов интерфейсов будет не мало, дополнительно, функции у меня будут одинаковые, при интерфейсе мне придется каждый раз переписывать всю функцию. Есть идея писать всё через static функции, но что-то я пока не могу придумать как именно. Система наследственности через классы тоже не подходит, потому что мне могут понадобиться сопрограммы, типа coroutine (только MonoBehaviour). Эх, конечно сложно всё это разложить на бумаге так, чтобы было понятно, но вообщем мне нужны отдельные скрипты, где я могу использовать сопрограммы, и общие функции, чтобы их не повторять каждый раз. Вообщем, я думаю сделать многое через static, а если мне придется обращаться к функциям из другого скрипта (именно локальной функции, понятное дело не static), то я буду получать MonoBehaviour и вызывать из него Invoke или StartCoroutine.
KoteKotovK
UNITрон
 
Сообщения: 267
Зарегистрирован: 20 июн 2014, 06:41

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение samana 01 ноя 2017, 13:59

KoteKotovK писал(а):Объект необязательно должен быть присвоен к одному типу, можно будет подключить к нему, как модуль, и другие типы.


Вы можете попробовать следующее.
1) У вас будет класс Item, который определяет некий объект. Но свойств у этого объекта по-умолчанию нет, но их можно динамически добавлять. Для этого в классе Item создаёте список его свойств, который изначально пуст.

2) Все свойства - это отдельные классы, наследники базового абстрактного класса PropBase. Допустим есть классы для еды, воды и оружия:

Синтаксис:
Используется csharp
public abstract class PropBase
{
}

public class Food : PropBase
{
    public int health = 2;
}

public class Water : PropBase
{
    public int thirst = 5;
}

public class Armor : PropBase
{
    public int damage = 110;
    public int sharpness = 1;

    public int getDamage()
    {
        return damage * sharpness;
    }
}



А класс некого объекта Item выглядит как-то так. Он умеет добавлять в себя любые свойства, которые являются наследниками от PropBase:

Синтаксис:
Используется csharp
public class Item
{
    protected Dictionary<Type, PropBase> _props = new Dictionary<Type, PropBase>();

    public T addProp<T>() where T : PropBase, new()
    {
        _props.Add(typeof(T), new T());
        return _props[typeof(T)] as T;
    }

    public T getProp<T>() where T : PropBase
    {
        PropBase result;
        if (_props.TryGetValue(typeof(T), out result)) return _props[typeof(T)] as T;
        return null;
    }

}


---------------------------------------
Дальше вам достаточно просто создать экземпляр Item и добавить в него нужных вам свойств, например:

Синтаксис:
Используется csharp
// создаём объект
Item item = new Item();

// добавляем в него свойства еды и воды
item.addProp<Food>();
item.addProp<Water>();

// меняем свойство воды на ноль
item.getProp<Water>().thirst = 0;
// узнаём сколько еды осталось
Debug.Log(item.getProp<Food>().health);

// добавляем оружие и назначаем степень урона
item.addProp<Armor>().damage = 300;


Естественно вы можете добавить другие полезные методы в класс Item, например для удаление каких либо свойств или удобную проверку на отсутствие конкретного свойства.
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск

Re: Гибкая/модульная система базы данных для RPG(не RPG)

Сообщение KoteKotovK 01 ноя 2017, 16:43

samana, то что вы мне предлагаете и вправду очень круто, но не могли ли вы написать пример функций в такой системе? Я не до конца понимаю зачем первый класс является абстрактным, но у меня есть некая идея сделать реализацию функций. В первом, родительском классе, создаем виртуальный метод, у дочерних классов override этих методов, после чего спокойно вызываем этот метод. Далее, в этом методе, у меня идет проверка нажатия кнопок, а что я пишу то? Сделаю наглядный пример, того как я это вижу.
Синтаксис:
Используется csharp
public class PropBase
{
        public virtual void GeneralMethod(OtherScript Object){}
}

public class Food : PropBase
{
        public int recoverHungerValue = 5;

        public override void GeneralMethod(OtherScript Object)
        {
                if(Input.GetButtonDown("Fire1"))
                {
                        recoverHunger(Object);
                }
        }

        public void recoverHunger(OtherScript Object)
        {
                Player p = (Player)Object;
                p.hungerValue += recoverHungerValue;
        }
}
 

Есть ли смысл делать такую каляку? Как иначе можно обыграть функции? Вы там ещё использовали Generic, с ним я чот поплыл совсем)) Я то всё понял, но вот сам всё это не напишу с нуля, немного сложновато.
KoteKotovK
UNITрон
 
Сообщения: 267
Зарегистрирован: 20 июн 2014, 06:41

След.

Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 14