Similar to this question, I have an issue with the use of sequenced animations in RealityKit.
I have the following function:
func openSlider(duration: TimeInterval, stayingOpenFor: TimeInterval) {
let closedPosition = Transform(translation: RKVector(DoorwaySegment.normalDoorWidth * -0.5, (WallUtilities.wallHeight - DoorwaySegment.normalDoorHeight) / -2.0, 0.0))
let openPosition = Transform(translation: RKVector(DoorwaySegment.normalDoorWidth * -1.45, (WallUtilities.wallHeight - DoorwaySegment.normalDoorHeight) / -2.0, 0.0))
do {
let openAction = FromToByAction<Transform>(from: closedPosition, to: openPosition)
let openAnimation = try AnimationResource.makeActionAnimation(for: openAction,
duration: duration,
bindTarget: .transform)
let closeAction = FromToByAction<Transform>(from: openPosition, to: closedPosition)
let closeAnimation = try AnimationResource.makeActionAnimation(for: closeAction,
duration: duration + stayingOpenFor,
bindTarget: .transform, offset: stayingOpenFor)
let concatenated = try! AnimationResource.sequence(
with: [openAnimation, closeAnimation]
)
door.playAnimation(concatenated)
} catch {
print("failed to open/shut door")
}
}
which is supposed to open a door, pause for 5 seconds, and then close it again. The pause is provided by the stayingOpenFor
parameter, and the duration of each animation by duration
.
I have an event handler that triggers when the animation completes, to let me know when the animations have both completed. I can see that the overall length of the animation is correct however visually, it seems that as soon as the open action completes, the close action triggers, even though I've set an offset to delay the second action.
Given that RealityKit's library of actions and animations and the operations around them is so lacking by comparison to SceneKit, I can't see a way to inject a "wait" or "delay" between animations without having to build a more complex scheduler around RealityKit. I thought, given the descriptions for the "offset" parameter, and perhaps the "delay" parameter on makeAnimationAction
that these were the way to go, but thats not what I'm seeing.
In my opinion, this is a different question than the one you linked to. Your problem is much easier to solve than the previous one, no matter how strange it may sound. To solve your problem, you'll need three struct instances (openingAction
, dummyAction
and closingAction
), each of which will contain the values of the rotation angles. Since RealityKit doesn't have the identical convenient SceneKit's .wait(duration: 5)
type method at the moment, I created a "dummy" transform that doesn't change over time.
Launch my app and tap on the screen: the door will open, then there will be a one-second pause, after which the door will close. In order to simulate rotation relative to the door hinges, I created a pivot point
Entity().
import SwiftUI
import RealityKit
struct ContentView : View {
@State var sequenced: AnimationResource!
var door = ModelEntity()
let pivot = Entity()
let mesh = MeshResource.generateBox(width: 0.8, height: 2.0, depth: 0.05)
init() {
door = ModelEntity(mesh: mesh)
door.position.x += 0.4
pivot.addChild(door)
}
var body: some View {
RealityView { rvc in
rvc.add(pivot)
let openingAction = FromToByAction(
by: .init(yaw: .pi/2.5), // counter-clockwise
timing: .easeInOut
)
let dummyAction = FromToByAction(
from: .init(yaw: .pi/2.5),
to: .init(yaw: .pi/2.5)
)
let closingAction = FromToByAction(
from: .init(yaw: .pi/2.5),
to: .init(yaw: .zero), // clockwise
timing: .easeInOut
)
let openingDoor = try! AnimationResource.makeActionAnimation(
for: openingAction,
duration: 0.75,
bindTarget: .transform
)
let waitOneSec = try! AnimationResource.makeActionAnimation(
for: dummyAction,
duration: 1.00, // set any value
bindTarget: .transform
)
let closingDoor = try! AnimationResource.makeActionAnimation(
for: closingAction,
duration: 1.23,
bindTarget: .transform
)
self.sequenced = try! AnimationResource.sequence(
with: [openingDoor, waitOneSec, closingDoor]
)
}
.ignoresSafeArea()
.background(.black)
.onTapGesture {
pivot.playAnimation(sequenced)
}
}
}