obsidian/笔记文件/2.笔记/Entitas——Attributes.md
2025-03-26 00:02:56 +08:00

5.5 KiB
Raw Blame History

#unity/日常积累

Attributes Entitas提供了各种属性在生成代码时提供特殊功能。 代码生成器支持以下与类,接口和结构一起使用的属性:

[Context] 将组件添加到指定的Context,如果没有指定则会添加到默认Context中Jenny 设置面板中定义的第一个Context。 例:

[Game]
public class ViewComponent : IComponent
{
    public GameObject gameObject;
}

将View组件添加到Game Context中生成代码后会在Generated/Game/Components文件夹下生成GameViewComponent类。 允许同时指定多个Context名称。 如果用于Class或者Struct上首先会在Generated/Components生成 {classname}Component的组件然后同上 例:

[Game]
public class ContextView {
    public GameObject gameObject;
}

[Game]
public struct ContextData {
    public float value;
}

[Unique] 将组件指定为单例模式则每个Context中只存在唯一实例。 例:

[Unique]
public class UniqueTestComponent : IComponent
{
    public int value;
}

而单例组件的调用方式和其他组件也有所不同:

Contexts _contexts = Contexts.sharedInstance;
if (!_contexts.game.hasUniqueTest) {
    _contexts.game.SetUniqueTest(1);
}
Debug.Log(_contexts.game.uniqueTest.value);

[FlagPrefix] 只对标记组件有效(没有数据的组件)。对标记组件指定自定义前缀。 例:

[Game]
[FlagPrefix("Custom")]
public class FlagComponent : IComponent
{

}

[Game]
public class FlagTowComponent : IComponent
{

}

生成带之后Entity访问两种组件的方式

Contexts _contexts = Contexts.sharedInstance;
var entity = _contexts.game.CreateEntity();
//指定前缀
entity.customFlag = true;
//没有指定前缀则用默认前缀is
entity.isFlagTow = true;

[PrimaryEntityIndex] 在Context中添加索引器功能可以用于快速查找Entity。注意同一Context下每个Entity的值不能相同。 例:

[Game]
public class PrimaryEntityIndexTestComponent : IComponent
{
    [PrimaryEntityIndex]
    public string index;
}
_contexts.game.CreateEntity().AddPrimaryEntityIndexTest("a");
_contexts.game.CreateEntity().AddPrimaryEntityIndexTest("b");
var entity2 = _contexts.game.GetEntityWithPrimaryEntityIndexTest("a");

[EntityIndex] 这个属性的功能和[PrimaryEntityIndex]类似,区别在于[PrimaryEntityIndex]查找的是指定的值的唯一Entity而[EntityIndex]是查找具有指定值的多个Entity也就是多个Entity的[EntityIndex]的值可以是相同的。

[Game]
public class EntityIndexComponent : IComponent
{
    [EntityIndex]
    public string name; 
}
_contexts.game.CreateEntity().AddEntityIndex("c");
_contexts.game.CreateEntity().AddEntityIndex("c");
_contexts.game.GetEntitiesWithEntityIndex("c");

[CustomComponentName] 为组件自定义名称且定义几个名称则生成几个具有相同数据但名称不同的组件。 例:

[Game, ComponentName("Speed", "Position")]
public class FloatVector {
    public float x;
    public float y;
}

在Game Context下会生成GamePositionComponent组件和GameSpeedComponent组件且两个组件都具有xy两个值。

[DontGenerate] 生成代码时将跳过所有具有[DontGenerate]属性的组件。 例我们之前需要有移动的功能所以定义了一个MoveComponent,并生成了代码,之后我们又不需要这个功能了所以想将这个组件移除

[DontGenerate(false)]
public class CustomNameComponent
{
    public int value;
}

再只需加上[DontGenerate]然后重新生成则Entitas会移除所有与MoveComponent相关的代码。

[Event] 为组件生成数据改变的事件。 例我们需要监听某个Entity的位置变化

[Game, Event(EventTarget.Self)] public class PositionComponent : IComponent { public float x; public float y; }

public class GameView: Monobehaviour, IPositionListener { // 注册事件监听 public void RegisterListeners(Contexts contexts, GameEntity entity) { entity.AddGamePositionListener(this); }

// 事件回调响应函数 public void OnPosition(GameEntity entity, float x, float y) { transform.position = new Vector2(x,y); } }

public class GameController : MonoBehaviour { private static Systems CreateSystems(Contexts contexts) { return new Feature("Systems") .Add(new GameEventSystems(contexts)); } } } 当Entity更改的位置时生成的GameEventSystems将调用OnPosition(entity, x, y)的事件监听的回调。 参数:

EventTarget Any 任何Entity的Position发生变化都会调用OnPosition()。OnPosition()回调中第一个参数就是发生位置变化的Entity。 Self 仅自身的Position发生变化时才会调用OnPosition()。 EventType Added 生成IPositionListener。 Removed 生成IPositionRemovedListener当组件被移除时调用。 priority 生成的事件执行顺序同一个Context中存在多个事件时值越小优先级越高。 [Cleanup] 这个是只对AssetStore版本生效我使用的是Github版本所以没办法测试一下是官方文档翻译 当前有两种选择:

CleanupMode.DestroyEntity 将生成一个系统,该系统将销毁所有具有此组件的实体。 CleanupMode.RemoveComponent 将生成一个系统,该系统将从具有此组件的所有实体中删除此组件。 例:

[Cleanup(CleanupMode.DestroyEntity)]
public sealed class DestroyedComponent : IComponent {
}