理解 DOTS - ECS - 编程思想(基础入门)
本文转自Unity Connect博主 郡墙
这是一篇关于 DOTS\ ECS \JobSystem相关的小白转换编程思想
实现游戏实体的传统方式是使用面向对象的编程。每个实体都是一个对象,可以直观地允许基于类的实例化系统,并使实体可以通过多态性扩展其他实体。 这导致了庞大而僵化的类层次结构。随着实体数量的增加,在层次结构中放置新实体变得越来越困难,尤其是在该实体需要大量不同类型的功能的情况下。 举个栗子
image需要实现一类怪物为 邪恶的树。在这个编程模式里,不论是继承哪边都会存在设计上的冲突或者冗余。 为了解决这个问题,我们通过组合模式来代替继承的设计来构建实体。实体只是组件的“集合“与上述面向对象的体系结构相比,这具有一些主要优点:
-
便于添加新的复杂实体
-
便于在数据中定义新实体
-
更高效
组件 - Component
image组件可以类比 C语言的结构。它没有方法,只能存储数据,不能对其进行操作。在典型的实现中,每种不同的组件类型都将从抽象的Component类派生,该类提供了在运行时获取组件的类型并包含实体的工具。每个组件都描述实体的某个方面及其参数。组件本身几乎没有任何意义,但是当与实体和系统结合使用时,它们将变得非常强大。空组件对于标记实体很有用。 例如:
-
Position (x, y)
-
Velocity (x, y)
-
Physics (body)
-
Sprite (images, animations)
-
Health (value)
-
Character (name, level)
-
Player (empty)
实体 - Entity 实体就是游戏世界中存在的东西。同样,实体不过是组件列表而已。因为它们是如此简单,所以大多数实现都不会将实体定义为具体的数据。相反,实体是唯一的ID,组成该实体的所有组件都将使用该ID进行标记。实体是用其ID标记的组件的隐式聚合。如果需要,可以允许将组件动态添加到实体或从实体中删除。这使可以动态“改变”实体。比如,法师释放了一个冰冻技能,那么只需删除被命中对象的Velocity组件。 例如:
-
Rock (Position, Sprite)
-
Crate (Position, Sprite, Health)
-
Sign (Position, Sprite, Text)
-
Ball (Position, Velocity, Physics, Sprite)
-
Enemy (Position, Velocity, Sprite, Character, Input, AI)
-
Player (Position, Velocity, Sprite, Character, Input, Player)
系统 - Systems 注意,在上面的两个概念里,都没有实现具象的游戏逻辑。因为这是 System 概念里要处理的事情。系统对相关的组件组(即属于同一实体的组件)进行操作。 拆解角色跳跃逻辑
-
首先检测下Input中的keyJump按键是否被按下
-
如果是,那么检查Collider中是否有接触地面
-
如果是,设置这个实体的Velocity的y速度,让这个实体对象跳起来。
由于系统只会对相关联的组件进行操作,所以组件就定义了一个实体所应该具有的行为。 比如,如果实体对象只有Position组件,没有Velocity组件,那么这个对象是静止不动的,系统就不会对这个实体的Position组件进行操作了。当这个实体添加elocity组件后,系统就会使用Velocity组件来对物体进行移动。这样的行为可以使用被标记的组件来进行,被标记的组件能够重复的使用在不同的上下文中。对一个实体,增加一个空的Player组件,将会为这个实体打上了Player的标签,那么PlayerControl系统,就会寻找带有这个标签的所有组件,然后使用Input中的数据,进行操作。 例如:
-
Movement (Position, Velocity)
-
Gravity (Velocity)
-
Render (Position, Sprite)
-
PlayerControl (Input, Player)
-
BotControl (Input, AI)
原文链接:https://connect.unity.com/p/li-jie-dots-ecs-bian-cheng-si-xiang-ji-chu-ru-men?app=true
欢迎戳上方原文链接,下载Unity官方技术社区app,在线技术答疑,发现更多资源干货!