SceneKit - 如何添加动画来改变 SCNNode 的颜色?

SceneKit - How to Add Animations to Change SCNNode's Color?

我想知道如何使用 Swift.

为 SCNNode 的颜色设置动画

例如:我希望节点不断改变颜色,或者我希望节点从黑色逐渐变为蓝色。

我是使用 SCNAction fadeIn 还是 fadeOut

您可以创建自定义操作。

如果场景中有红色球体

let sphereNode = scene.rootNode.childNode(withName: "sphere", recursively: false)!
sphereNode.geometry!.firstMaterial!.diffuse.contents = UIColor.red

这就是您构建自定义操作的方式

let changeColor = SCNAction.customAction(duration: 10) { (node, elapsedTime) -> () in
    let percentage = elapsedTime / 5
    let color = UIColor(red: 1 - percentage, green: percentage, blue: 0, alpha: 1)
    node.geometry!.firstMaterial!.diffuse.contents = color
}

最后你只需要运行球体上的动作

sphereNode.runAction(changeColor)

结果

@Luca Angeletti 那里得到灵感,我编写代码以便我们可以在任何颜色之间设置动画,包括它们的 alpha:

func aniColor(from: UIColor, to: UIColor, percentage: CGFloat) -> UIColor {
    let fromComponents = from.cgColor.components!
    let toComponents = to.cgColor.components!

    let color = UIColor(red: fromComponents[0] + (toComponents[0] - fromComponents[0]) * percentage,
        green: fromComponents[1] + (toComponents[1] - fromComponents[1]) * percentage,
        blue: fromComponents[2] + (toComponents[2] - fromComponents[2]) * percentage,
        alpha: fromComponents[3] + (toComponents[3] - fromComponents[3]) * percentage)
    return color
}

使用:

let oldColor = UIColor.red
let newColor = UIColor(colorLiteralRed: 0.0, green: 0.0, blue: 1.0, alpha: 0.5)
let duration: TimeInterval = 1
let act0 = SCNAction.customAction(duration: duration, action: { (node, elapsedTime) in
    let percentage = elapsedTime / CGFloat(duration)
    node.geometry?.firstMaterial?.diffuse.contents = self.aniColor(from: newColor, to: oldColor, percentage: percentage)
})
let act1 = SCNAction.customAction(duration: duration, action: { (node, elapsedTime) in
    let percentage = elapsedTime / CGFloat(duration)
    node.geometry?.firstMaterial?.diffuse.contents = self.aniColor(from: oldColor, to: newColor, percentage: percentage)
})

let act = SCNAction.repeatForever(SCNAction.sequence([act0, act1]))
node.runAction(act)

我正在使用这个功能; 您只需提供 material 的名称、动画需要多长时间以及当前颜色和 将达到哪种颜色。

您将颜色作为数组(红色、绿色、蓝色和 alpha);

 let startColor: [CGFloat] = [0.5, 0.5, 1, 1]
 let targetColor: [CGFloat] = [1, 1, 1, 1]

这就是你调用函数的方式;

   changeColorWithAnimation(duration    : 5,
                            materialName: myCubeMaterial,
                            start       : startColor,
                            end         : targetColor)






 func chageColorWithAnimation(duration: CGFloat,
                                     materialName: SCNMaterial,
                                     start: [CGFloat],
                                     end: [CGFloat]){

    let rs = (end[0] - start[0]) / duration
    let gs = (end[1] - start[1]) / duration
    let bs = (end[2] - start[2]) / duration
    let alphas = (end[3] - start[3]) / duration


    let changeColor = SCNAction.customAction(duration: TimeInterval(duration)) { (node, elapsedTime) -> () in

        let red = start[0] + rs * elapsedTime 
        let green = start[1] + gs * elapsedTime 
        let blue = start[2] + bs * elapsedTime 
        let alpha = start[3] + alphas * elapsedTime

        materialName.diffuse.contents = UIColor(displayP3Red:red,
                                                green: green,
                                                blue: blue,
                                                alpha: alpha)
    }
    rootNode.runAction(changeColor)
}