RealityKit - Animate opacity of a ModelEntity?
Asked Answered
S

4

8

By setting the color of a material on the model property of a ModelEntity, I can alter the opacity/alpha of an object. But how do you animate this? My goal is to animate objects with full opacity, then have them fade to a set opacity, such as 50%.

With SCNAction.fadeOpacity on a SCNNode in SceneKit, this was particularly easy.

let fade = SCNAction.fadeOpacity(by: 0.5, duration: 0.5)
node.runAction(fade)

An Entity conforms to HasTransform, but that will only allow you to animate scale, position, and orientation. Nothing to do with animation of the material for something like fading it in or out. The effect is in RealityComposer if you create a behavior for animating hide or showing, but there doesn't seem to be something similar to HasTransform to provide functionality for animating opacity.

I've been all around the documentation looking for something, my next idea is essentially creating a custom animation to replace this behavior, but it seems like it should be available and I am just not finding it.

Schubert answered 16/1, 2020 at 8:4 Comment(0)
M
2

I tested it using different techniques and came to the sad conclusion: you can't animate a material's opacity in RealityKit framework because RealityKit materials don't support animation at runtime (for now I hope). Let's wait for RealityKit's major update.

Here's a code you can use for test

(arView.alpha property just works):

import UIKit
import RealityKit

class ViewController: UIViewController {

    @IBOutlet var arView: ARView!

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        arView.alpha = 1.0 
        opacityAnimation()
    }

    func opacityAnimation() {

        UIView.animate(withDuration: 5.0,
                         animations: {

            self.arView.alpha = 0.0
        })
    }
}

And use this code snippet in order to make sure that animation doesn't work properly

(there's no animation process, just value assignment):

import UIKit
import RealityKit

class ViewController: UIViewController {

    @IBOutlet var arView: ARView!
    let tetheringAnchor = AnchorEntity(world: [0,0,0])
    var material = SimpleMaterial()
    let mesh: MeshResource = .generateSphere(radius: 0.5)
    var sphereComponent: ModelComponent? = nil

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        material.metallic = .float(1.0)
        material.roughness = .float(0.0)
        material.baseColor = .color(.red)

        sphereComponent = ModelComponent(mesh: mesh,
                                    materials: [material])

        tetheringAnchor.components.set(sphereComponent!)
        arView.scene.anchors.append(tetheringAnchor)

        opacityAnimation()
    }

    func opacityAnimation() {

        UIView.animate(withDuration: 5.0,
                         animations: {

            self.material.metallic = .float(1.0)
            self.material.roughness = .float(0.0)
            self.material.baseColor = .color(.green)

            self.sphereComponent = ModelComponent(mesh: self.mesh,
                                             materials: [self.material])

            self.tetheringAnchor.components.set(self.sphereComponent!)
            self.arView.scene.anchors.append(self.tetheringAnchor)
        })
    }
}
Mignonmignonette answered 16/1, 2020 at 11:59 Comment(1)
still no way to do this properly in 2023?Khelat
K
2

As @AndyFedo says there is currently no way to animate the opacity nor alpha of an Entity.

Even changing a SimpleMaterial at run time currently results in flickering.

Having said this I was able to animate the Alpha of a SimpleMaterials Color, however based on testing it is in no way optimal or recommended for that matter.

But just in case you wanted to try to further experiment with this avenue please see an attached example which assumes that you only have a single SimpleMaterial:

class CustomBox: Entity, HasModel, HasAnchoring {

  var timer: Timer?
  var baseColour: UIColor!

  //MARK:- Initialization

  /// Initializes The Box With The Desired Colour
  /// - Parameter color: UIColor
  required init(color: UIColor) {
    self.baseColour = color
    super.init()
    self.components[ModelComponent] = ModelComponent(mesh: .generateBox(size: [0.2, 0.2, 0.2]),
                                                     materials:  [SimpleMaterial (color:  baseColour, isMetallic: false)]
    )
  }

  required init() { super.init() }

  //MARK:- Example Fading

  /// Fades The Colour Of The Entities Current Material
  func fadeOut() {

    var alpha: CGFloat = 1.0
    timer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { timer in

      if alpha == 0 {
        timer.invalidate()
        return
      }

      var material = SimpleMaterial()
      alpha -= 0.01
      material.baseColor = MaterialColorParameter.color(self.baseColour.withAlphaComponent(alpha))
      material.metallic = .float(Float(alpha))
      material.roughness = .float(Float(alpha))
      DispatchQueue.main.async {
        self.model?.materials = [material]

      }
    }
  }
}

As such just to test you can create and then call the function like so:

let box = CustomBox(color: .green)
box.position = [0,0,-0.5]
arView.scene.anchors.append(box)
box.fadeOut()

Also I would politely ask, that this answer not get downvoted as I am simply iterating the fact that (a) it isn't possible with any current built in methods, and (b) that it can in part be achieved albeit to a very limited extent (and thus currently; in a way which one would see fit for production).

Koy answered 18/1, 2020 at 5:25 Comment(0)
Q
0

I don't know if it suits with your use case. But you should consider video material. As you can see in this WWDC session (2min45). An entity with complex pulsating opacity.

https://developer.apple.com/videos/play/wwdc2020/10612/

Quintic answered 16/10, 2020 at 15:56 Comment(0)
A
0

you can also create the fade in experience in Reality Composer and trigger the .rcproject file in Xcode. Have not tested other interactions with .rcproject but I know at least this can load a model to fade in into the scene.

Assumptive answered 4/3, 2021 at 20:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.