Articles of 实体系统

Libgdx + Ashley移动一个纹理导致一切都跳跃

我的问题是,当我移动我的玩家实体时,所有的实体都通过我的玩家实体移动向量的相反总量来移动位置。但是唯一移动事物的系统是我的MovementSystem类,它通过它自己的移动向量来移动实体并被夹紧由德尔塔时间。 MovementSystem public class MovementSystem extends IteratingSystem { private ComponentMapper<MovementComponent> movementComponentMap; private ComponentMapper<TransformComponent> posComponentMap; private ComponentMapper<DebugComponent> debugComponentMap; public MovementSystem() { super(Family.all(MovementComponent.class, TransformComponent.class, DebugComponent.class).get()); movementComponentMap = ComponentMapper.getFor(MovementComponent.class); posComponentMap = ComponentMapper.getFor(TransformComponent.class); debugComponentMap = ComponentMapper.getFor(DebugComponent.class); } @Override protected void processEntity(Entity entity, float deltaTime) { TransformComponent pos = posComponentMap.get(entity); MovementComponent mov = movementComponentMap.get(entity); DebugComponent db = debugComponentMap.get(entity); pos.Position.x += […]

我应该加载文件的场景,还是硬编码?

在我正在开发的游戏引擎中,我使用的是类似于Unity中可以find的场景。 在我的游戏中,实体由可重用的组件和与这些组件相关联的自定义数据组成。 实体有孩子,有一个家长。 如下所示: class Entity { …custom data here… let parent : Component var children : [Component] = [] var components : [Component] = [] …methods… } 如果实体没有自定义数据,则创建场景将通过以下步骤进行描述: 将文件加载到内存中。 创建一个实体树。 使用文件中列出的参数向它们添加组件。 但是,这不会为自定义数据留下空间。 我的另一种select是通过创建一个场景对象来创建一个场景,然后对这些实体进行硬编码。看起来有点像这样: var opening_scene = Scene() opening_scene.addEntity(Player()) opening_scene.addEntity(Car()) opening_scene.addEntity(Terrain()) … 这个缺点是一切都是硬编码的。 我能做些什么来更有效地创建游戏场景?

如何通过速度乘以德尔塔时间来避免位置增加,即使身体不动?

在下图中,即使在空闲空间上移动,字符纹理也能正确地同步到人体。 在下图中,角色正在向下移动。 但是当有障碍物或墙壁的时候,纹理会有一定的跨度或者不同步。 我用于数据逻辑(ECS)的系统 class MovementSystem extends IteratingSystem { @Override public void processEntity(Entity entity, float deltaTime) { PositionComponent position = … VelocityComponent velocity = … position.x = velocity.x * deltaTime; position.y = velocity.y * deltaTime; } } class PhysicsSystem extends IteratingSystems { @Override public void processEntity(Entity entity, float deltaTime) { PositionComponent position … BodyComponent body… […]

ecs和fsm中的角色运动应该包含哪些组件?

在下面的代码中,有一个CharacterState的FSM,它也将在CharacterSystem处理。 问题是,我不知道在CharacterState或CharacterSystem哪个组件应该保存移动数据 public class CharacterState implements State<Entity> { STANDING, WALKING, RUNNING, IN_PAIN, DEAD } public enum Movements { STAND_STILL, MOVE_UP, MOVE_DOWN, MOVE_LEFT, MOVE_RIGHT, MOVE_UP_RIGHT, MOVE_UP_LEFT, MOVE_DOWN_RIGHT, MOVE_DOWN_LEFT; } CharacterComponent implements Component { Movements movement } MovementComponent implements Component { Movements movement } AnimationComponent implements Component { IntMap<Animation> map = new IntMap<Animation>(); } animation.map.put(Movements.MOVE_UP.order, ASSET.CHAR_MOVE_UP);

如果其中一个值为空,如何跳过比较?

我正在使用libGDX – Ashley作为实体系统框架。 我的问题是我不知道如何避免有一个java.lang.NullPointerException使用Comparator<Entity>实体比较。 有一种情况,实体从引擎中移除,但Comparator器仍在继续。 现在,如果附近的其中一个为空,我该如何跳过比较? @Override public int compare(Entity nearby1, Entity nearby2) { Vector2 ownerPos = Mapper.transform.get(owner).position; Vector2 nearbyPos1 = Mapper.transform.get(nearby1).position; // possible null Vector2 nearbyPos2 = Mapper.transform.get(nearby2).position; // possible null return … } 当我sortingArray<Entity>例如,使用我的自定义比较器,它返回一个错误,因为其中一个实体为null或一个组件实体为空。 我不知道要回来做什么比较跳过。 boolean skip = ownerPos == null || nearbyPos1 == null || nearbyPos2 == null; if(skip) { return ??? […]

AI和EntitySystem

我正在使用一个实体组件系统,并有一个AI系统,作用于系统内的某些实体(代理)。 我的问题是:AI系统应该如何与世界和代理商互动? 我正在考虑两种相反的方法: 如果AI认为应该发生某些事情(例如,某个特工正在睡觉,导致其疲劳程度降低): 它直接做到这一点。 (例如,AI系统在每次更新时改变代理上的疲劳属性) 它将一个或多个组件添加到实体。 (例如,AI系统将一次SleepNowComponent添加到代理,然后等待它在每次更新时到达terminal状态) #1优点/缺点:这很简单,但是如果我有另外一段代码基本上是相同的事情,我不得不复制或分解成一个共同的function。 #2优点/缺点:更复杂的是,如果代理人的AI处于“睡眠”子程序中,则AI系统基本上不会对该代理程序做任何事情,除非检查以确保正确的组件连接到实体。 当组件完成(例如,代理的疲劳属性达到0)时,AI将移动到下一个任务。 好的一面,如果游戏的任何部分都需要实体进入睡眠状态,就像添加正确的组件一样简单。 人们对此有什么想法? 我现在在#1和#2选项之间平分秋色。

子系统和GameObject组件之间的通信?

目前我有一个架构(不是100%准确): RenderData包含原始graphics,由GraphicsEngine处理。 在创建之后,我必须将渲染数据的指针从渲染器发送到GraphicsEngine。 这是通过传递给GameObject来完成的,GameObject将它传递给Scene,它传递给Core,它将在GraphicsEngine中调用相应的方法。 这个问题是场景可以访问Core。 我怎样才能正确地在GraphicsEngine上注册这些RenderData? 这与用于发送声音的AudioEngine的行为组件相同。 这与刚体组件的刚体数据和物理引擎也是一样的。 但是还有一个问题:如何发送与PhysicsEngine相撞的对象? 我曾经想过在碰撞对象的RigidbodyData处注册对象ID,Renderer会感觉到这一点,并处理自定义行为。 (就像子弹与玩家相撞时发生的情况) 如果这是好的,那么我如何给自定义的脚本指示与另一个游戏对象有碰撞? 在创建Behavior之后,我们将他们的OnCollide方法添加到Rigidbody的数组中? 或者只是将行为存储在通用组件容器中,而不是将这些行为存储在通用组件容器中,只需对它们进行迭代,然后调用OnCollosion? 另一个问题:窗口处理input,并且必须在场景中指示这些行为组件。 所以它已经访问了Scene,并且在接收到input时,它会调用Scene对应的方法来以某种方式传播事件?

实体组件系统中的高效系统

我正在用ECSdevise一个简单的Arcanoid游戏。 有了ECS,有很多系统只是偶尔更新组件。 例如, 粒子系统是可用于碰撞效果或爆炸的animation精灵。 这种效果很less发生。 ParticleSystem只会在存在的时候更新ParticleComponent ,很less发生碰撞等。剩下的时间是通过ParticleComponent查找实体。 这轮询不是低效的吗? 如果我有更多类似于ParticleSystem函数,那么这个函数很less会起作用,更新将会被不更新任何东西的系统所阻塞。 在实体被分配给ParticleComponent之前,“睡觉”系统是否是一个好习惯? 例如(使用EntityX): class ParticleComponent : Component<ParticleComponent> { public: ParticleComponent(ParticleId id) : id(id), time(0.0){}; ParticleId id; double time; }; class ParticleSystem : System<ParticleSystem> { public: void update(EntityManager & entities, EventManager & events, TimeDelta dt) { // this list will be empty if there are no entities.. but […]

你将如何实现和区分input操作和input状态?

我目前正试图设置我的游戏,我开始实施input。 它是这样工作的: 我有一个Input类,每当按下某个键(或释放或其他)时都会通知InputMapper 。 这个InputMapper获取按键,并根据当前的InputContext (Action和State是枚举)返回一个Action或一个State (我使用这篇文章来了解它应该如何工作)。 这里的Action表示像Jump一样的一次性动作,而State表示像move_right这样的连续move_right 。 我现在将一个InputListener附加到InputMapper ,每次按下它都会得到Action或State 。 在游戏中,我使用了一个实体组件系统 。 我有一个ControlComponent ,它应该有一个variables来决定一个实体应该做什么,一个KeyBoardSystem应该设置这些variables。 然后ControlComponent被诸如WalkSystem或JumpSystem类的东西使用。 我现在的问题是:你将如何在一个实体 – 组件系统中实现这些国家和行动? 我知道国家可以由控制组件中的布尔代表,但行动? 他们可能是事件,但ControlComponent doesnt(不应该?)有任何方法或知道使用它的系统。 任何帮助表示赞赏。

纯粹实体组件系统中的事件处理,这种方法是否正确?

我想问一下,使用ECS来构建事件传播是否是一种有效的方法? 这是一个假设的使用ECS的碰撞情景。 组件 : class Collider { public var rect:Rectangle; } 和 class Health { public var health:Int; } 现在的行为逻辑: 我们可以创建具有Collider和/或Health组件的实体。 一些ColliderSystem处理具有Collider组件的实体(更具体地说是节点)。 它涉及处理碰撞逻辑并确定两个Collider组件矩形是否重叠。 此外,如果具有Collider组件的实体具有Health组件,则Health组件的值应该降低。 我将如何实现这种行为? 我看到了三种方法来处理它,2坏,1好。 坏主意1:我们可以检查HandleCollisionsSystem每个帧的所有ColliderHealthNode上的碰撞,但是这看起来像是浪费了计算。 价值可能不会改变每一帧。 坏主意2:然而,我们可以使用ECS通过系统注册来传递这个逻辑,而不是一个事件系统。 我们的HandleCollisionsSystem可以将一个Collided组件(实际上只是一个标签)添加到Collider组件的实体中。 然后,我们的HandleCollisionsSystem将在<Collider, Health, Collided>方面注册到我们的ECS。 除了这看起来像过度使用/滥用ECS,它也默默地耦合系统之间的逻辑(我们怎么知道CollisionSystem将Collided组件标签添加到它处理的ColliderNode的实体?)我们如何知道我们的HandleCollisionsSystem需要有一个方面,包括一个Collided标签? CollisionSystem和HandleCollisionsSystem需要知道彼此的内部运作,因此变得逻辑上,但不可见,耦合。 好主意(?):我认为最有意义的方法是使用事件侦听器模式,让我们的CollisionSystem广播CollisionEvent ,而我们的HandleCollisionsSystem可以侦听CollisionEvent 。 实现如下所述: 我们将创建一个枚举: enum CollisionEvent { BEGIN_COLLISION; // … could have more types } 而且我们像这样创建了CollisionSystem //aspect:<Collider> class CollisionSystem […]