如何在SceneKit中检测GKComponent中两个GKEntities(SCNNodes)之间的SCNPhysics交集

时间:2019-02-02 17:18:37

标签: swift scenekit arkit gameplay-kit

我正在尝试检测SceneKit中两个scnnode的交集。它们已注册为GKEntities。我想将一个组件关联到两个实体,这两个实体将使用SCNPhysicsContactDelegate检测其物理体的相交,但是我不想在视图控制器中执行此操作,因为我知道这不是最佳实践,并且这将使注册变得困难作为一个组成部分。任何帮助将不胜感激。

感谢您的帮助,

蒙特罗

import Foundation
import SpriteKit
import GameplayKit
import SceneKit

class MeleeComponent: GKComponent, SCNPhysicsContactDelegate {

 let damage: CGFloat
 let destroySelf: Bool
 let damageRate: CGFloat
 var lastDamageTime: TimeInterval
 let aoe: Bool
 //  let sound: SKAction
   let entityManager: EntityManager
   init(damage: CGFloat, destroySelf: Bool, damageRate: CGFloat, aoe:      Bool, entityManager: EntityManager) {
 self.damage = damage
self.destroySelf = destroySelf
self.damageRate = damageRate
self.aoe = aoe
 //    self.sound = sound
self.lastDamageTime = 0
self.entityManager = entityManager
super.init()
 }

 required init?(coder aDecoder: NSCoder) {
     fatalError("init(coder:) has not been implemented")
}


 override func update(deltaTime seconds: TimeInterval) {

super.update(deltaTime: seconds)

// Get required components
guard let teamComponent = entity?.component(ofType: TeamComponent.self),
          let spriteComponent = entity?.component(ofType: SpriteComponent.self) else {
  return
}

// Loop through enemy entities
var aoeDamageCaused = false
let enemyEntities = entityManager.entitiesForTeam(teamComponent.team.oppositeTeam())
for enemyEntity in enemyEntities {

  // Get required components
  guard let enemySpriteComponent = enemyEntity.component(ofType: SpriteComponent.self),
        let enemyHealthComponent = enemyEntity.component(ofType: HealthComponent.self) else {
    continue
  }

  // Check for intersection

  if       (spriteComponent.node.frame.intersects(enemySpriteComponent.node.frame)) {

    // Check damage rate
    if (CGFloat(CACurrentMediaTime() - lastDamageTime) > damageRate) {

      // Cause damage
//          spriteComponent.node.parent?.run(sound)
      if (aoe) {
        aoeDamageCaused = true
      } else {
        lastDamageTime = CACurrentMediaTime()
      }

      // Subtract health
      enemyHealthComponent.takeDamage(damage)

      // Destroy self
      if destroySelf {
        entityManager.remove(entity!)
      }
    }
  }
}

if (aoeDamageCaused) {
  lastDamageTime = CACurrentMediaTime()
}

} }

1 个答案:

答案 0 :(得分:0)

在SCNPhysicsWorld中,有一些API可以帮助您。

例如

 func contactTestBetween(_ bodyA: SCNPhysicsBody, _ bodyB: SCNPhysicsBody, options: [SCNPhysicsWorld.TestOption : Any]? = nil) -> [SCNPhysicsContact]

它与您示例中的代码相似:

if  (spriteComponent.node.frame.intersects(enemySpriteComponent.node.frame))

但是它在SceneKit中,将为您提供有关该联系人的更多信息。