Attributes - OneYoungMean/Entitas-CSharp-OYM GitHub Wiki

属性概述

代码生成器支持一下用于类,接口和结构的属性:

  • [Context]: 你可以使用这个属性让它仅在特定的上下文中可以被获取; e.g., [MyContextName], [Enemies], [UI], etc. 提高内存占用率。不仅如此,他还可以创建组件。
  • [Unique]: 代码生成器将会提供一个额外的方法,来确保最大仅有一个实体在这个组件上存在。
  • [FlagPrefix]: 这个属性可以给你的组件标记一个自定义的前缀。
  • [PrimaryEntityIndex]: 可以将实体固定为一个唯一的组件值。
  • [EntityIndex]: 可用于通过组件值寻找相对应的组件。
  • [CustomComponentName]: 生成多个名字不同的组件继承自同一个类或者同一个接口。
  • [DontGenerate]: 代码生成器将会跳过这个属性的组件。
  • [Event]: 代码生成器将会为反应式的UI 生成相应的组件,系统。接口。
  • [Cleanup]: 代码生成器将会生成一处组件或者删除组件。

[Context]上下文属性

你可以使用这个属性让它仅在特定的上下文中可以被获取; e.g., [MyContextName], [Enemies], [UI], etc. 提高内存占用率。不仅如此,他还可以创建组件。

上下文属性可以用于以下目的:

  • 添加组件到默认的上下文当中.
  • 添加组件到自定义的上下文当中.
  • 生成一个来自组件的class, interfacestruct.

当在一个class, interface 或者 struct中简单使用[Context]属性,代码生成器将会创造一个新的类并命名为你的"class名称"+"Component",然后将此添加到默认上下文当中。举个例子,如果您的类被调用,则将会调用Position生成的组件PositionComponent。

如果你希望使用自定义的上下文,你必须在Entitas首选项窗口定义它。创建自定义的上下文,比如'Enemies',代码生成器将会继承默认上下文的属性,以便您可以简单的使用 [Enemies]在你的class, interfacestruct作为自定义的上下文属性。你可以代码生成器的生成文件夹当中找到 {contextName}Attribute.cs,以查看当前已被自定义的上下文。

在Entitas首选项窗口中添加一些自定义的上下文,比如Game,GameState,Input等,然后单击 "Generate":

Entitas.Unity.CodeGeneration

然后,您现在可以在组件中使用新生成的上下文属性。 下面所有操作都是执行两个相同的操作:创建组件并将其添加到一个或者多个上下文当中。

using Entitas;
using Entitas.CodeGeneration;

[Game, Ui]
public class SceneComponent : IComponent
{
    public Scene Value;
}

[Game]
public class Bullet
{
    // Since it doesn't derive from 'IComponent'
    // it will be generated as 'BulletComponent'
}

[Meta]
public struct EditorOnlyVisual
{
    public bool ShowInMode;

    public EditorOnlyVisual(bool show) {
        this.ShowInMode = show;
    }
}

[Unique]独特属性

代码生成器将会提供一个额外的方法,来确保最大仅有一个实体在这个组件上存在。

将这个属性添加组件上可以确保仅有一个实例在你的应用中。对于你想要使用单例的情况,这是一个不错的代替方法。如果有多个实体在Component被找到,那么它将以下面的方式抛出异常。同时它将会为组件生成一下附加属性和方法:

  • Context.{ComponentName}Entity
  • Context.{ComponentName}.{ComponentProperty} (non-flag components)
  • Context.Set{ComponentName}({ComponentProperty}) (non-flag components)
  • Context.Replace{ComponentName}({ComponentProperty}) (non-flag components)
  • Context.Remove{ComponentName}() (non-flag components)
  • Context.has{ComponentName}() (non-flag components)

定义你的组件:

using Entitas;
using Entitas.CodeGeneration.Attributes;

[Core] // Context name
[Unique]
public class UserComponent : IComponent {
    public string name;
    public int age;
}

你现在可以使用以下属性和方法:

var context = Contexts.core;
var e = context.userEntity;
var name = context.user.name;
var has = context.hasUser;

context.SetUser("John", 42);
context.ReplaceUser("Max", 24);
context.RemoveUser();

[FlagPrefix]前缀属性

这个属性可以给你的组件标记一个自定义的前缀。

仅适用于充当标志的组件。标志组件是空类,因此是没有字段与行为填充布尔值的实体。如果在具有公共字段的组件当中使用此属性,他将会以静默的方式失败,且不会生成自定义前缀。

创建一个附带标签的组件:

using Entitas;
using Entitas.CodeGeneration;

[FlagPrefix("flag")]
public class DestroyComponent : IComponent {
}

代码生成器通常在没有这个属性时,会生成这种形式

entity.isDestroy = true;

如果添加了 [FlagPrefix] 属性:

entity.flagDestroy = true;

[PrimaryEntityIndex]原实体数属性

可以将实体固定为一个唯一的组件值。

在组件值上使用这个属性将会使得实体不会重复加载这个组件值,这将会使其他带有该组件值的组件不会同时被加载到一个实体当中。此外,一个访问的功能也会被添加到上下文当中,这将允许你使用组件值快速查找这个实体。

using Entitas;
using Entitas.CodeGeneration.Attributes;

// Core component to provide a name.  Will only allow a single entity with that name.
[Game]
public class NameComponent : IComponent {
    [PrimaryEntityIndex]
    public string value;
}

// Can use Game.GetEntityWithName("Foo");

[EntityIndex]实体数属性

在组件值上使用此属性将允许您搜索具有附加组件和特定值的所有实体的上下文。 与上面不同,生成器并不会去关心这个属性的组件添加了多少。

Example

[Game]
public class FactionComponent : IComponent {
    [EntityIndex]
    public string name;
}
// Can now use Game.GetEntitiesWithFaction("Player");

[CustomComponentName]自定义组件名属性

生成多个名字不同的组件继承自同一个类或者同一个接口。

使用这个属性,你可以生成多个仅在名字上不同的组件共用同一个公共字段。所有组件都为同一个定义。这可以适用于强制跨多个组件使其一致,避免单独编写所有组件的繁琐任务。

下面这个例子将自动生成PositionComponent,VelocityComponent并将它们添加到默认上下文中:

[Context, CustomComponentName("Position", "Velocity")]
public struct IntVector2 {
  public int x;
  public int y;
}

[DontGenerate]拒绝转换属性

代码生成器将会跳过这个属性的组件。

此属性不言自明,代码生成器将跳过任何具有此属性的组件。(作者的不屑)

Example

using Entitas;
using Entitas.CodeGeneration;

[DontGenerate]
public class FutureFeatureComponent : IComponent {
}

[Event] (又名Reactive-UI)事件属性

[Event({EventTarget}, {EventType}, {priority})] 代码生成器将会为反应式的UI 生成相应的组件,系统。接口。

将生成对组件更改做出反应的其他侦听器接口和组件。消除了编写RenderXSystems 的需要。

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

public class GameView: Monobehaviour, IPositionListener
{
  // Function to call after adding this View to a GameEntity
  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);
  }
}

// using the same GameController from HelloWorld tutorial
public class GameController : MonoBehaviour
{
  ...
  private static Systems CreateSystems(Contexts contexts)
    {
      return new Feature("Systems")
        // Your systems here
        .Add(new GameEventSystems(contexts));
    }
  }
}

在上面的示例中,当GameEntity更改位置时,生成的GameEventSystems将对所有联系的监听者调用OnPosition(entity, x, y);

相关参数

我们用 PositionComponent 这个例子来方便我们理解e:

EventTarget

  • .Self: View's OnPosition 将会被调用,仅当 GameEntity的位置发生改变。
  • .Any: View's OnPosition 将会被调用,当 任何 GameEntity的位置发生改变。

第一个参数OnPosition是Position已更改的实体。

EventType

  • .Added (default): 将生成 IPositionListener.
  • .Removed: 将生成 IPositionRemovedListener.

priority

确定生成的系统的执行顺序。

[Cleanup] (Asset Store only)清理属性

代码生成器将会生成一处组件或者删除组件。

这个属性只能在插件商店的版本当中出现,由于VNO2巨穷无比,实在掏不起90美刀一窥究竟(怨念),所以这部分留给读者自行理解。 There are currently two options:

  • CleanupMode.DestroyEntity
  • CleanupMode.RemoveComponent

CleanupMode.DestroyEntity will generate a system that destroys all entities which have this component.

CleanupMode.RemoveComponent will generate a system that will remove this component from all entities which have this component.

Example

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