Open musjj opened 9 months ago
You could use tracks, but you'd have to recreate the looping tween which would be tedious. A simple-ish approach would be to add a wrapper that can have it's own animator which can do the rotation.
A similar need I have (I'm not sure if this should go here or in a new issue) is to tell a tween to run after the current tween. So for example, when my player is hit, I want them to flash red, and afterwards start animating their alpha to indicate an invulnerability state. (This might not be the correct way to approach the problem, I'm not sure yet).
To do this I need one of the following:
.then(self, &tween)
method on the Tweenable
trait, and a way of owning animator.tweenable()
in order to be able to call it (since Sequence::then
only accepts an owned self
, not a reference).then
method on the animator itself (which will probably use the .then
I suggested)animator.tweenable()
into Sequence::from_single
(or ::new
or the likes).I also need a way to know when the current animation will end - but I think I can get that via the existing total_duration
, which seems great
The second option is probably the best one, but I'm too new to writing APIs in rust to have a clear idea. Also, I could see a world in which it is just a bad idea to allow enqueuing more animations from the outside.
@musjj sorry I completely missed this issue.
The problem is that this requires you to put more than one Animator
component on the entity, which is currently not possible in Bevy. Is there a good solution for this use-case?
Yes indeed. So you're stuck with a single animator, unless you can reparent your scaled object to an invisible rotating one? If not, then the way I'd approach it in this case given the two animations are widely different is to put the logic into a custom Lens
, where you always apply the rotation, and conditionally apply the scaling when needed. You will need to use some form of Arc
to share the lens (or some of it's fields) with the animator. And it's a bit awkward if the scaling doesn't start in sync with the rotation nor has the same duration, but you can figure some delayed t
value inside the lens from the first time the scaling is activated I think. Definitely more complex than it should, but I don't see a good solution at least until we have dynamic queries in Bevy ECS.
@guyguy2001
So for example, when my player is hit, I want them to flash red, and afterwards start animating their alpha to indicate an invulnerability state.
I'm not sure I understand. It seems that you want to animate first the color and then the alpha of the same material or sprite? If so, you can just use Tracks
and enqueue two Tween
s one after the other.
If, on the other hand, you're trying to execute a tweenable on one Animator
and synchronize it with another tween on a different Animator
, then yes there's no good built-in solution for this. One workaround I can think of is if you know the duration of each individual tweenable, you can insert delays to indirectly synchronize them based on time.
I think a simple solution would be to allow Animator
to target an entity other than itself. For example:
Animator::new(tween).with_entity(entity)
This way you can just spawn multiple animator entities targeting the entity you want. This is similar to the approach used by bevy_tween, except that it traverses up the parent hierarchy until it finds a target marker.
Let's say I have an entity that is set up with a tween targeting the entity's
transform.rotation
. The tween loops infinitely throughout the game.But I also want to have a system that can insert a new tween that targets said entity's
transform.scale
, depending on the state of the game. The tween loops only once. I also want to be able to replay that tween, depending on the game state.The problem is that this requires you to put more than one
Animator<Transform>
component on the entity, which is currently not possible in Bevy. Is there a good solution for this use-case?