如何在生成spritekitnodes上设置physicsBody(How to set physicsBody on spawning spritekitnodes)

编程入门 行业动态 更新时间:2024-10-09 06:28:53
如何在生成spritekitnodes上设置physicsBody(How to set physicsBody on spawning spritekitnodes)

我有物理机构的问题。 我有大约20个节点随机产生来查看。 每次节点产生时我都会设置对象的物理,如下所示:

func showObject(){ let texture = SKTexture(imageNamed: "A.png") object = SKSpriteNode(texture: texture) object.name = "A" object.position = CGPoint(x: 0, y: self.frame.width) object.setScale(0.7) object.zPosition = 2 object.run(moveAndRemove) object.physicsBody = SKPhysicsBody(texture: texture, size: texture.size()) object.physicsBody?.categoryBitMask = PhysicsCategory.Object object.physicsBody?.collisionBitMask = PhysicsCategory.Object2 object.physicsBody?.contactTestBitMask = PhysicsCategory.Object2 object.physicsBody?.affectedByGravity = false object.physicsBody?.isDynamic = true addChild(object) }

我认为这不是最优的,因为每次生成节点时都会设置physicsBody。 因此,我有时几乎没有闪烁 - 在应用程序运行时降低fps。 当physicsBody关闭时,一切正常。 所以我有一个简单的问题。 如何在游戏开始后为所有20个节点设置物理主体,而不仅仅生成它们而不再创建physicsBody。 我尝试将带有纹理的物理体直接设置为SKView,但在此之后,应用程序崩溃,出现nil错误。

谢谢你的提示。

有我的产卵:

let SpawnObject = SKAction.run({ () in let randomFunc = [self.showObject, self.showObject1.......] let randomResult = Int(arc4random_uniform(UInt32(randomFunc.count))) randomFunc[randomResult]() }) let delay1 = SKAction.wait(forDuration: 0.9) let SpawnDelay1 = SKAction.sequence([SpawnObject,delay1]) let SpawnDelayForever1 = SKAction.repeatForever(SpawnDelay1) self.run(SpawnDelayForever1) let distance = CGFloat(self.frame.height + 200) let moveObject = SKAction.moveBy(x: -distance, y: 0, duration: TimeInterval(0.004 * distance)) let removeObject = SKAction.removeFromParent() moveAndRemove = SKAction.sequence([moveObject,removeObject])

I have problem with physics body. I have about 20 nodes spawning randomly to view. Every time the node spawns I set the object's physics, like this:

func showObject(){ let texture = SKTexture(imageNamed: "A.png") object = SKSpriteNode(texture: texture) object.name = "A" object.position = CGPoint(x: 0, y: self.frame.width) object.setScale(0.7) object.zPosition = 2 object.run(moveAndRemove) object.physicsBody = SKPhysicsBody(texture: texture, size: texture.size()) object.physicsBody?.categoryBitMask = PhysicsCategory.Object object.physicsBody?.collisionBitMask = PhysicsCategory.Object2 object.physicsBody?.contactTestBitMask = PhysicsCategory.Object2 object.physicsBody?.affectedByGravity = false object.physicsBody?.isDynamic = true addChild(object) }

I think this is not optimal, because physicsBody is set everytime when node is spawned. Because of this I have sometimes little flickering - lower fps when app running. When is physicsBody turned off, everything is ok. So I have a simple question. How to set physics body for all 20 nodes after games started and than just spawn them without creating physicsBody again. I try to set physics body with texture straight to SKView but after this, app crash with nil error.

Thanks for any tip.

There is my spawn:

let SpawnObject = SKAction.run({ () in let randomFunc = [self.showObject, self.showObject1.......] let randomResult = Int(arc4random_uniform(UInt32(randomFunc.count))) randomFunc[randomResult]() }) let delay1 = SKAction.wait(forDuration: 0.9) let SpawnDelay1 = SKAction.sequence([SpawnObject,delay1]) let SpawnDelayForever1 = SKAction.repeatForever(SpawnDelay1) self.run(SpawnDelayForever1) let distance = CGFloat(self.frame.height + 200) let moveObject = SKAction.moveBy(x: -distance, y: 0, duration: TimeInterval(0.004 * distance)) let removeObject = SKAction.removeFromParent() moveAndRemove = SKAction.sequence([moveObject,removeObject])

最满意答案

有很多不同的方法可以解决这个问题,如果我产生多个相同的对象,我喜欢做的事情就是将对象预加载到一个数组中,并在我需要时从数组中拉出它们,当你完成了对象,您可以从场景中删除它们,但将它们保留在数组中。 然后,您可以再次使用该对象,而无需重新创建它,也无需重新创建导致滞后的物理主体

private var moveAndRemove = SKAction() private var objects = [SKSpriteNode]() private let objectCount = 20 override func didMove(to view: SKView) { for x in 0..<objectCount { let texture = SKTexture(imageNamed: "A") let object = SKSpriteNode(texture: texture) object.name = "A" object.isHidden = true object.setScale(0.7) object.zPosition = 2 object.physicsBody = SKPhysicsBody(texture: texture, size: texture.size()) object.physicsBody?.categoryBitMask = 0 object.physicsBody?.collisionBitMask = 0 object.physicsBody?.contactTestBitMask = 0 object.physicsBody?.affectedByGravity = false object.physicsBody?.isDynamic = true objects.append(object) } let distance = CGFloat(self.frame.height + 200) let moveObject = SKAction.moveBy(x:0 - distance, y: 0, duration: Double(0.004 * distance)) let removeObject = SKAction.removeFromParent() let hideObject = SKAction.hide() moveAndRemove = SKAction.sequence([moveObject, hideObject, removeObject]) let SpawnObject = SKAction.run( { let randomResult = Int(arc4random_uniform(UInt32(self.objects.count))) self.showObject(objectIndex: randomResult) }) let delay1 = SKAction.wait(forDuration: 0.9) let SpawnDelay1 = SKAction.sequence([SpawnObject, delay1]) let SpawnDelayForever1 = SKAction.repeatForever(SpawnDelay1) self.run(SpawnDelayForever1) } func showObject(objectIndex: Int) { let object = objects[objectIndex] guard object.isHidden == true else { return } object.isHidden = false object.position = CGPoint(x: 0, y: self.frame.width) object.zPosition = 10000 addChild(object) object.run(moveAndRemove) }

我编辑了答案以反映您的产卵代码。 请注意,我只是通过检查对象的隐藏状态来检查数组中的对象是否已被使用。 还有许多其他方法可以检查对象是否已被使用,但您必须找出最适合您的方法。

There is many different ways you could go about this, what I like to do if I am spawning multiple of the same object is preload the objects into an array and the pull them from the array as I need them, when you are done with the object you can remove them from the scene but keep them in the array. You can then use that object again without having to recreate it and without having to recreate the physics body causing the lag

private var moveAndRemove = SKAction() private var objects = [SKSpriteNode]() private let objectCount = 20 override func didMove(to view: SKView) { for x in 0..<objectCount { let texture = SKTexture(imageNamed: "A") let object = SKSpriteNode(texture: texture) object.name = "A" object.isHidden = true object.setScale(0.7) object.zPosition = 2 object.physicsBody = SKPhysicsBody(texture: texture, size: texture.size()) object.physicsBody?.categoryBitMask = 0 object.physicsBody?.collisionBitMask = 0 object.physicsBody?.contactTestBitMask = 0 object.physicsBody?.affectedByGravity = false object.physicsBody?.isDynamic = true objects.append(object) } let distance = CGFloat(self.frame.height + 200) let moveObject = SKAction.moveBy(x:0 - distance, y: 0, duration: Double(0.004 * distance)) let removeObject = SKAction.removeFromParent() let hideObject = SKAction.hide() moveAndRemove = SKAction.sequence([moveObject, hideObject, removeObject]) let SpawnObject = SKAction.run( { let randomResult = Int(arc4random_uniform(UInt32(self.objects.count))) self.showObject(objectIndex: randomResult) }) let delay1 = SKAction.wait(forDuration: 0.9) let SpawnDelay1 = SKAction.sequence([SpawnObject, delay1]) let SpawnDelayForever1 = SKAction.repeatForever(SpawnDelay1) self.run(SpawnDelayForever1) } func showObject(objectIndex: Int) { let object = objects[objectIndex] guard object.isHidden == true else { return } object.isHidden = false object.position = CGPoint(x: 0, y: self.frame.width) object.zPosition = 10000 addChild(object) object.run(moveAndRemove) }

I've edited the answer to reflect your spawn code. Please note that I am only checking if the object in the array has already been used by checking the hidden status of the object. There are many other ways to check if the object has been used, but you'll have to figure out what works best for you.

更多推荐

本文发布于:2023-08-07 13:26:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1464153.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:如何在   spritekitnodes   physicsBody   set   spawning

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!