Менеджер способностей. Обработка данных.
В прошлой части я закончил на объявлении класса менеджера и абстрактного класса AbilityBihaviour.
В этой части я расскажу каким образом будут храниться и обрабатываться способности.
Но сначала вернусь к менеджеру и дополню его парой методов: AddAbility который будет добавлять способность, RemoveAbility
который будет удалять ненужную способность и UseAbility который будет использовать указанную способность - вроде все просто.
Синтаксис:
Используется csharp
[DisallowMultipleComponent]
public class SpellManager : MonoBehaviour {
public AbilityBihaviour objectSpellBihaviour { get; private set;}
protected virtual void Awake() {
this.objectSpellBihaviour = this.GetComponent<AbilityBihaviour>();
}
protected virtual void Start() {
}
public void AddAbility(AbilityObject ability) {
}
public void RemoveAbility(AbilityObject ability) {
}
public void UseAbility(AbilityObject ability) {
}
protected void SendAbilityEvent(SpellManagerData.AbilitySendEvent e, AbilityObject ability) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), ability, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.AbilitySendEvent.OnAbilityAdded: this.objectSpellBihaviour.OnAbilityAdded(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityRemoved: this.objectSpellBihaviour.OnAbilityRemoved(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityUsed: this.objectSpellBihaviour.OnAbilityUsed(ability);
break;
}
}
}
}
public class SpellManager : MonoBehaviour {
public AbilityBihaviour objectSpellBihaviour { get; private set;}
protected virtual void Awake() {
this.objectSpellBihaviour = this.GetComponent<AbilityBihaviour>();
}
protected virtual void Start() {
}
public void AddAbility(AbilityObject ability) {
}
public void RemoveAbility(AbilityObject ability) {
}
public void UseAbility(AbilityObject ability) {
}
protected void SendAbilityEvent(SpellManagerData.AbilitySendEvent e, AbilityObject ability) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), ability, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.AbilitySendEvent.OnAbilityAdded: this.objectSpellBihaviour.OnAbilityAdded(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityRemoved: this.objectSpellBihaviour.OnAbilityRemoved(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityUsed: this.objectSpellBihaviour.OnAbilityUsed(ability);
break;
}
}
}
}
Готово. Пока что эти методы будут пустыми пока мы не разберемся какие действия мы хотим в них добавить.
Вернемся опять к теории, и начнем с способностей.
В моем приложении у объектов могут быть разные способности но также они могут и обладать идентичными способностями, тоесть
допустим я создал способность и раздал всем объектам ее ссылку, теперь получается все объекты имеют ссылку на одну и туже
способность, а значит если хоть один объект решит что то исправить в этой способности - то эти исправления каснутся всех
других объектов, следовательно мне нужно как то обезопасить способность от изменений со стороны объектов что их хранит. И тогда
я решил написать некую обертку, эта обертка будет хранить в себе способность, точнее ссылку на нее, как абсолютное свойство
(readonly) это свойство нельзя будет изменить - оно будет предназначено только для чтения. Но т к существует всего два вида
способностей и они довольно таки сильно отличаются мне придется также создать две отдельные обертки для каждого вида.
И я начал с объявления базового класса - обертки, теперь перейдем к програмной части, создадим класс AbilityData, с, пока
что, одним свойством и защищенным конструктором.
Синтаксис:
Используется csharp
public class AbilityData {
public readonly AbilityObject ability = null;
protected AbilityData(AbilityObject ability) {
this.ability = ability;
}
}
public readonly AbilityObject ability = null;
protected AbilityData(AbilityObject ability) {
this.ability = ability;
}
}
Теперь нужно унаследовать два типа класса - обертки для каждого типа способности.
Я назвал эти классы ActiveAbilityData и PassiveAbilityData
Синтаксис:
Используется csharp
public sealed class PassiveAbilityData : AbilityData {
public PassiveAbilityData(PassiveAbility ability) : base(ability) {}
public new PassiveAbility ability {
get { return base.ability as PassiveAbility;}
}
}
public sealed class ActiveAbilityData : AbilityData {
public ActiveAbilityData(ActiveAbility ability) : base(ability) {}
public new ActiveAbility ability {
get { return base.ability as ActiveAbility;}
}
}
public PassiveAbilityData(PassiveAbility ability) : base(ability) {}
public new PassiveAbility ability {
get { return base.ability as PassiveAbility;}
}
}
public sealed class ActiveAbilityData : AbilityData {
public ActiveAbilityData(ActiveAbility ability) : base(ability) {}
public new ActiveAbility ability {
get { return base.ability as ActiveAbility;}
}
}
Как видите я сделал эти классы запечатанными(sealed) и также объявил новое(new) свойство ability, т к у базового класса уже
есть свойство ability оно вернет только общий тип способности AbilityObject, а унаследовавщиеся классы уже могут вернуть
мне способность определенного типа что я и сделал в этих новых свойствах.
Готово. Теперь у нас есть обертки которые будут хранить неизменяемую переменную способности. Мы еще вернемся к этим обертками
т к их нужно будет наполнить еще несколькими свойствами, в особенности ту что хранит активную способность.
Теперь можно возвращаться опять к менеджеру и создать в нем список(массив) этих оберток который будет хранить в себе
способности.
По ходу работы, класс менеджера будет увеличивать и увеличиваться в размерах, поэтому я создал отдельный класс как локальную
базу данных где я мог бы хранить именно данные(способности, списки и тд), а обрабатывать эти данные уже в самом менеджере.
Поэтому давайте создадим такой класс который бы хранил данные менеджера, я назвал такой класс AbilitiesManagerData
Синтаксис:
Используется csharp
public sealed class AbilitiesManagerData {
}
}
Теперь в нем давайте создадим наш список в котором будем хранить способности.
Синтаксис:
Используется csharp
public sealed class AbilitiesManagerData {
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
}
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
}
Как видите это не простой список - это список типа Dictionary который хранит данные в виде <ключ, данные>, я использовал
именно такого вида список потому что им легче оперировать имея разные ключи. Ключами у нас будут выступать типы способностей
- их всего два: активная и пассивная, а значениями будут списки где уже будут храниться способности.
Теперь объявим в этом классе конструктор
Синтаксис:
Используется csharp
public sealed class AbilitiesManagerData {
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
В конструкторе я сначала инициализирую список, потом под каждый ключ создаю список способностей.
Готово теперь объявим переменную этого класса в самом менеджере.
Синтаксис:
Используется csharp
[DisallowMultipleComponent]
public class SpellManager : MonoBehaviour {
public AbilityBihaviour objectSpellBihaviour { get; private set;}
protected AbilitiesManagerData data { get; private set;}
protected virtual void Awake() {
this.objectSpellBihaviour = this.GetComponent<AbilityBihaviour>();
this.data = new AbilitiesManagerData();
}
protected virtual void Start() {
}
public void AddAbility(AbilityObject ability) {
}
public void RemoveAbility(AbilityObject ability) {
}
public void UseAbility(AbilityObject ability) {
}
protected void SendAbilityEvent(SpellManagerData.AbilitySendEvent e, AbilityObject ability) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), ability, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.AbilitySendEvent.OnAbilityAdded: this.objectSpellBihaviour.OnAbilityAdded(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityRemoved: this.objectSpellBihaviour.OnAbilityRemoved(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityUsed: this.objectSpellBihaviour.OnAbilityUsed(ability);
break;
}
}
}
}
public class SpellManager : MonoBehaviour {
public AbilityBihaviour objectSpellBihaviour { get; private set;}
protected AbilitiesManagerData data { get; private set;}
protected virtual void Awake() {
this.objectSpellBihaviour = this.GetComponent<AbilityBihaviour>();
this.data = new AbilitiesManagerData();
}
protected virtual void Start() {
}
public void AddAbility(AbilityObject ability) {
}
public void RemoveAbility(AbilityObject ability) {
}
public void UseAbility(AbilityObject ability) {
}
protected void SendAbilityEvent(SpellManagerData.AbilitySendEvent e, AbilityObject ability) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), ability, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.AbilitySendEvent.OnAbilityAdded: this.objectSpellBihaviour.OnAbilityAdded(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityRemoved: this.objectSpellBihaviour.OnAbilityRemoved(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityUsed: this.objectSpellBihaviour.OnAbilityUsed(ability);
break;
}
}
}
}
Я сделал свойство data защищенного типа т к ни в коем случае НЕЛЬЗЯ допустить чтобы объект мог получить доступ к способности
вне менеджера, иначе отсюда начнут расти проблемы с нечестным использованием системы способностей.
Как вы видите я сделал список в классе AbilitiesManagerData приватным чтобы опять же не допустить вывод данных вне области
работ менеджера, но все же прочитать эти данные возможность будет.
Допустим если я хочу узнать сколько вообще способностей у объекта или есть ли у него определенная способность или нет, или
вообще как я смогу рисовать иконку способности если это свойство закрыто. Для этого мне нужно вернуть список способностей.
Но все способности закрыты под ключом, и мало того они еще все находятся в виде базового класса AbilityData, и выходом из
этой ситуации стал НУМЕРОВАННЫЙ список точнее список типа IEnumerable который будет возвращать мне список объектов того вида
которого я захочу - опять же здесь мы имеем дело с преобразованием.
И так как это будет выглядеть в классе AbilitiesManagerData
Синтаксис:
Используется csharp
public sealed class AbilitiesManagerData {
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
Хоть это
Синтаксис:
Используется csharp
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
может и показаться сложным для понимая новичкам на самом делел здесь заложен простой принцип.
Ведь на самом деле такая запись практически равносильна записи такого вида
Синтаксис:
Используется csharp
public PassiveAbilityData[] passiveAbilities {
get {
return this.abilities[AbilitySettings.AbilityType.Passive].Select(d => d as PassiveAbilityData).ToArray();
}
}
get {
return this.abilities[AbilitySettings.AbilityType.Passive].Select(d => d as PassiveAbilityData).ToArray();
}
}
или более понятной
Синтаксис:
Используется csharp
public List<PassiveAbilityData> passiveAbilities {
get {
List<PassiveAbilityData> list = new List<PassiveAbilityData>();
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
list.Add(data as PassiveAbilityData);
return list;
}
}
get {
List<PassiveAbilityData> list = new List<PassiveAbilityData>();
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
list.Add(data as PassiveAbilityData);
return list;
}
}
Все эти три записи по функционалу похожи, но в первом варианте главную задачу выполняет yeild - инструкция.
Дело в том что когда вы используете цикл типа foreach обычно мы заранее уже имеем список(массив) по которому будет проходить
цикл - тоесть список(массив) уже заранее определен, в случае же с yeild мы также получаем массив на выходе но пока цикл
перебирает элемент за елементом мы можем выполнять какието действия с этим елементом не в самом цикле а сразу в массиве, это
очень полезная вещь на самом деле. И если хотите с ней лучше разобраться то рекомендую вот это видео из youtube.
Видео
Ну а мы движемся дальше.
Как вы помните активная способность имеет кнопку на которую нажав мы можем ее активировать через всем известный Input, а
значит нам нужно подключить метод Update в менеджере где мы будет обрабатывать нажатия на клавииши.
Синтаксис:
Используется csharp
[DisallowMultipleComponent]
public class SpellManager : MonoBehaviour {
public AbilityBihaviour objectSpellBihaviour { get; private set;}
protected AbilitiesManagerData data { get; private set;}
protected virtual void Awake() {
this.objectSpellBihaviour = this.GetComponent<AbilityBihaviour>();
this.data = new AbilitiesManagerData();
}
protected virtual void Start() {
}
protected virtual void Update() {
}
public void AddAbility(AbilityObject ability) {
}
public void RemoveAbility(AbilityObject ability) {
}
public void UseAbility(AbilityObject ability) {
}
protected void SendAbilityEvent(SpellManagerData.AbilitySendEvent e, AbilityObject ability) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), ability, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.AbilitySendEvent.OnAbilityAdded: this.objectSpellBihaviour.OnAbilityAdded(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityRemoved: this.objectSpellBihaviour.OnAbilityRemoved(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityUsed: this.objectSpellBihaviour.OnAbilityUsed(ability);
break;
}
}
}
}
public class SpellManager : MonoBehaviour {
public AbilityBihaviour objectSpellBihaviour { get; private set;}
protected AbilitiesManagerData data { get; private set;}
protected virtual void Awake() {
this.objectSpellBihaviour = this.GetComponent<AbilityBihaviour>();
this.data = new AbilitiesManagerData();
}
protected virtual void Start() {
}
protected virtual void Update() {
}
public void AddAbility(AbilityObject ability) {
}
public void RemoveAbility(AbilityObject ability) {
}
public void UseAbility(AbilityObject ability) {
}
protected void SendAbilityEvent(SpellManagerData.AbilitySendEvent e, AbilityObject ability) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), ability, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.AbilitySendEvent.OnAbilityAdded: this.objectSpellBihaviour.OnAbilityAdded(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityRemoved: this.objectSpellBihaviour.OnAbilityRemoved(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityUsed: this.objectSpellBihaviour.OnAbilityUsed(ability);
break;
}
}
}
}
Я сделал метод Update тоже виртуальным чтобы будущие наследующиеся классы могли перегрузить его.
Теперь пройдемся циклом по списку активных способностей чтобы знать какую способность мы активировали.
Синтаксис:
Используется csharp
protected virtual void Update() {
foreach(ActiveAbilityData data in this.data.activeAbilities) {
if (Input.GetKeyUp(data.ability.castKey)) {
Debug.Log("User used: " + data.ability.name);
return;
}
}
}
foreach(ActiveAbilityData data in this.data.activeAbilities) {
if (Input.GetKeyUp(data.ability.castKey)) {
Debug.Log("User used: " + data.ability.name);
return;
}
}
}
Готово теперь при нажатии определенной кнопки мы будет знать какая способность сработала.
Теперь давайте рассмотрим работу метода AddAbility который должен добавлять новые способности в менеджер.
Как я упоминал в прошлой части при добавлении разного типа способностей мы имеем не много разную реализацию метода AddAbility
Давайте наполним этот метод некоторыми действиями
Синтаксис:
Используется csharp
public void AddAbility(AbilityObject ability) {
AbilityData data = null;
if (ability.type == AbilitySettings.AbilityType.Active)
data = new ActiveAbilityData(ability as ActiveAbility);
else
data = new PassiveAbilityData(ability as PassiveAbility);
this.data.AddAbilityData(data);
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityAdded, ability);
}
AbilityData data = null;
if (ability.type == AbilitySettings.AbilityType.Active)
data = new ActiveAbilityData(ability as ActiveAbility);
else
data = new PassiveAbilityData(ability as PassiveAbility);
this.data.AddAbilityData(data);
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityAdded, ability);
}
Рассмотрим поближе: мы вызываем метод AddAbility и передаем в его параметры способность которую хотим добавить в менеджер, но
сначала нам нужно создать обертку для этой способности, поэтому я объявляю переменную стандартной обертки AbilityData а
дальше в зависимости от того какой тип способности присваиваю этой переменной определенный тип обертки, дальше я добавляю
через метод AddAbilityData класса AbilitiesManagerData обертку со способностью, и вызываю событие что способность была
добавлена. Вроде все просто. Теперь нужно в классе AbilitiesManagerData объявить метод AddAbilityData.
Синтаксис:
Используется csharp
public sealed class AbilitiesManagerData {
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
В этом методе(AddAbilityData) я сначала проверяю: есть ли по данному ключу уже такая обертка и если их нет то добавляю новую.
Но раз у нас есть метод который добавляет данные нужен тогда и метод который будет удалять эти данные.
Поэтому объявим еще метод RemoveAbilityData который будет удалять данные из списка.
Синтаксис:
Используется csharp
public sealed class AbilitiesManagerData {
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public void RemoveAbilityData(AbilityData data) {
for(int index = 0; index < this.abilities[data.ability.type].Count; index++) {
if (this.abilities[data.ability.type][index] == data) {
this.abilities[data.ability.type].RemoveAt(index);
return;
}
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public void RemoveAbilityData(AbilityData data) {
for(int index = 0; index < this.abilities[data.ability.type].Count; index++) {
if (this.abilities[data.ability.type][index] == data) {
this.abilities[data.ability.type].RemoveAt(index);
return;
}
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
Теперь мы можем также и удалить данные, данные к которым нет доступа - ага, значит нужно этот доступ както получить. Раз у
меня всегда есть ссылка на способность то я смогу и найти по этой ссылке данные(обертку) в которых эта способность находится.
Сделал я это через метод FindAbilityData
Синтаксис:
Используется csharp
public sealed class AbilitiesManagerData {
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public AbilityData FindAbilityData(AbilityObject ability) {
return this.abilities[ability.type].FirstOrDefault(d => d.ability == ability);
}
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public void RemoveAbilityData(AbilityData data) {
for(int index = 0; index < this.abilities[data.ability.type].Count; index++) {
if (this.abilities[data.ability.type][index] == data) {
this.abilities[data.ability.type].RemoveAt(index);
return;
}
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public AbilityData FindAbilityData(AbilityObject ability) {
return this.abilities[ability.type].FirstOrDefault(d => d.ability == ability);
}
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public void RemoveAbilityData(AbilityData data) {
for(int index = 0; index < this.abilities[data.ability.type].Count; index++) {
if (this.abilities[data.ability.type][index] == data) {
this.abilities[data.ability.type].RemoveAt(index);
return;
}
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
Этот метод(FindAbilityData) ищет данные по способности.
Также мне тогда придется добавить метод через который я бы мог убедиться через менеджер что у него уже есть такая
способность. Я сделал это через метод AbilityExists
Синтаксис:
Используется csharp
public sealed class AbilitiesManagerData {
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public bool AbilityExists(AbilityObject ability) {
return this.abilities[ability.type].Any(d => d.ability == ability);
}
public AbilityData FindAbilityData(AbilityObject ability) {
return this.abilities[ability.type].FirstOrDefault(d => d.ability == ability);
}
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public void RemoveAbilityData(AbilityData data) {
for(int index = 0; index < this.abilities[data.ability.type].Count; index++) {
if (this.abilities[data.ability.type][index] == data) {
this.abilities[data.ability.type].RemoveAt(index);
return;
}
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public bool AbilityExists(AbilityObject ability) {
return this.abilities[ability.type].Any(d => d.ability == ability);
}
public AbilityData FindAbilityData(AbilityObject ability) {
return this.abilities[ability.type].FirstOrDefault(d => d.ability == ability);
}
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public void RemoveAbilityData(AbilityData data) {
for(int index = 0; index < this.abilities[data.ability.type].Count; index++) {
if (this.abilities[data.ability.type][index] == data) {
this.abilities[data.ability.type].RemoveAt(index);
return;
}
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
Ну вот вроде весь функционал и готов для работы с данными способностей.
Вот конечный вариант класса AbilitiesManagerData
Синтаксис:
Используется csharp
public sealed class AbilitiesManagerData {
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public bool AbilityExists(AbilityObject ability) {
return this.abilities[ability.type].Any(d => d.ability == ability);
}
public AbilityData FindAbilityData(AbilityObject ability) {
return this.abilities[ability.type].FirstOrDefault(d => d.ability == ability);
}
public bool AbilityExists(string name) {
return FindAbility(name) != null;
}
public AbilityObject FindAbility(string name) {
AbilityData data = this.abilities[AbilitySettings.AbilityType.Active].FirstOrDefault(d => d.ability.name == name);
if (data == null)
data = this.abilities[AbilitySettings.AbilityType.Passive].FirstOrDefault(d => d.ability.name == name);
return data.ability;
}
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public void RemoveAbility(string name) {
this.RemoveAbility(FindAbility(name));
}
public void RemoveAbility(AbilityObject ability) {
this.RemoveAbilityData(this.abilities[ability.type].FirstOrDefault(d => d.ability == ability));
}
public void RemoveAbilityData(AbilityData data) {
for(int index = 0; index < this.abilities[data.ability.type].Count; index++) {
if (this.abilities[data.ability.type][index] == data) {
this.abilities[data.ability.type].RemoveAt(index);
return;
}
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
private readonly Dictionary<AbilitySettings.AbilityType, List<AbilityData>> abilities;
public bool AbilityExists(AbilityObject ability) {
return this.abilities[ability.type].Any(d => d.ability == ability);
}
public AbilityData FindAbilityData(AbilityObject ability) {
return this.abilities[ability.type].FirstOrDefault(d => d.ability == ability);
}
public bool AbilityExists(string name) {
return FindAbility(name) != null;
}
public AbilityObject FindAbility(string name) {
AbilityData data = this.abilities[AbilitySettings.AbilityType.Active].FirstOrDefault(d => d.ability.name == name);
if (data == null)
data = this.abilities[AbilitySettings.AbilityType.Passive].FirstOrDefault(d => d.ability.name == name);
return data.ability;
}
public void AddAbilityData(AbilityData data) {
if (this.abilities[data.ability.type].Contains(data) == false) {
this.abilities[data.ability.type].Add(data);
}
}
public void RemoveAbility(string name) {
this.RemoveAbility(FindAbility(name));
}
public void RemoveAbility(AbilityObject ability) {
this.RemoveAbilityData(this.abilities[ability.type].FirstOrDefault(d => d.ability == ability));
}
public void RemoveAbilityData(AbilityData data) {
for(int index = 0; index < this.abilities[data.ability.type].Count; index++) {
if (this.abilities[data.ability.type][index] == data) {
this.abilities[data.ability.type].RemoveAt(index);
return;
}
}
}
public IEnumerable<ActiveAbilityData> activeAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Active])
yield return data as ActiveAbilityData;
}
}
public IEnumerable<PassiveAbilityData> passiveAbilities {
get {
foreach(AbilityData data in this.abilities[AbilitySettings.AbilityType.Passive])
yield return data as PassiveAbilityData;
}
}
public AbilitiesManagerData() {
this.abilities = new Dictionary<AbilitySettings.AbilityType, List<AbilityData>>();
this.abilities.Add(AbilitySettings.AbilityType.Active, new List<AbilityData>());
this.abilities.Add(AbilitySettings.AbilityType.Passive, new List<AbilityData>());
}
}
Теперь можно полностью посветить остальное время менеджеру и способностям.
Как я говорил в прошлой части, пассивная способность не имеет какой либо активации через кнопки или еще как, он активируется
сразу как только добавилась в менеджер. Но активная способность активируется уже с помощью нажатия на клавиши.
Я уже рассказывал что из себя представляет активация и какие действия она выполняет.
Как видно на картинке, активация в менеджере будет представлять собой метод который будет раскладывать способность на
компоненты и отсылать эти компоненты в компонент AbilityBihaviour и там уже пользователь дальше решит что с ними делать.
Но в компоненте AbilityBihaviour нет методов которые будут принимать эти компоненты, значит надо их объявить.
Как и в случае с посыланием сообщений о добавлении\удалении\использовании способности, мы также будем использовать
перечисление событий которые хотим отослать в AbilityBihaviour.
Я создал в статическом классе перечисление ComponentSendEvent
Синтаксис:
Используется csharp
public static class SpellManagerData {
public static SpellManager SpellManager(this GameObject gameObject) {
return gameObject.GetComponent<SpellManager>();
}
public enum AbilitySendEvent {
OnAbilityAdded,
OnAbilityUsed,
OnAbilityRemoved
}
public enum ComponentSendEvent {
OnComponentExpansion
}
}
public static SpellManager SpellManager(this GameObject gameObject) {
return gameObject.GetComponent<SpellManager>();
}
public enum AbilitySendEvent {
OnAbilityAdded,
OnAbilityUsed,
OnAbilityRemoved
}
public enum ComponentSendEvent {
OnComponentExpansion
}
}
Пока что там будет только одно перечисление OnComponentExpansion которое будет отправляться в случае когда менеджер будет
отправлять компонент при разложении.
Теперь нужно добавить метод SendComponentEvent в менеджер который будет отправлять сообщения вместе с компонентом.
Синтаксис:
Используется csharp
protected void SendComponentEvent(SpellManagerData.ComponentSendEvent e, AbilityComponent component) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), component, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.ComponentSendEvent.OnComponentExpansion: this.objectSpellBihaviour.OnComponentExpansion(component);
break;
}
}
}
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), component, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.ComponentSendEvent.OnComponentExpansion: this.objectSpellBihaviour.OnComponentExpansion(component);
break;
}
}
}
Опять же я проверяю здесь если менеджер имеет ссылку на AbilityBihaviour значит отослать сообщение на прямую иначе
использовать SendMessage. Теперь нужно объявить метод OnComponentExpansion в классе AbilityBihaviour.
Синтаксис:
Используется csharp
public abstract class AbilityBihaviour : MonoBehaviour {
private SpellManager objectManager = null;
public SpellManager spellManager {
get {
if (this.objectManager == null) {
this.objectManager = this.gameObject.GetComponent<SpellManager>();
if (this.objectManager == null) this.objectManager = this.gameObject.AddComponent<SpellManager>();
}
return this.objectManager;
}
}
public virtual void OnAbilityAdded(AbilityObject ability) {
Debug.Log("Character: " + this.name + " got new ability: " + ability.name);
}
public virtual void OnAbilityUsed(AbilityObject ability) {
Debug.Log("Character: " + this.name + " used ability: " + ability.name);
}
public virtual void OnAbilityRemoved(AbilityObject ability) {
Debug.Log("Character: " + this.name + " has removed ability: " + ability.name);
}
public abstract void OnComponentExpansion(AbilityComponent component);
}
private SpellManager objectManager = null;
public SpellManager spellManager {
get {
if (this.objectManager == null) {
this.objectManager = this.gameObject.GetComponent<SpellManager>();
if (this.objectManager == null) this.objectManager = this.gameObject.AddComponent<SpellManager>();
}
return this.objectManager;
}
}
public virtual void OnAbilityAdded(AbilityObject ability) {
Debug.Log("Character: " + this.name + " got new ability: " + ability.name);
}
public virtual void OnAbilityUsed(AbilityObject ability) {
Debug.Log("Character: " + this.name + " used ability: " + ability.name);
}
public virtual void OnAbilityRemoved(AbilityObject ability) {
Debug.Log("Character: " + this.name + " has removed ability: " + ability.name);
}
public abstract void OnComponentExpansion(AbilityComponent component);
}
А вот теперь как видите я объявил метод OnComponentExpansion абстрактным т к если в случае с получение сообщений о
способностях мы сделали их виртуальными чтобы каждый раз не перегружать изза очень редкого их использования, то этот метод я
обязательно буду перегружать т к в этом случае пользователь уже должен будет сам решать что делать со значениями компонента.
Готово. Теперь мы можем, при разложении способности на компоненты, отослать любой компонент с помощью метода
SendComponentEvent.
Теперь нужно заняться самим методом разложения(активации).
Вернемся к менеджеру.
Активация будет представлять собой корутину InitializeAbility в которой будет происходить активация способности.
Давайте создадим ее пустой для начала.
Синтаксис:
Используется csharp
private IEnumerator InitializeAbility(AbilityData data) {
yeild break;
}
yeild break;
}
Как видите она берет параметр AbilityData - тоесть не способность на прямую а обертку в которой она находится.
Теперь когда мы добавим пассивную способность в методе AddAbility мы сразу же передадим ее на активацию.
Синтаксис:
Используется csharp
public void AddAbility(AbilityObject ability) {
if (this.data.AbilityExists(ability)) return;
AbilityData data = null;
if (ability.type == AbilitySettings.AbilityType.Active)
data = new ActiveAbilityData(ability as ActiveAbility);
else
data = new PassiveAbilityData(ability as PassiveAbility);
this.data.AddAbilityData(data);
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityAdded, ability);
if (ability.type == AbilitySettings.AbilityType.Passive)
UseAbility(data);
}
if (this.data.AbilityExists(ability)) return;
AbilityData data = null;
if (ability.type == AbilitySettings.AbilityType.Active)
data = new ActiveAbilityData(ability as ActiveAbility);
else
data = new PassiveAbilityData(ability as PassiveAbility);
this.data.AddAbilityData(data);
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityAdded, ability);
if (ability.type == AbilitySettings.AbilityType.Passive)
UseAbility(data);
}
Как видите в самом конце метода AddAbility я передаю данные(обертку) способности в метод UseAbility который будет отсылать
сообщения о том что мы использовали способность и запустит корутину активации.
Синтаксис:
Используется csharp
private void UseAbility(AbilityData data) {
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityUsed, data.ability);
this.StartCoroutine(InitializeAbility(data));
}
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityUsed, data.ability);
this.StartCoroutine(InitializeAbility(data));
}
Готово. Теперь опять вернемся к методу активации, и рассмотрим ее действия.
Синтаксис:
Используется csharp
private IEnumerator InitializeAbility(AbilityData data) {
IAbilityComponentable compSys = data.ability as IAbilityComponentable;
if (compSys == null) yield break;
foreach(AbilityComponent component in compSys.components) {
SendComponentEvent(SpellManagerData.ComponentSendEvent.OnComponentExpansion, component);
yield return new WaitForFixedUpdate();
}
}
IAbilityComponentable compSys = data.ability as IAbilityComponentable;
if (compSys == null) yield break;
foreach(AbilityComponent component in compSys.components) {
SendComponentEvent(SpellManagerData.ComponentSendEvent.OnComponentExpansion, component);
yield return new WaitForFixedUpdate();
}
}
Сначала мне нужно узнать есть ли вообще у этой способности компоненты, это я делаю с помощью интерфейса
IAbilityComponentable, далее проверяю если у способности нет компонентов то завершаю корутина на этом этапе т к слать нечего.
Иначе я с помощью цикла перебираю все компоненты в способности и с помощью метода SendComponentEvent отсылаю ее дальше
объектам.
Готово. Теперь у нас есть базовые представления о том как менеджер будет справляться со способностями: как их сохранять
\удалять и активировать. Думаю для этой части хватит. Вот как выглядит класс менеджера в этой части статьи.
Синтаксис:
Используется csharp
[DisallowMultipleComponent]
public class SpellManager : MonoBehaviour {
public AbilityBihaviour objectSpellBihaviour { get; private set;}
protected AbilitiesManagerData data { get; private set;}
protected virtual void Awake() {
this.objectSpellBihaviour = this.GetComponent<AbilityBihaviour>();
this.data = new AbilitiesManagerData();
}
protected virtual void Start() {
}
protected virtual void Update() {
foreach(ActiveAbilityData data in this.data.activeAbilities) {
if (Input.GetKeyUp(data.ability.castKey)) {
Debug.Log("User used: " + data.ability.name);
return;
}
}
}
public void AddAbility(AbilityObject ability) {
if (this.data.AbilityExists(ability)) return;
AbilityData data = null;
if (ability.type == AbilitySettings.AbilityType.Active)
data = new ActiveAbilityData(ability as ActiveAbility);
else
data = new PassiveAbilityData(ability as PassiveAbility);
this.data.AddAbilityData(data);
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityAdded, ability);
if (ability.type == AbilitySettings.AbilityType.Passive)
UseAbility(data);
}
public void RemoveAbility(AbilityObject ability) {
}
public void UseAbility(AbilityObject ability) {
}
private void UseAbility(AbilityData data) {
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityUsed, data.ability);
this.StartCoroutine(InitializeAbility(data));
}
private IEnumerator InitializeAbility(AbilityData data) {
IAbilityComponentable compSys = data.ability as IAbilityComponentable;
if (compSys == null) yield break;
foreach(AbilityComponent component in compSys.components) {
SendComponentEvent(SpellManagerData.ComponentSendEvent.OnComponentExpansion, component);
yield return new WaitForFixedUpdate();
}
}
protected void SendAbilityEvent(SpellManagerData.AbilitySendEvent e, AbilityObject ability) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), ability, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.AbilitySendEvent.OnAbilityAdded: this.objectSpellBihaviour.OnAbilityAdded(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityRemoved: this.objectSpellBihaviour.OnAbilityRemoved(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityUsed: this.objectSpellBihaviour.OnAbilityUsed(ability);
break;
}
}
}
protected void SendComponentEvent(SpellManagerData.ComponentSendEvent e, AbilityComponent component) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), component, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.ComponentSendEvent.OnComponentExpansion: this.objectSpellBihaviour.OnComponentExpansion(component);
break;
}
}
}
}
public class SpellManager : MonoBehaviour {
public AbilityBihaviour objectSpellBihaviour { get; private set;}
protected AbilitiesManagerData data { get; private set;}
protected virtual void Awake() {
this.objectSpellBihaviour = this.GetComponent<AbilityBihaviour>();
this.data = new AbilitiesManagerData();
}
protected virtual void Start() {
}
protected virtual void Update() {
foreach(ActiveAbilityData data in this.data.activeAbilities) {
if (Input.GetKeyUp(data.ability.castKey)) {
Debug.Log("User used: " + data.ability.name);
return;
}
}
}
public void AddAbility(AbilityObject ability) {
if (this.data.AbilityExists(ability)) return;
AbilityData data = null;
if (ability.type == AbilitySettings.AbilityType.Active)
data = new ActiveAbilityData(ability as ActiveAbility);
else
data = new PassiveAbilityData(ability as PassiveAbility);
this.data.AddAbilityData(data);
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityAdded, ability);
if (ability.type == AbilitySettings.AbilityType.Passive)
UseAbility(data);
}
public void RemoveAbility(AbilityObject ability) {
}
public void UseAbility(AbilityObject ability) {
}
private void UseAbility(AbilityData data) {
SendAbilityEvent(SpellManagerData.AbilitySendEvent.OnAbilityUsed, data.ability);
this.StartCoroutine(InitializeAbility(data));
}
private IEnumerator InitializeAbility(AbilityData data) {
IAbilityComponentable compSys = data.ability as IAbilityComponentable;
if (compSys == null) yield break;
foreach(AbilityComponent component in compSys.components) {
SendComponentEvent(SpellManagerData.ComponentSendEvent.OnComponentExpansion, component);
yield return new WaitForFixedUpdate();
}
}
protected void SendAbilityEvent(SpellManagerData.AbilitySendEvent e, AbilityObject ability) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), ability, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.AbilitySendEvent.OnAbilityAdded: this.objectSpellBihaviour.OnAbilityAdded(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityRemoved: this.objectSpellBihaviour.OnAbilityRemoved(ability);
break;
case SpellManagerData.AbilitySendEvent.OnAbilityUsed: this.objectSpellBihaviour.OnAbilityUsed(ability);
break;
}
}
}
protected void SendComponentEvent(SpellManagerData.ComponentSendEvent e, AbilityComponent component) {
if (this.objectSpellBihaviour == null) {
this.SendMessage(e.ToString(), component, SendMessageOptions.DontRequireReceiver);
} else {
switch(e) {
case SpellManagerData.ComponentSendEvent.OnComponentExpansion: this.objectSpellBihaviour.OnComponentExpansion(component);
break;
}
}
}
}
Заключение: теперь у нас есть рабочие методы менеджера через которые мы сможем в будущем добавлять\удалять и использовать
способности, конечно пока они не полностью рабочие т к эту часть я оставил на следующий раз, мы продолжим работать с этими компонентами а также разберемся с эффектами от способностей.
Следующая часть
автор: этот хрен, он же llka, он же lawsonilka