SwiftUI: Repeat animation forever with delay at the end, without autoreverse - swift

I want to repeat an animation forever, without it to autoreverse, and with a delay/pause between the repetitions after the animation played.
I know there is a .delay() modifier, but it delays the beginning of the animation:
let ani = Animation.easeInOut.delay(1.0).repeatForever(autoreverses: false)
In addition with the .repeatForever modifier, after the animation played it immediately jumps back to its beginning. But I want the last keyframe to remain visible on the screen for a short amount of time.
I’ve also tried it the other way around, adding a .delay() after the .repeatForever modifier, but without success (delay has no effect).
let ani = Animation.easeInOut.repeatForever(autoreverses: false).delay(1.0)
How can I add a delay after the animation played?

Related

How to make play an animation from current frame until N seconds en Rive

I have an animation and an input, I want to play my animation N seconds from current frame every time my input change his value
I was using scrub function but that only jumps between frames, that help to has controll over the animation but it seem a little laggy

How to keep the animation at the end without restarting?

not loop disable/enable but to keep the animation at it's end frame.
the animation pointing is starting by default but when the state getting to the end the animation ending and not playing again. if i make it loop it will start over again when ending but i don't want it to start over again but to stay on the last frame.
The pointing animation make the player pointing with the finger on a target :
i want the animation to stay at this frame or the last frame so the hand and finger will point all the time and not starting over again.
but this way the hand when the state finish playing move back down.
I tried to enable loop and then to enable also loop pose but didn't work so i tried to change the root transform rotation , root transform position Y , root transform position x-z to bake into pose but nothing of that worked yet.
A working solution is to set the key frames of the animation to the two frames where you want to keep the animation at when playing it.
In my case it's frames 78-79 : I set the frames 78 as the Start and frame 79 as the End. Loop time and Loop pose both disabled unchecked.

Move During playing Jump Animation

So the case is that I have a 36 frames long jumping animation and the jump itself starts at frame 12, where my object raises along y axis.
What would be the most easiest way to move my object forward while it's in air(during frames 12-36)?
How is jumping with animation generally done in games? I don't think my way is the best one. But I would also like to know how its usually done in my way too. Thanks
I have just read the comments and your question. Why not write this code:
Whenever You want him to jump at whatever condition:
Here I'll show you how to do it onClick of Space i.e, whenever you click space the jump animation plays whatever animation you have now the object moving in y-axis
if(Input.GetKeyDown(Keycode.Space))
{
yourPlayerAnimator.setBool("TheAnimatorCondition",true); //Bool for your animation to play if u have a idle with you.
}
if(yourPlayerAnimator.GetBool("TheAnimatorCondition")== true)
{
transform.Translate(Vector3.forward * Time.deltaTime)
}
All these Happens inside void update
Animation transition is your friend.
Put any condition when jumping to move to another animation. In this case i.e. when pressed left displacement key, move from "jump" to "jump&moveleft" or similar and when unpress return to jump state increasing the frames you spent moving to left.

Drawable presented late, causes steady state delay

I have a little Swift playground that uses a Metal compute kernel to draw into a texture each time the mouse moves. The compute kernel runs very fast, but for some reason, as I start dragging the mouse, some unknown delays build up in the system and eventually the result of each mouse move event is displayed as much as 4 frames after the event is received.
All my code is here: https://github.com/jtbandes/metalbrot-playground
I copied this code into a sample app and added some os_signposts around the mouse event handler so I could analyze it in Instruments. What I see is that the first mouse drag event completes its compute work quickly, but the "surface queued" event doesn't happen until more than a frame later. Then once the surface is queued, it doesn't actually get displayed at the next vsync, but the one after that.
The second mouse drag event's surface gets queued immediately after the compute finishes, but it's now stuck waiting for another vsync because the previous frame was late. After a few frames, the delay builds and later frames have to wait a long time for a drawable to be available before they can do any work. In the steady state, I see about 4 frames of delay between the event handler and when the drawable is finally presented.
What causes these initial delays and can I do something to reduce them?
Is there an easy way to prevent the delays from compounding, for example by telling the system to automatically drop frames?
I still don't know where the initial delay came from, but I found a solution to prevent the delays from compounding.
It turns out I was making an incorrect assumption about mouse events. Mouse events can be delivered more frequently than the screen updates — in my testing, often there is less than 8ms between mouse drag events and sometimes even less than 3ms, while the screen updates at ~16.67ms intervals. So the idea of rendering the scene on each mouse drag event is fundamentally flawed.
A simple way to work around this is to keep track of queued draws and simply don't begin drawing again if another drawable is still queued. For example, something like:
var queuedDraws = 0
// Mouse event handler:
if queuedDraws > 1 {
return // skip this frame
}
queuedDraws += 1
// While drawing
drawable.addPresentedHandler { _ in
queuedDraws -= 1
}

Flare/Flutter: How to reset the progress of an animation before starting it?

I have a Flare file with 3 animations contained within it, all in the same artboard. I understand that when switching between animations, Flare will mix the animations together by default, and that playing one animation will not reset the relevant nodes values back to what they were on frame 0 in the editor. That is the behavior I would like to achieve: when playing a new animation, I would like the previous animation to stop completely (don't mix them at all) and for the incoming animation to start at the very beginning with all its default values.
The use case is this:
Play an animation where, say, the opacity of a shape goes down to zero
Play a different animation that uses the shape from above, but in the Flare editor its opacity is 1 at the start of the animation
Desired result: the new animation resets the opacity of the shape and then begins and plays like normal
Actual result: since the previous animation changed the shape's opacity, the new animation will use the shape how it is instead of how it was created in the editor
For my question as explained on GitHub you can look at the end of the thread on this issue (has gifs): https://github.com/2d-inc/Flare-Flutter/issues/14
In the above thread, Luigi Rosso mentions "re-instancing" the artboard. Does anyone know what he means by this and how to do it? I have tried several methods of doing this such as the makeInstance methods found on classes such as FlutterActorArtboard, ActorNode and some others (there are a few variants of the makeInstance method but they are all similarly named and return a new artboard. However, I had no luck with replacing the current instance of my artboard in a FlareController implementation so far.
I have also tried to manually loop through all of the ActorNodes of the artboard and first saving their initial values and then copying the saved values to the artboard every time a new animation is played, but this seemed to break things pretty badly (the animation was unrecognizable and just didn't play correctly after that, so I must have done something wrong. Or I'm resetting the wrong values).
Any help is appreciated, thanks!
For playing a different animation on a shape and resetting its opacity, you can access the opacity of the node at runtime with:
ActorNode myNode = _artboard.getNode("nodeString");
myNode.opacity = 0.00;
As outlined here in the manual.
More simply, in the new animation, you can set a keyframe in the Rive/Flare editor for the opacity to be 1 at the start of the new animation, so that when it plays the animation from the beginning its opacity will be reset to 1.
For playing one animation, then overriding it completely when the next animation plays you can extend the FlareController and create a custom animation controller to do this in the advance method.
Here's a quick and dirty example (not best practices) to give you an idea of using advance:
https://gist.github.com/she-who-codes/85d8f0da97abfc3ecc43b1cb470e9c29
https://gist.github.com/she-who-codes/ce633204cd2d4babfe9a5b54e34ca63d