Использование словаря делегатов

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

Использование словаря делегатов

Сообщение Woland 11 май 2019, 12:38

Всем привет!

В игре в определенный момент я создаю NPC, в зависимости от его типа (строка) я добавляю на него компоненты. Сначала я не парился и сделал так:
Синтаксис:
Используется csharp
if (type == "map")
        {
            this.gameObject.AddComponent<NPCMap>();
        }
        if (type == "toFight")
        {
            this.gameObject.AddComponent<NPCToFightScene>();
        }
        if (type == "oldFights")
        {
            this.gameObject.AddComponent<NPCToOldFights>();
        }



Потом мне это надоело, решил использовать словарь делегатов

Синтаксис:
Используется csharp
_addComponents =new Dictionary<string, AddComponentsDelegate>
        {
            { "map", this.AddMapComponent },
            { "toFight", this.AddToFightComponent },
            { "oldFights", this.AddOldFightsComponent },
        };
       
.......

       _addComponents[type]();
 


Все работает прекрасно. но в какой-то момент получилась ситуация, что для одного типа НПЦ мне надо добавлять 2 компонента

Синтаксис:
Используется csharp
 _addComponents = new Dictionary<string, AddComponentsDelegate>
        {
            { "map", this.AddMapComponent },
            { "toFight", this.AddToFightComponent },
            { "oldFights", this.AddOldFightsComponent },
            { "dialog", this.AddMoveToMainCharacterComponent },
            { "dialog", this.AddTalkToMainCharacterComponent },
        };


Так не работает, естественно, ключевое значение "dialog" повторяется. Можно методы AddMoveToMainCharacterComponent и AddTalkToMainCharacterComponent вызывать из другого метода, например, AddDialogComponents, но тогда теряется вся гибкость.

Как лучше это реализовать? Спасибо!
Woland
Адепт
 
Сообщения: 1240
Зарегистрирован: 20 апр 2013, 18:09
  • Сайт

Re: Использование словаря делегатов

Сообщение 1max1 11 май 2019, 13:18

А если флагами добавлять?
Синтаксис:
Используется csharp
using UnityEngine;
using System;

[Flags]
enum Type
{
    Map       = 1,
    ToFight   = 2,
    OldFights = 4,
    Dialog    = 8
}

class Map       : MonoBehaviour { }
class ToFight   : MonoBehaviour { }
class OldFights : MonoBehaviour { }
class Dialog    : MonoBehaviour { }

class Test : MonoBehaviour
{
    void AddComponentForNPC(GameObject npc, Type type)
    {
        if (type.HasFlag(Type.Map))
            npc.AddComponent<Map>();

        if (type.HasFlag(Type.ToFight))
            npc.AddComponent<ToFight>();

        if (type.HasFlag(Type.OldFights))
            npc.AddComponent<OldFights>();

        if (type.HasFlag(Type.Dialog))
            npc.AddComponent<Dialog>();
    }

    void Start()
    {
        // Будут добавлены два компонента
        AddComponentForNPC(new GameObject(), Type.Dialog | Type.Map);
    }
}
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Использование словаря делегатов

Сообщение Woland 11 май 2019, 13:53

Хз, по сути тут так же получается много if else. Я как раз ищу сейчас решение без if, поэтому и стал копать в сторону делегатов.
Woland
Адепт
 
Сообщения: 1240
Зарегистрирован: 20 апр 2013, 18:09
  • Сайт

Re: Использование словаря делегатов

Сообщение 1max1 11 май 2019, 14:07

Что в этом плохого? У тебя же там их не пару сотен будет. Нет, ну можно и без if обойтись, только надо напрямую задавать имена компонентов:
Синтаксис:
Используется csharp
using UnityEngine;
using System;

class Map       : MonoBehaviour { }
class ToFight   : MonoBehaviour { }
class OldFights : MonoBehaviour { }
class Dialog    : MonoBehaviour { }

class Test : MonoBehaviour
{
    void AddComponentForNPC(GameObject npc, params Type[] types)
    {
        foreach (var type in types)
            npc.AddComponent(type);
    }

    void Start()
    {
        AddComponentForNPC(new GameObject(), typeof(Map), typeof(ToFight));
    }
}
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Использование словаря делегатов

Сообщение AngryCat 11 май 2019, 14:08

Woland писал(а):Хз, по сути тут так же получается много if else. Я как раз ищу сейчас решение без if, поэтому и стал копать в сторону делегатов.

что тебе if сделали?
Здесь могла бы быть ваша реклама.
Аватара пользователя
AngryCat
Старожил
 
Сообщения: 716
Зарегистрирован: 20 июл 2018, 22:29
Skype: Дискорд - Флеш#4099

Re: Использование словаря делегатов

Сообщение Woland 12 май 2019, 15:29

Да можно и с if все сделать) Я расцениваю это, как самообучение, узнаю для себя новые способы, кроме как все на ифах писать
Woland
Адепт
 
Сообщения: 1240
Зарегистрирован: 20 апр 2013, 18:09
  • Сайт

Re: Использование словаря делегатов

Сообщение AngryCat 12 май 2019, 18:29

Woland писал(а):Да можно и с if все сделать) Я расцениваю это, как самообучение, узнаю для себя новые способы, кроме как все на ифах писать
Раз для опыта, то можешь еще рефлексию копнуть, но много и часто я бы не рекомендовал ее использовать т.к она медленнее
Здесь могла бы быть ваша реклама.
Аватара пользователя
AngryCat
Старожил
 
Сообщения: 716
Зарегистрирован: 20 июл 2018, 22:29
Skype: Дискорд - Флеш#4099

Re: Использование словаря делегатов

Сообщение ~AvA~ 12 май 2019, 18:57

Ну, если нужно добавлять по одному компоненту, то можно было бы такое провернуть:
Назвать компоненты типами, которые будут анализироваться.. ну там map и соответствующий тип NPCmap.

Тогда можно было бы совсем без ифов: gameObject.AddComponent("NPC" + type);
Правда метод добавления компонента по строке - депрекейтнули (
Аватара пользователя
~AvA~
UNIверсал
 
Сообщения: 396
Зарегистрирован: 17 фев 2015, 13:09

Re: Использование словаря делегатов

Сообщение ~AvA~ 12 май 2019, 19:00

1max1 писал(а):Что в этом плохого? У тебя же там их не пару сотен будет. Нет, ну можно и без if обойтись, только надо напрямую задавать имена компонентов:
Синтаксис:
Используется csharp
using UnityEngine;
using System;

class Map       : MonoBehaviour { }
class ToFight   : MonoBehaviour { }
class OldFights : MonoBehaviour { }
class Dialog    : MonoBehaviour { }

class Test : MonoBehaviour
{
    void AddComponentForNPC(GameObject npc, params Type[] types)
    {
        foreach (var type in types)
            npc.AddComponent(type);
    }

    void Start()
    {
        AddComponentForNPC(new GameObject(), typeof(Map), typeof(ToFight));
    }
}

Такой вариант пишется проще, так как при создании GameObject можно сразу указать компоненты, чтобы добавились
Синтаксис:
Используется csharp
void Start()
    {
       var go = new GameObject("NPC", typeof(Map), typeof(ToFight));
    }
 

Но автору нужно добавлять компоненты к уже существующему объекту.. кажется)
Аватара пользователя
~AvA~
UNIверсал
 
Сообщения: 396
Зарегистрирован: 17 фев 2015, 13:09


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

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

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