我正在使用GamePlay套件实体 - 组件系统进行2D游戏。 每个实体都有一个GKComponents-spriteComponent,physicComponent等的sersis和一个GKComponent(ChaseScrollMovement.swift),它接受一个实体spriteComponent并在屏幕上移动它。
将ChaseScrollMovment组件添加到Enemy Enity
addComponent(physicsCompnment);
scrollerComponent = ChaseScrollComponent(entity: self, isEnemey : true);
addComponent(scrollerComponent);
问题是当我从GameScence中删除EnemyEnity表格时(与WeaponEnity联系时):
Class ThrowWeaponEnity.....didBginContact...
case "enemyEntity":
if let spriteComponentEnemy = entity.componentForClass(SpriteComponent.self){
let pos = spriteComponentEnemy.node.position;
//Remove enemy sprote and its entiy
spriteComponentEnemy.node.parent?.runAction(SKAction.playSoundFileNamed("110548__noisehag__comp-cover-02.wav", waitForCompletion: false));
spriteComponentEnemy.node.removeAllActions();
spriteComponentEnemy.node.removeFromParent();
//Remove the entire entity
entity.removeComponentForClass(SpriteComponent.self);
emitterExplosion(pos);
}
break;
.... EnemeyEnitiy从GameScene中删除,GameScene更新方法然后调用组件更新方法....
GameScene中的组件
lazy var componentSystems: [GKComponentSystem] = {
let parallaxSystem = GKComponentSystem(componentClass: ParallaxComponent.self)
let animationSystem = GKComponentSystem(componentClass: AnimationComponent.self)
let scrollerSystem = GKComponentSystem(componentClass: ChaseScrollComponent.self)
return [animationSystem, parallaxSystem, scrollerSystem]
}()
let scrollerSystem = FullControlComponentSystem(componentClass: FullControlComponent.self).......
//MARK: Life Cycle
override func update(currentTime: CFTimeInterval) {
if !pauseLoop {........
// Update Components
for componentSystem in componentSystems {
componentSystem.updateWithDeltaTime(deltaTime)
}
.....所以ChaseScroll组件无法找到EnemyEntity的spriteCompnment,因为它已从场景中删除,并在此处抛出异常....
class ChaseScrollComponent: GKComponent {
var spriteComponent: SpriteComponent {
//Called after Init() and during GaemplayMode.updat / componments.udate
guard let spriteComponent = entity?.componentForClass(SpriteComponent.self)
else{
fatalError("SpriteCompnemnet Missing");
}
print("SpriteCompnemnt for CHaseScroll GKConponent : \(spriteComponent.node.name)")
return spriteComponent;
}
我是Enity-Compnent系统的新手,所以我想知道当场景中删除单个EnemyEntity(场景中有很多)并允许组件在成功期间成功更新时,防止异常的最佳方法是什么GameScene生命周期。
提前致谢
更新: 尝试从系统中删除组件,以便在游戏场景更新中不会调用组件upDate方法:
//在我们的游戏场景中
func removeEntity(entity : GKEntity){
print("Enity hashValue and \(entity.hash)description: \(entities.count)");
if entities.contains(entity){
//Remove the entities components
let entiyRemoved = entities.remove(entity);
entity.removeComponentForClass(PhysicsComponent.self);
entity.removeComponentForClass(ChaseScrollComponent.self);
}
//Remove entity from array of enities
entities.remove(entity); print(entities.count);
for componentsytem in self.componentSystems{
//Remove componment is from the system not the entity, so if removed the component update will not be called
componentsytem.removeComponentWithEntity(entity); }
}
但是应该删除的Component仍然会调用其更新,在此更新中,实体spriteComponent的初始化失败,因为我们已从实体中删除了组件(并试图从系统中删除!):< / p>
var spriteComponent: SpriteComponent {
guard let spriteComponent = entity?.componentForClass(SpriteComponent.self)
else{
fatalError("SpriteCompnemnet Missing");
}
print("SpriteCompnemnt for CHaseScroll GKConponent : \(spriteComponent.node.name)")
return spriteComponent;
}
所以仍然无法从系统中删除Component,因为它的更新仍然被调用,或者无法从系统中删除实体。
答案 0 :(得分:1)
以下是我如何在ECS
中初始化系统的示例。此代码位于GameScene中。请注意,Entity会创建自己的组件。
var entities: [GKEntity]!
var componentSystems: [GKComponentSystem<GKComponent>]!
override func didMove(to view: SKView) {
self.setupEntities()
self.setupComponentSystems()
}
override func update(_ currentTime: TimeInterval) {
// Update ComponentSystems
for componentSystem in componentSystems {
componentSystem.update(deltaTime: dt)
}
}
func setupEntities() {
self.entities = [GKEntity]()
// Initialise Rover
self.roverEntity = RoverEntity()
self.entities.append(self.roverEntity as! GKEntity)
// Add entites to scene
for entity in self.entities {
if let visualEntity = entity as? VisualEntity {
self.addChild(visualEntity.node)
}
}
}
func setupComponentSystems() {
self.healthSystem = HealthSystem()
self.healthSystem.addComponents(from: self.entities)
self.healthSystem.delegate = self
self.moveSystem = MoveSystem()
self.moveSystem.addComponents(from: self.entities)
self.moveSystem.delegate = self
self.selectionSystem = SelectionSystem()
self.selectionSystem.addComponents(from: self.entities)
self.selectionSystem.delegate = self
self.componentSystems = [
self.healthSystem,
self.moveSystem,
self.selectionSystem
]
}
当需要删除实体时,removeComponent(foundIn:)
上有一个函数GKComponentSystem
。这是Swift 3,所以期望Swift 2的命名会有所不同。
for componentSystem in componentSystems {
componentSystem.removeComponent(foundIn: self.roverEntity as! GKEntity)
}
现在可以从ECS
中的所有系统中删除与此实体关联的此组件,并且可以从场景中删除实体节点。