Swift SpriteKit浮动气泡在Watch App出界卡边角不回弹问题求解
问题根因
你的代码异常核心原因是WatchOS与iOS的SKScene生命周期存在差异:sceneDidLoad方法调用时,WatchOS端的SKScene还未完成布局,frame和size都是默认值而非实际SpriteView的渲染尺寸,导致你创建的物理边界位置错误、气泡随机生成坐标超出真实视图范围,最终出现气泡出界、碰撞卡住的问题。
修复方案
- 把边界初始化、气泡生成逻辑从
sceneDidLoad迁移到didMove(to view: SKView)方法中,该方法会在Scene被挂载到视图、尺寸已经正确计算后触发 - 添加初始化标记,避免重复创建边界和气泡
- 随机坐标计算时额外预留气泡半径的偏移量,避免气泡生成时就卡在边界上
- 确认SwiftUI中SpriteView添加了
.ignoresSafeArea()修饰符,避免WatchOS安全区挤压Scene的显示范围
修改后核心代码示例
let ballCategory: UInt32 = 0xb0001 let edgeCategory: UInt32 = 0xb0010 var nodeCount = 0 // 添加初始化标记 var hasInitialized = false override func sceneDidLoad() { physicsWorld.contactDelegate = self physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0) } override func didMove(to view: SKView) { guard !hasInitialized else { return } hasInitialized = true // 此时size已经是正确的渲染尺寸 let edge = SKPhysicsBody(edgeLoopFrom: self.frame) edge.friction = 0 edge.categoryBitMask = edgeCategory self.physicsBody = edge makebubble() makebubble() makebubble() makebubble() } func makebubble() { let bubbleTexture = SKTexture(imageNamed: "bubble") let bubble = SKSpriteNode(texture: bubbleTexture) let bubbleRadius = bubbleTexture.size().height/2 let bphysicsBody = SKPhysicsBody(circleOfRadius: bubbleRadius) bphysicsBody.isDynamic = true bphysicsBody.usesPreciseCollisionDetection = true bphysicsBody.restitution = 0.5 bphysicsBody.friction = 0 bphysicsBody.angularDamping = 0 bphysicsBody.linearDamping = 0 bphysicsBody.categoryBitMask = ballCategory bphysicsBody.collisionBitMask = ballCategory | edgeCategory bphysicsBody.contactTestBitMask = ballCategory | edgeCategory bubble.physicsBody = bphysicsBody bubble.name = "bubble" // 随机位置预留气泡半径偏移,避免初始位置越界 let x = CGFloat.random(in: bubbleRadius...(size.width - bubbleRadius)) let y = CGFloat.random(in: bubbleRadius...(size.height - bubbleRadius)) bubble.position = CGPoint(x: x, y: y) addMyChild(node: bubble) } func addMyChild(node:SKSpriteNode){ self.addChild(node) node.physicsBody!.applyImpulse(CGVector(dx: 10.0, dy: -2.0)) nodeCount += 1 }
SwiftUI端调用参考:
SpriteView(scene: YourBubbleScene(size: CGSize(width: WKInterfaceDevice.current().screenBounds.width, height: WKInterfaceDevice.current().screenBounds.height))) .ignoresSafeArea()
内容的提问来源于stack exchange,提问作者user11270714
相关产品推荐
相关产品推荐

