GameplayKit - 关于在组件之间发送消息的困惑

时间:2023-01-22 23:55:10

I'm diving into GameplayKit with Spritekit and from what I gather, you subclass GKEntity and then start adding GKComponents to that entity. The entity would more or less just be a bag of components that fill some function.

我正在使用Spritekit潜入GameplayKit,从我收集的内容中,你继承了GKEntity,然后开始将GKComponents添加到该实体。该实体或多或少只是一个充满某些功能的组件包。

The part I'm confused about is communication between components. How do you keep them decoupled. For example, lets say I have a HealthComponent class, and I add that component to a PlayerEntity, and an EnemyEntity. I also have a HealthBarComponent but I only want a health bar to appear above the player. When the player takes damage, that information needs to be updated in the HealthBarComponent.

我很困惑的部分是组件之间的通信。你如何让他们脱钩。例如,假设我有一个HealthComponent类,我将该组件添加到PlayerEntity和EnemyEntity。我也有一个HealthBarComponent,但我只想在播放器上方显示一个健康栏。当玩家受到伤害时,需要在HealthBarComponent中更新该信息。

So how should that information be sent? I see there is a class called GKComponentSystem in the documentation. I'm not 100% on how that should be used.

那么该信息应该如何发送?我看到文档中有一个名为GKComponentSystem的类。我不是100%应该如何使用它。

Another question is.. when the player's health reaches zero he should regenerate while the enemy should stay dead. When the player runs out of lives, the game ends.

另一个问题是......当玩家的健康状况达到零时,他应该在敌人应该死的时候再生。当玩家用完生命时,游戏结束。

The health system for both an enemy and player would be roughly the same, but the events around death would be totally different for each. I'm not following how to use a component system while keeping the unique behavior of each entity.

敌人和玩家的卫生系统大致相同,但死亡事件对每个人来说都是完全不同的。我不遵循如何使用组件系统,同时保持每个实体的独特行为。

some pseudo-code would be great

一些伪代码会很棒

2 个解决方案

#1


5  

It looks like this framework works a bit differently than others I've seen, in that systems only work on a single type of component rather than on entities with groups of component types.

看起来这个框架与我见过的其他框架的工作方式略有不同,因为系统只能处理单一类型的组件而不是组件类型组的实体。

In the GamePlay-Kit framework you can either loop through and update your entities manually (which in turns updates each entities components) or create a class which inherits from GKComponentSystem. Then when you update the system it updates all the components you have added to it so long as their class type matches the type you initialized the system with

在GamePlay-Kit框架中,您可以手动循环并更新您的实体(这反过来更新每个实体组件)或创建一个继承自GKComponentSystem的类。然后,当您更新系统时,它会更新您添加到它的所有组件,只要它们的类类型与您初始化系统的类型相匹配

To handle your health bar issue I would say make a HealthBarComponent which, during its update, retrieves the HealthComponent from its owner entity, reads the health value & renders itself every frame. But you only add a HealthBarComponent to your player entity.

为了处理你的健康栏问题,我想说一个HealthBarComponent,它在更新过程中从其所有者实体中检索HealthComponent,读取健康值并在每一帧中呈现自己。但是,您只需将HealthBarComponent添加到播放器实体。

You can retrieve the owner entity from a component and vice versa (see GKComponent.entity & GKEntity.components) so you could update your health bar like this:

您可以从组件中检索所有者实体,反之亦然(请参阅GKComponent.entity和GKEntity.components),以便您可以像这样更新健康栏:

/*Note: I'm not an ios developer, this is pseudocode*/

HealthBarComponent.update(){
  int healthValue = self.entity.components.get(HealthComponent).value;
  //Now render your health bar accordingly or hold onto this for later
}

To handle the player death issue I would think your best bet would be to have two different types of Health components (PlayerHealth & EnemyHealth) with two different corresponding systems. That or have a single Health component but 2 separate 'Death' components. Yeah it seems redundant but I'm having a hard time thinking of a better way inside of this framework. In my experience you either spend your time worrying about keeping everything completely decoupled and reusable or you build a game :)

为了处理玩家死亡问题,我认为你最好的选择是拥有两种不同类型的健康组件(PlayerHealth和EnemyHealth)以及两种不同的相应系统。那或者有一个健康组件,但有两个独立的'死亡'组件。是的,这似乎是多余的,但我很难想到在这个框架内有更好的方法。根据我的经验,你要么花时间担心保持一切完全脱离和可重复使用,要么你建立一个游戏:)

#2


3  

Components can access their entities via the self.entity property. From there, you can query other components to pass data to via the entity componentForClass property:

组件可以通过self.entity属性访问其实体。从那里,您可以查询其他组件以通过实体componentForClass属性传递数据:

guard let moveComponent = entity?.componentForClass(MoveComponent.self) else {
        fatalError("A MovementComponent's entity must have a MoveComponent")
    }

The iOS Games by Tutorials book has an excellent tutorial that covers GameplayKit entities and components.

iOS Games by Tutorials一书提供了一个很好的教程,涵盖了GameplayKit实体和组件。

#1


5  

It looks like this framework works a bit differently than others I've seen, in that systems only work on a single type of component rather than on entities with groups of component types.

看起来这个框架与我见过的其他框架的工作方式略有不同,因为系统只能处理单一类型的组件而不是组件类型组的实体。

In the GamePlay-Kit framework you can either loop through and update your entities manually (which in turns updates each entities components) or create a class which inherits from GKComponentSystem. Then when you update the system it updates all the components you have added to it so long as their class type matches the type you initialized the system with

在GamePlay-Kit框架中,您可以手动循环并更新您的实体(这反过来更新每个实体组件)或创建一个继承自GKComponentSystem的类。然后,当您更新系统时,它会更新您添加到它的所有组件,只要它们的类类型与您初始化系统的类型相匹配

To handle your health bar issue I would say make a HealthBarComponent which, during its update, retrieves the HealthComponent from its owner entity, reads the health value & renders itself every frame. But you only add a HealthBarComponent to your player entity.

为了处理你的健康栏问题,我想说一个HealthBarComponent,它在更新过程中从其所有者实体中检索HealthComponent,读取健康值并在每一帧中呈现自己。但是,您只需将HealthBarComponent添加到播放器实体。

You can retrieve the owner entity from a component and vice versa (see GKComponent.entity & GKEntity.components) so you could update your health bar like this:

您可以从组件中检索所有者实体,反之亦然(请参阅GKComponent.entity和GKEntity.components),以便您可以像这样更新健康栏:

/*Note: I'm not an ios developer, this is pseudocode*/

HealthBarComponent.update(){
  int healthValue = self.entity.components.get(HealthComponent).value;
  //Now render your health bar accordingly or hold onto this for later
}

To handle the player death issue I would think your best bet would be to have two different types of Health components (PlayerHealth & EnemyHealth) with two different corresponding systems. That or have a single Health component but 2 separate 'Death' components. Yeah it seems redundant but I'm having a hard time thinking of a better way inside of this framework. In my experience you either spend your time worrying about keeping everything completely decoupled and reusable or you build a game :)

为了处理玩家死亡问题,我认为你最好的选择是拥有两种不同类型的健康组件(PlayerHealth和EnemyHealth)以及两种不同的相应系统。那或者有一个健康组件,但有两个独立的'死亡'组件。是的,这似乎是多余的,但我很难想到在这个框架内有更好的方法。根据我的经验,你要么花时间担心保持一切完全脱离和可重复使用,要么你建立一个游戏:)

#2


3  

Components can access their entities via the self.entity property. From there, you can query other components to pass data to via the entity componentForClass property:

组件可以通过self.entity属性访问其实体。从那里,您可以查询其他组件以通过实体componentForClass属性传递数据:

guard let moveComponent = entity?.componentForClass(MoveComponent.self) else {
        fatalError("A MovementComponent's entity must have a MoveComponent")
    }

The iOS Games by Tutorials book has an excellent tutorial that covers GameplayKit entities and components.

iOS Games by Tutorials一书提供了一个很好的教程,涵盖了GameplayKit实体和组件。