Tween "crossfading?"

Greetings,

I’m making a prototype, and I would like to use tweens in it.

Here, I have the ball jiggling whenever it bumps into a wall, jiggling only a little bit when bumping slower, and very slightly jiggling when moving (The latter is very subtle and hard to see here)
GDevelop_XWP0TxEFhj

It might not look to clear because of ShareX’s framerate, but there’s a minor issue…

The tweens conflict with each other.

When a tween triggers, another tween already in effect will likely prioritize, messing up the animations.

Also, for the tween that jiggles when you move, if you let go, it stays at it’s current size instead of reverting back to it’s original size.

I’m aware we have things like “Remove tween,” but if it’s meant to be spammed everywhere where tweens conflict, that seems a bit cumbersome to type AND read.

Here’s the code so far:


I plan to add more tweens later, so I want to get this taken care of now so it doesn’t become harder later on.

So, basically, is it possible to “crossfade” tweens in GDevelop? And if so, what’s the most proficient way to approach it?

Do I need to make a “tween state machine,” that only uses the tweens when a state variable is activated?
Do I need to make a function that tweens the ball back to it’s original size before starting the next tween?
Is there some way to remove tweens in bulk to make the code cleaner, or a way to prevent removing the same tweens over and over again?

I’m going to try out some of these things, but a step in the right direction would be appreciated if you can. Thanks

I don’t fully understand your process. It might be easier to handle the scaling with a time based formula or a formula based on a tweened variable or a value.

Observations. If only 1 tween can play at a time then you can use the same tween name. This would remove the need for all of the different finished conditions and removals.

Tweens are based on time. You can use a formula for time. Maybe, think of it as speed instead of time. When the tween starts, you know the distance you want to travel (the difference between the current scale and the target scale), you know the speed, you would need to calculate the time based on those other values.

It’s like if you wanted to move an object to where the screen was clicked. With a fixed time it would move faster or slower based on how close it was to the destination because it’s moving based on time.

It would move slowly when it only had to move a little and it would move quickly if it had to travel a large distance in the same amount of time.

In this example, you could calculate the time based on the distance and desired speed. (distance/speed) I think that’s right.

I hope that might inspire you. I still don’t know if tweens are the best approach. IMO, a more dynamic formula might be smoother either based on a counter or time maybe using cos() and sin() imagine it as a changing waveform.

There is extra overhead when adding and removing tweens.

1 Like

Thank you for your insight, although, I’m confused on what you mean by this:

Are you saying that all of the tween names here for example should just be called “jiggle?”

I’ve tried doing that, but sadly, since they’re all named the same thing, the engine doesn’t know which one to pick, so the animation just… freezes. Did you mean it someway else?

Anyways, I played around with this some more, and I added some new stuff to give me more control over my tweens.

As you can see in the above screenshot, I have a new tween called “crossfade,” which is supposed to automatically reset the object to it’s original size super fast to try and prevent any conflict with the upcoming tweens. I’ve set it all up and it works (The screenshot is from a while ago back from when it didn’t. THIS code doesn’t work, the screenshot below shows the right setup)!

Alternatively, I’ve even added a basic state machine for the tweens, so that the tweens only trigger if the state is activated. And so far, it seems to be working well.

Although, now that it’s all up and running, there’s another problem…

Let’s say there’s two or more bodies, for multiple players or perhaps NPCs (I’m controlling both here).

I put their states above them to demonstrate the issue:

GDevelop_ZGTEq8smkO

You can see that while the body’s OWN tweens no longer conflict, once you add more bodies to the map, THEIR tweens start to conflict with their friend’s tweens!

One of the balls has the “jiggleSmall” tween state, while clearly being idle, thus shutting off all of his animations until it’s state is reset some other way, like bumping against a wall.

Ofc, I would like for each body’s state to act independently from one another and not cancel each other’s tweens out.

I assumed that simply nesting everything underneath “Repeat for each” events would fix it, but sadly nope…

Something got messed up, but I can’t put my finger on exactly what…

IDK about your new issue but as far as what I meant by using 1 tween name is that you could start a tween with whatever settings you want and when the tween ended you would just have one tween finished and 1 tween to delete. You could use an object variable to track the current jiggle and start a new tween or whatever.

You could also create a structure of structures to store the different tween setting.

Jiggle.mode1.scale
Jiggle.mode1.time
Jiggle.mode1.easing

Then using the variable mode=“mode1” or “mode2” or whatever name you want to use.

Tween scale to Jiggle[mode].scale using Jiggle[mode].easing for Jiggle[mode].time

I prefer lean coding. The fewer events the better. It’s easier to read, debug and more efficient. I realize this is a sort of proof of concept project and it’s currently just a test.

I see, I’ll look into converting this into lean later on given the information you’ve provided.

For now, I think I found the cause of why the states are getting stuck. I used more debug information to make it more clear what might be going wrong here.

In fact, I can now set up this bug consistently to show it more clearly:
GDevelop_0Yf9FtW6nU

Basically, if a body is in the “jiggle” state for example, and the second body enters the same state while the first body is still in that state, it appears to get stuck. The only way to get it free again is to activate the “jiggleSmall” tween, and vise versa.

I’m not sure why it’s happening, considering they should just be able to act independently from each other?

EDIT: I tried doing the variable thing you told me about, and I don’t think I did it right…


With this setup, the jiggle state just doesn’t work at all? I’ve even tried using the “Tween doesn’t exist” conditions, and still nothing. Is this the wrong way?

Hi @Shadowbonnie7

Try using the “for each object” event and place your conditions / actions in it.

It could be the trigger once.it’s prevent the tween is finished from beimg checked. The trigger once is OK but tween has finished event probably needs to be outside of that group.

This was my idea using an array of structures. To test this, I used 3 objects with currentJiggle set from 0 to 2 and playTween set to true. You can add additional variables and use separate values for tween in and tween out.

Unfortunately, they already are nested under “For each” events and still getting stuck regardless…

Also, I tried to see if I can get it to work by moving the events around, but no luck, it still won’t work with this setup:

I even tried to use a more compact version of event chaining using the wait action instead:

Unfortunately, while using wait DOES work, it doesn’t crossfade the tweens like I want. GDevelop’s documentation says this:

Basically, the way I have it set up currently, it just gives me more control over my tweens and how they interact with each other. As bulky as it may be, it’s currently up and running just fine (I plan to add an object group where objects can share these tweens, so I don’t have to retype so much).

Although, I DID take what I have an make it just a tiny bit neater. Moving copied events elsewhere and removing whatever events did nothing:

While I do greatly appreciate the alternate options provided, I just don’t feel like they’re exactly suited for the annoyingly specific outcome I have in mind (The variable option looks promising though, if I could just get it to work, I can test it out)…

But with all that aside, yeah, the problem where the states get stuck still persists, and as shown, nesting everything under “For each” events for some reason doesn’t fix it…?

It’s all good. Create your project as you want. Optimizing can come later. I don’t truly follow your methodology, so I don’t think I can help with this one.

I recreated a simpler version of your scene and after I tried several methods using “tween finished playing”, it seems to be broken. The two objects interfere with each other even if nested in a “for each” event. Even if I only placed one object in the scene and it bounces (collides) too quickly, the tween just simply gives up.

I also get why you don’t want to use wait, it just won’t work the way you want it.

Instead of “tween finished playing”, I checked the current X & Y scales of the object, if they match the values of the scale tween, then the next tween will run. I also added a number variable to make sure the tweens run in correct order (in case checking scale conditions match but not in the correct order).

Note: I couldn’t find tween scale X & Y in one event for some reason, so I had to add them separately, and you’ll probably want to the tween ID to be the same in all the actions (you can leave it empty “”).

You can do the same for the smaller jiggle, just make sure the tween ID is also the same (“”).

Good luck!

Video capture: video

How interesting, I tried this out using the code here:

Now the problem from before is now fixed! But in doing so, it introduced 4 new problems:

  1. The code is now bigger and harder to debug

  2. I don’t think the crossfade tween is working anymore

  3. The looping “move” tween doesn’t work at all. The state changes, but no tween. The variables aren’t cycling like they should

  4. This:
    GDevelop_4CcHpXpUCE

Basically, if my tween state changes before the current one finishes (In this case, jiggleSmall starts while jiggle is still playing), ALL the tweens just completely lock up…

Did I do it correctly, or is there more I need?

If the “tween finished playing” was working properly you wouldn’t be in this mess in the first place! It might be bigger but it follows simple steps and once everything is working, it’ll be easier to introduce new tweenStates if needed using the same steps.

You also need to set the tween ID to “”. Since all your tweens change the scale, they all need to have the same ID so they can cancel each other out when a new tween is triggered. (refer to the screenshot)

That’s because you didn’t reset the scales so the tween never starts. (refer to the screenshot)

Same as the 3rd point, you need to reset the scales on every new tweenState.

1 Like

What is the issue with this condition?

Note that “trigger once” should never be used in conditions where objects have several instances.
https://wiki.gdevelop.io/gdevelop5/all-features/advanced-conditions/#trigger-once

Maybe that’s why the tweens are not working properly for each instance then.

Ahhh, thank you, looking back, even though the code is bigger, it does allow me to be more specific with it.

Thanks for pointing out what I missed, I added them in, and now all the tweens are working exactly as intended, and crossfading nicely!

Sadly, now that all 4 of those problems are gone, the original problem has returned…

GDevelop_3uaxjGIPvd

Once again, if a body enters the same state that the other body is currently still in, it just gives up.

The code was set up completely differently, and yet, I still have the same problem as before. I feel like I’m so close, but don’t know what to do

After some trial and error, I finally discovered the most likely cause of this bug:


This block of code. More specifically, the string variable action that changes the state to idle. Disabling it yields much more consistent results, but still not perfect. The code STILL locks up, especially if there are more than 2 objects on the scene.

Plus, I still wish to have an idle state, as I wish to add an idle animation as well.

I also tried what davy said, removing the Trigger Onces since they aren’t checked per instance. Although, this has no effect either…

Should I just share the project file?

Yes share the project file and I’ll take a look, maybe I’ll find a solution to this.

Alright, here’s a link: Dropbox - Game Prototype - Simplify your life

Hello again,

Good news! It’s working now. Download from here