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

标签 swift scenekit arkit gameplay-kit

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

感谢您的帮助,

蒙特勒

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()
}

} }

最佳答案

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

比如

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

它与示例中的代码类似:

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

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

关于swift - 如何在 SceneKit 中的 GKComponent 中检测两个 GKEntities(SCNNodes) 之间的 SCNPhysics 交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54495506/

相关文章:

ios - Scenekit:为什么不应该对 SCNNode 进行子类化?

swift - 文本与应删除的文本重叠

json - 变量 json = [ :] null dictionary

ios - 如何在 arkit (swift4) 上添加黑白滤镜

ios - 在 native iOS 中使用 NSKeyedArchiver 序列化的 Unity 中反序列化 ARWorldMap

ios - 在 ARKit 中缩放 SCNNode

ios - 从应用程序向 ARKit 添加引用图像

arrays - 如何检查数组以查看它是否包含 nil 值?

objective-c - NSFetchRequest 的 fetchBatchSize 导致在 Swift 中立即获取所有批处理

ios - 具有多个 UIPanGestureRecognizers 的 SceneKit 立方体旋转