Entities是Unity2018新引入的一个全新游戏设计框架,我们称之为实体组件系统(Entity Component System,简称ECS),它的出现使我们能够集中精力解决实际问题:构成游戏的数据和行为。它利用了C# Job System和Burst,使我们能够充分利用当今的多核处理器。通过从面向对象的设计转向面向数据的设计,我们将更容易重用代码,也更容易让其他人理解和使用ECS。
在Unity2018引入Entities之前,其实ECS框架早已经出现,但是ECS还是因为守望先锋采用了这个框架才被我们所熟知,后来Git上面出现了一个Entitas的插件可以直接用在Unity上面,我在以前的公司参与过一个项目就是用的Entitas插件。
实体Entity:一个ID,它可以用于间接的组件查找,用于在容器里面遍历。
组件数据ComponentData:存储在实体中的数据。
组件系统ComponentSystem:处理游戏,系统逻辑和行为的地方。
组Group:组件系统运行所需的ComponentData列表,相对于判断条件。
Entities名称 | 传统ECS名称 |
Entity | Entity |
ComponentData | Component |
ComponentSystem | System |
Entities | MonoBehaviour |
Entity | GameObject |
ComponentData | Component的字段变量 |
ComponentSystem | Component的Update方法 |
注意:安装Entities后会报错是因为Unity默认的Scripting Runtime Version是.Net 3.5 Equivalent,我们改为.Net 4.x Equivalent即可。
我们用一个简单的例子来讲解一下Entities的使用方法。
我们先用传统的写法写一个Cube的自转。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotationCube : MonoBehaviour {
public float speed;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
transform.Rotate(Vector3.up * speed * Time.deltaTime);
}
}
接下来我们混合加入ECS,把上面的代码拆分成Component和System。我们先写一个Component,只有一个字段变量。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotationCubeComponent :MonoBehaviour
{
public float speed;
}
然后我们再写一个System,作为逻辑的处理。首先我们要继承ComponentSystem,然后重写OnUpdate,这里相当于MonoBehaviour的Update,我们在这里处理逻辑。Group则是组件系统运行所需的ComponentData列表,可以随意命名,我们可以在这里写很多不同的Group,作为处理逻辑的条件。GetEntities
using System.Collections;
using System.Collections.Generic;
using Unity.Entities;
using UnityEngine;
public class RotationCubeSystem : ComponentSystem
{
struct Group
{
public RotationCubeComponent rotation;
public Transform transform;
}
protected override void OnUpdate()
{
foreach (var enitites in GetEntities())
{
enitites.transform.Rotate(Vector3.up * enitites.rotation.speed * Time.deltaTime);
}
}
}
我们也可以用另外一种方式来写System。Inject表示注入数据,在Unity启动时会自动赋值合适的值
using System.Collections;
using System.Collections.Generic;
using Unity.Entities;
using UnityEngine;
public class RotationCubeSystem : ComponentSystem
{
struct Group
{
public readonly int Length;
public ComponentArray rotationCubeComponents;
//public RotationCubeComponent rotation;
//public Transform transform;
}
[Inject] Group group;
protected override void OnUpdate()
{
//foreach (var enitites in GetEntities())
//{
// enitites.transform.Rotate(Vector3.up * enitites.rotation.speed * Time.deltaTime);
//}
for (int i = 0; i < group.rotationCubeComponents.Length; i++)
{
group.rotationCubeComponents[i].transform.Rotate(Vector3.up * group.rotationCubeComponents[i].speed * Time.deltaTime);
}
}
}
最后,我们创建一个Cube,附加上GameObjectEntity给他一个实体ID标识,附加上RotationCubeComponent组件,我们把旋转速度调为100,再创建几个Cube并且附加上GameObjectEntity,但不附加RotationCubeComponent组件,运行Unity后发现,带有RotationCubeComponent组件的实体会自转,没有带RotationCubeComponent组件的实体不会自传。
我们讲的这个案例主要是让大家了解ECS这个框架的基本思想和传统的开发思路的区别,即数据和逻辑分离。
我将在下一篇文章中继续深入讲解ECS的框架。
Unity2018新功能之Entity Component System(ECS)二