本文转自Unity Connect博主 郡墙
这是一篇关于 DOTS\ ECS \JobSystem相关的小白转换编程思想
实现游戏实体的传统方式是使用面向对象的编程。每个实体都是一个对象,可以直观地允许基于类的实例化系统,并使实体可以通过多态性扩展其他实体。 这导致了庞大而僵化的类层次结构。随着实体数量的增加,在层次结构中放置新实体变得越来越困难,尤其是在该实体需要大量不同类型的功能的情况下。 举个栗子
需要实现一类怪物为 邪恶的树。在这个编程模式里,不论是继承哪边都会存在设计上的冲突或者冗余。 为了解决这个问题,我们通过组合模式来代替继承的设计来构建实体。实体只是组件的“集合“与上述面向对象的体系结构相比,这具有一些主要优点:
便于添加新的复杂实体
便于在数据中定义新实体
更高效
组件 - Component
组件可以类比 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,在线技术答疑,发现更多资源干货!