-
Notifications
You must be signed in to change notification settings - Fork 77
(RU) Tags
Тэги - это целочисленные константы с удобной настройкой в редакторе Unity. Тэги чаще всего используются как фильтры в группах компонентов либо как маркеры, состояния для объекта.
Для использования тэгов создайте статичный класс. Я по умолчанию использую класс Tag.
public static class Tag
{
// регионами я разделяю для себя тэги различных групп. Так же я указываю индексы которые "резервирую" под эту группу тэгов.
#region Actions 0 - 1000
// TagField атрибут позволяет "видеть" эти тэги в инспекторе Unity
[TagField(categoryName = "Action")] public const int Hit = 0;
[TagField(categoryName = "Action")] public const int Stun = 1;
#endregion
}
Для того чтобы выбрать тэг из инспектора Unity используется атрибут [TagFilter(typeof(Tags))]
где typeof() указывает на класс в котором есть тэги. В нашем примере это класс Tags.
public class DemoTags : MonoBehaviour
{
// Используем тэг фильтр чтобы увидеть тэг.
[TagFilter(typeof(Tag))] public int tag;
}
Если вам нужен список тэгов то используйте массив TagNode[]
[System.Serializable]
public struct TagNode
{
[TagFilter(typeof(Tag))] public int tag;
}
public static partial class Game
{
public static int[] Convert(this TagNode[] tagNodes)
{
var tags = new int[tagNodes.Length];
for (int i = 0; i < tagNodes.Length; i++)
{
tags[i] = tagNodes[i].tag;
}
return tags;
}
}
Тэги работают как дополнительный фильтр у групп компонентов. Для этого используйте два атрибута над группой.
-
[GroupBy(params int[] filter)]
- указанные тэги должны быть у сущности. -
[GroupExclude(params int[] filter)]
- указанные тэги должны отсутствовать у сущности.
Пример - Есть обработчик выстрелов у героя. Обработка происходит в группе WantShoot состоящая из нужных для стрельбы компонентов. Однако мы не хотим чтобы эта группа работала если герой в прыжке, бьет в ближнем бою или перекатывается.
[GroupExclude(Tag.Jump, Tag.Melee, Tag.Roll)]
public Group<ComponentWeapon, ComponentPlayer, ComponentObject, ComponentView, ComponentMotion> groupWantShoot;
public void Tick()
{
var delta = Time.DeltaTime;
// want shoot
for (int i = 0; i < groupWantShoot.length; i++)
{
var cWeapon = groupWantShoot.component[i];
var cPlayer = groupWantShoot.component2[i];
var cObject = groupWantShoot.component3[i];
cWeapon.rate = Math.Max(0, cWeapon.rate -= delta);
if (cPlayer.source.GetButton(DataInputActions.Default.Fire))
{
if (cWeapon.clip == 0)
continue;
if (cWeapon.rate > 0)
continue;
Timing.RunCoroutine(cWeapon.current._Shoot(cObject.entity));
}
}
}
Нередко возникает ситуация когда мы хотим указать в исключении для групп некий компонент. Фреймворк поддерживает очень простую фильтрацию по компонентам: по наличию всех указанных. Однако мы можем решить эту задачу через атрибут компонента
TagRequire
.
Для этого я обычно создаю тэг маску для компонента и называю ее так же как компонент. После этого указываю ее в атрибуте как на примере ниже:
[TagRequire(Tag.ComponentInAir)]
public class ComponentInAir : IComponent
{
public float landingSpot = 0;
}
Каждый раз когда этот компонент будет добавлен сущности - тэг так же передастся. Тэг будет изъят у сущности вместе с ее уничтожением/отключением компонента.
Тэги хранятся в объекте Tags
, обращения к тэгам идут через методы расширения сущности.
// сущность с индексом 0
int entity = 0;
// проверка есть ли у сущность указанный тэг
entity.Has(Tag.Jump);
// проверка есть ли у сущность хотя бы один из указанных тэгов
entity.HasAny(Tag.Jump, Tag.Attack, Tag.Roll);
// добавить указанный тэг
entity.Set(Tag.Jump);
// удалить указанный тэг
entity.Remove(Tag.Jump);
// удалить полностью указанный тэг
entity.RemoveAll(Tag.Jump);
Однотипные тэги суммируются. Так, дважды добавив сущности Tag.Jump
и удалив один раз у нас все еще будет один Tag.Jump
у сущности. Имейте это в виду при составлении логики.