Я создал игру в SceneKit и в настоящее время портирую в проект ARKit. Все прошло гладко, пока физика точек не добавилась к узлам, которые необходимы для присоединения физического тела. FPS идет от стабильного 60FPS до добавления физических тел примерно до 5FPS после добавления физических тел. В данный момент я застрял на этом и попробовал множество вещей, чтобы решить эту проблему, но безуспешно. Кто-нибудь знает, что может вызвать это?
ПРИМЕЧАНИЕ Этот же код прекрасно работает только в обычном проекте SceneKit.
Моя игра ARKit настроена следующим образом. Сначала я инициирую сеанс, который использует изображение, чтобы распознать плоскость, которую я положил на пол.
let configuration = ARImageTrackingConfiguration()
guard let trackingImages = ARReferenceImage.referenceImages(inGroupNamed: "AR-Images", bundle: nil) else {
fatalError("Couldn't load tracking images.")
}
configuration.trackingImages = trackingImages
//gameView.debugOptions = [.showPhysicsShapes]
gameView.session.run(configuration)
Приведенный ниже метод является частью ARSCNViewDelegate и создает опорную точку, в которую будет загружаться и привязываться мир.
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
guard let imageAnchor = anchor as? ARImageAnchor else { return nil }
// create a plane at the exact physical width and height of our reference image
let plane = SCNPlane(width: imageAnchor.referenceImage.physicalSize.width, height: imageAnchor.referenceImage.physicalSize.height)
// make the plane have a transparent blue color
plane.firstMaterial?.diffuse.contents = UIColor.blue.withAlphaComponent(0.5)
// wrap the plane in a node and rotate it so it's facing us
let planeNode = SCNNode(geometry: plane)
planeNode.eulerAngles.x = -.pi / 2
// now wrap that in another node and send it back
let node = SCNNode()
node.name = "holderNode"
planeNode.name = "plane"
node.addChildNode(planeNode)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.setup(node: planeNode)
}
return node
}
Это Метод настройки, используемый для инициализации игры и ее зависимостей.
func setup(node: SCNNode){
let gameScale:Float = 0.05
let configuration = ARWorldTrackingConfiguration()
gameView.session.run(configuration)
setupScene(node: node, scale: gameScale)
setupPlayer(scale: gameScale)
setupGameManager()
setupCamera()
setupNPCS()
setupDPad()
// setup collisions
setupCollisions(scale: gameScale)
world.addChildNode(playerNode)
// connect to multiplayer server
NetworkController.shared.connectToServer()
// Add tap gesture
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
gameView.addGestureRecognizer(tap)
gameState = .playing
// Add views
gameView.addSubview(gameManager.topMenu)
gameView.addSubview(gameManager.actionButtonView)
}
Этот метод используется для настройки сцены.
private func setupScene(node: SCNNode, scale: Float){
gameView.allowsCameraControl = false
gameView.antialiasingMode = .none
guard let worldScene = SCNScene(named:"art.scnassets/Scene/world.scn") else { return }
world = worldScene.rootNode.childNode(withName: "world", recursively: true)
gameView.scene.physicsWorld.contactDelegate = self
world.rotation = SCNVector4(x: 1,
y: 0,
z: 0,
w: Float.pi / 2)
world.position.z = -5
node.addChildNode(self.world)
node.scale = SCNVector3(x: scale, y: scale, z: scale)
}
Этот метод устанавливает правильные физические тела на узлах, которые находятся в мир.
let root должен получить root, в котором объекты находятся в сцене ARSCNView.
private func setupCollisionBitMasks(nodeName: String, withChildNodes: Bool, scale: Float){
var collisionNodes = [SCNNode]()
guard let root = self.gameView.scene.rootNode.childNode(withName: "plane", recursively: true) else { return }
guard let nodes = root.childNode(withName: nodeName, recursively: true) else { return }
for node in nodes.childNodes {
if(withChildNodes){
for node in node.childNodes {
collisionNodes.append(node)
}
}else{
collisionNodes.append(node)
}
}
for node in collisionNodes {
node.physicsBody = SCNPhysicsBody.static()
node.physicsBody!.categoryBitMask = BitMasks.BitmasksWall.rawValue
node.physicsBody!.physicsShape = SCNPhysicsShape(node: node, options: [.type: SCNPhysicsShape.ShapeType.concavePolyhedron as NSString, SCNPhysicsShape.Option.scale: SCNVector3(scale, scale, scale)])
}
}