【问题标题】:How to detect SCNPhysics Intersection between two GKEntities(SCNNodes) in a GKComponent for in SceneKit如何在 SceneKit 中检测 GKComponent 中两个 GKEntities(SCNNodes)之间的 SCNPhysics 交集
【发布时间】:2019-02-02 17:18:36
【问题描述】:

我正在尝试检测 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()
}

} }

【问题讨论】:

    标签: swift scenekit arkit gameplay-kit


    【解决方案1】:

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

    比如

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

    它类似于您示例中的代码:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-25
      • 2018-02-08
      • 2017-06-04
      • 2015-04-27
      • 1970-01-01
      相关资源
      最近更新 更多