Entitas Cookbook

Entitas CookBook 翻译 - 101_Compon

2018-04-24  本文已影响0人  SkyrimWu

组件 Component

Component是ECS中最简单的原料。它是数据的最原子性的呈现。它可以是空的、有一个或多个属性,甚至可以被标记为唯一的(类似单例)。接下来我将解释Entitas的组件实现方式。

最简单的组件 - 标志组件 (Flag Component)

我会用 Match-One 项目中定义的组件作为例子。

using Entitas;

public sealed class MovableComponent : IComponent {
}

正如你所看到的,一个组件是一个实现了IComponent接口的类。它没有任何属性,因此它是标志组件。Flag component是用于定义Flag Entity。在这种情况下,我们说有些东西是可移动的(is Movable对应MovableComponent)。所以如果我们有一个Entity,我们可以通过查询entity.isMovable并返回true或false。我们也可以要求所有拥有MovableComponent的Entity,但是我想稍后再讨论这种用法。

数据组件 (Data Component)

Data Component可以有多个可以存储纯数据的属性:

using Entitas;

public sealed class PositionComponent : IComponent {
    public int x;
    public int y;
}

在Entitas-CSharp中,我们可以使用以下语句为Entity添加一个Position:

entity.AddPosition(1, 2);

有一种方法来检查一个实体是否有对应的组件(hasPosition)。我们也可以获取(position),替换(ReplacePosition)和删除(RemovePosition)组件。每个实体只能有一种类型的组件集。这就是为什么我们有Replace方法。但我们可以将所有不同类型的组件结合在一个实体中。这就是为什么最好将组件尽可能粒子化(thin)。这在肆意组合(improvisation)方面给了你很大的好处。

引用组件 (Reference Component)

一个Reference Component在技术上等同于Data Component,主要是逻辑上的差别。

using Entitas;
using UnityEngine;

public sealed class ViewComponent : IComponent {
    public GameObject gameObject;
}

从技术上讲,Reference Component也是具有多个属性的Component,但是这些属性不代表数据。它们引用一个复杂的对象,这有一个更深一层的含义。这些组件很难被序列化,它们指向在运行时创建的一些对象,因此持久化指针是没有用的。我们将在Receipt章节深入研究Reference Component

操作组件 (Action Component)

这又是一个Data Component的衍生物。只是在这种情况下,属性是属于一个功能/操作。

using Entitas;
using System;

public sealed class DelegateComponent : IComponent {
    public Action action;
}

在这种情况下,我们可以将一个函数/委托/操作存储在一个组件中,并将其附加到一个Entity中。虽然组件能够这样使用,但它的坏处比好处更多,而不是我们将会在Reciept部分讨论的那样。

唯一组件 (Unique Component)

在每个应用程序中,有许多情况下你只想要一个物体的一个实例。这个想法一般呈现在大家多知道并且常常讨厌的单例模式中。在Entitas中,我们有类似的但更好的东西。

我们之前讨论的每种类型的组件都可以定义为一个唯一组件。

using Entitas;
using Entitas.CodeGeneration.Attributes;

[Unique]
public sealed class GameBoardComponent : IComponent {
    public int columns;
    public int rows;
}

为此,我们只需要将该类(通过Attribute)注释为唯一(Unique)的。

该框架(Entitas)将确保在上下文(Context)中只有一个唯一组件实例可以存在(请参阅Context章节)。这就是为什么在Entitas-CSharp中,我们可以用下面的表达式 - context.gameBoard来获得一个独特组件的实例。

怎么样,是不是比单例模式更好呢?由于我们将状态与行为分开,这会比单列模式更好。这个组件也可以被替换和移除。所以它打破了单例模式的习惯用法 - 一个对象在整个应用程序生命周期中是唯一且持久的。一个独特的组件比单例更像是一个全局变量。

通常来说一个程序需要多少个组件呢?

这个问题始终是专门针对ECS的新手。和往常一样,正确答案是 - 看!情!况!不过从我的经验来看,中端核心手机游戏上,150个组件相当不错。事实上,我对比了我参与制作的两个完全不同的手机游戏,大约都在150个组件左右。也就是说,我用EntitasKit构建的iOS应用程序(Swift实现)包含大约50个组件,也并不令人意外,因为游戏往往比应用程序复杂得多。

上一篇下一篇

猜你喜欢

热点阅读