You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS SceneKit粒子系统如何强制粒子朝向指定方向/姿态?

iOS SceneKit粒子系统如何强制粒子朝向指定方向/姿态?

我太懂你这种憋屈的感觉了——好不容易做出来的同心圆粒子,不管怎么调参数都死磕着X方向不放,旋转父节点、加动画控制器全不管用,SceneKit的文档又说得模棱两可。我之前做类似的径向扩散粒子时也踩过几乎一模一样的坑,其实问题出在你没抓住粒子初始朝向的控制逻辑,还有几个被忽略的关键属性。

先拆解下你之前的尝试为什么没用:

  • 旋转父节点pNode:粒子系统的朝向是基于自身发射坐标系的,而你用birthDirection = .surfaceNormal时,粒子的初始朝向默认和发射法线绑定,父节点旋转只会挪位置,改不了粒子自身的朝向逻辑
  • 用propertyControllers调rotationAxis和angle:一是你没给粒子一个明确的初始朝向基准,二是.free模式下粒子的初始朝向还是由birthOrientation(默认是.direction,即和运动方向绑定)决定的,动画相当于在错误的初始状态上做修改,自然看不到效果

正确的解决方案:固定粒子朝向的核心调整

要让粒子牢牢朝向Y轴向上(或任意指定方向),你只需要修改3个关键属性,再配合正确的初始朝向设置:

1. 切断粒子朝向和运动方向的绑定

默认birthOrientation = .direction会让粒子的初始朝向和运动方向(你这里是球体表面法线)完全绑定,所以第一步要把它改成.fixed,让粒子朝向不受运动方向影响:

particleSystem.birthOrientation = .fixed

2. 设置固定朝向模式

用orientationMode = .fixed让粒子始终固定在粒子系统的本地坐标系,不会随相机角度、粒子运动改变朝向:

particleSystem.orientationMode = .fixed

3. 给粒子设置目标朝向(Y轴向上)

SceneKit粒子的默认“正面”是Z轴正方向,要让它转向Y轴向上,我们需要给它一个绕X轴旋转90度的四元数(把Z轴转到Y轴的方向),用particleOrientation属性设置:

// 绕X轴旋转π/2(90度),让粒子正面朝向Y轴向上
particleSystem.particleOrientation = SCNQuaternionMakeRotation(Float.pi / 2, 1, 0, 0)

完整修改后的代码片段

把这些调整加到你的原代码里,最终的粒子系统部分是这样的:

let particleSystem = SCNParticleSystem()
particleSystem.particleImage = UIImage(named: "circle.png")
particleSystem.emitterShape = SCNSphere(radius: 0.01)
particleSystem.birthLocation = .surface
particleSystem.birthDirection = .surfaceNormal
particleSystem.birthRate = 0.4
particleSystem.acceleration = SCNVector3(0, 0, 0)

// 核心朝向控制代码
particleSystem.birthOrientation = .fixed
particleSystem.orientationMode = .fixed
particleSystem.particleOrientation = SCNQuaternionMakeRotation(Float.pi / 2, 1, 0, 0)

// 粒子大小动画部分保持不变
let sizeController = SCNParticlePropertyController()
let sizeAnimation = CAKeyframeAnimation(keyPath: "particleSize")
sizeAnimation.values = [0.1, 0.4]
sizeAnimation.keyTimes = [0.0, 1.0]
sizeController.animation = sizeAnimation
particleSystem.propertyControllers = [.size: sizeController]

let pNode = SCNNode()
pNode.addParticleSystem(particleSystem)
rootNode.addChildNode(pNode)

额外说明:如果需要动态调整朝向

如果你之后想让粒子在生命周期内改变朝向(比如从X方向转到Y方向),可以用SCNParticlePropertyController给.rotation属性加动画,比如:

let rotationController = SCNParticlePropertyController()
let rotationAnim = CAKeyframeAnimation(keyPath: "rotation")
// 从初始X方向转到Y方向的四元数
let startRot = SCNQuaternionMakeRotation(0, 0, 0, 0)
let endRot = SCNQuaternionMakeRotation(Float.pi / 2, 1, 0, 0)
rotationAnim.values = [NSValue(scnQuaternion: startRot), NSValue(scnQuaternion: endRot)]
rotationAnim.keyTimes = [0.0, 1.0]
rotationController.animation = rotationAnim
particleSystem.propertyControllers[.rotation] = rotationController

这种方式适合.free模式下的动态朝向变化,不过你现在的需求用固定模式就足够了。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 12:13:07