Weird behavior when applying max speed on different actors
Hello everyone,
I’m seeing a weird behavior regarding the apply max speed setting so I was wondering if anyone here could help me understand what is happening. To summarize the problem: actors with same max speed applied are moving with different speeds, even though the display text behavior (which I’m using to debug) claims that they are travelling at the same speed.
To understand what I’m saying, consider this set up example:
1 – Create 2 actors and place them at the top of your display (same y coordinate). Apply max speed of 230 to both
2 – On the first actor, add a accelerate behavior (direction: 270 degrees, acceleration of 1500)
3 - On the second actor, add the move behavior (direction: 270 degrees, speed 230)
When you hit preview, they are going to “race” to the bottom of the display and they should move at the same speed because you applied max speed of 230. However, that is not what happens. The actor with accelerate behavior moves with a speed slightly greater than the actor with the move behavior. The images attached show this. They were taken a couple of seconds apart (the red actor is the one with the accelerate behavior). You can see that he is about to win the race because he was moving faster. I used the display text to display the linear velocity y of them and it claims that they are both at speed of 230 but they are not.
What I find super weird is that there is clearly a max speed applied to the actor with the acceleration behavior, because if you untick this setting, his speed will be extremely high (because of the high acceleration of 1500). However, this max speed is not the one I had previously set.
My goal is to make them both move at the same speed, using accelerate behavior in one actor and move behavior on the other actor. Even though I could fix this by applying a lower max speed on the actor with accelerate behavior, I still can’t find a logic to this. And there is more, if I increase the acceleration, the speed difference will be greater, and I can’t find a linear correlation between these two attributes (max speed and acceleration). If I duplicate the accelerate behavior, they will work as additive and also provide a greater speed. It looks like the apply max speed setting on the actor with accelerate behavior is working kind of sloppy/half-assed.
Any insights? Am I missing something here?
Thanks!
Comments
I believe it's that Accelerate increases in speed over time so it will start slow and increase to 230. Where Move starts and keeps constant at 230. I suspect if they had enough distance/time the two actors would even out and stay equal. If you use both Accelerate OR both Move behaviors I would expect you'd see both actors acting identically.
Edit: So I just tested this and what I see happening is that because the Accelerate starts slow and builds to its max speed it will always lag behind the actor with the Move Behavior. The Move Behavior keeps the actor (from the start) moving at its top speed (You won't need to use max speed on this actor). There will always be a gap between the two because of the lag time of the Accelerate Behavior building up to its max speed. Once it reaches its top speed the actor with the move behavior is already out in front and that space with stay consistent the rest of the time.
http://jamie-cross.net/posts/ ✮ Udemy: Introduction to Mobile Games Development ✮ Learn Mobile Game Development in One Day Using Gamesalad ✮ My Patreon Page
Hello @jamie_c , you are right that it takes some time for the actor with accelerate behavior to reach its max speed (it is a fraction of seconds in my example because of the high acceleration used). During this period it is normal to see a gap between them, but after it builds up to max speed the gap between the actors is not constant (and it should be!).
The pictures I provided were taken after the actor with accelerate behaviour had reached its maximum speed (230), but you see in the picture taken seconds later that he is ahead of the actor with the move behavior.
To make sure you visualize this bug, I recommend using portrait and lowering the size of actors to 30 x 30. You can also add a rule to change their position to the top of the screen once they reach the bottom. With that you can see the phenomenon stacking up. The gap between them will become so big that eventually the actor with accelerate behavior will catch up with the actor with the move behavior!
I see, when I set it up exactly like you describe the actor that uses Accelerate continues to 'lap' the actor with the Move Behavior.
http://jamie-cross.net/posts/ ✮ Udemy: Introduction to Mobile Games Development ✮ Learn Mobile Game Development in One Day Using Gamesalad ✮ My Patreon Page
Another bug that I found is that stacking multiple accelerate behaviors inside an actor makes it go beyond the max speed. So, what I am seeing here is that a max speed is, in fact, applied, which prevents the actor from accelerating indefinitely. However, this max speed is not the one I set (230 in my example). It is this preset value plus a delta factor that is proportional to how many accelerate behaviors you stacked in the actor and the acceleration value used.
Does anyone relate to that?
@Baguvix so this will be a bit of a pain, but i think you might need to add a rule to set the speed attribute after it reaches or goes beyond the max speed (which is beyond the point of having max speed, but bear with me).
I think the problem you're running into is related to how the game loop works I think.
I'm guessing that Box2D, rather than hard setting the max speed when reached is doing a dynamic thing. It accelerates, checks max speed, stops the acceleration.
As long as the acceleration is active, it pushes the simulated object to accelerate before clamping the max speed.
Of course, that also may be us, but I'm pretty sure (from memory), that we leave that kind of stuff up to Box2D.
So for now you'll need to manually fix your max speed (I got the desired behavior by using a rule). We can look into fixing it for a future release, but problems this deep in behaviors tend to need more testing and we're in the middle of an android update sprint (getting the android build more modernized to make future ad network updates easier and looking at setting the ground work for expansion files).
Hi @adent42 , thank you so much for your explanation and insight! It feels better to at least understand what is happening. I tried to set the max speed of my actor after he's reached the max speed but it didn't seem to work. The way I found to partially fix this is by putting the accelerate behavior inside a rule that is true only when the actor speed is lower than the max speed. In other words:
when magnitude( self.Motion.Linear Velocity.X , self.Motion.Linear Velocity.Y ) <= max speed
{
accelerate
}
So, this basically works as a ''custom apply max speed''. It doesn't matter the acceleration value I use or how many accelerate behavior I have inside the rule, the actor holds its max speed.
However, this doesn't work inside my game because I'm actually using the ''accelerate to'' behavior to make the enemy chase the player to its X and Y coordinates. So, when it reaches the max speed, the rule deactivates and the enemy loses track of the target, messing up the chase. Therefore, I couldn't use this approach, unfortunately.
Right now the best workaround I found is to set a lower max speed. So I'm considering the theoretical max speed and the real max speed. I could not find a formula to relate these two so it was a method of trial and error. I found that if I want the actor to move at a max speed of 230 using an acceleration of 1500, I need to set its max speed to 205 (I know...crazy...but it works, just put an actor with the move behavior and speed of 230 next to it to see I'm not wrong!). Since I'm using multiple combinations of acceleration and max speed in my game according to the level, I created a spreadsheet that correlates these two inputs (acceleration value and theoretical max speed) to the output (real max speed). After setting everything up my enemies are finally behaving properly and moving at the speed I want.
The only remaining problem happens when multiple rules that control my enemy's AI are triggered, subjecting the actors to more than one accelerate behavior. When this happens, the bug is intensified (because it is proportional to the number of accelerate behaviors) and actors won't hold to my preset max speed. But I think I managed to minimize this problem to a level that is almost unperceptive (and not annoying).
But, since you mentioned, I would love to have this problem fixed in a future release, it would save me a lot of time by just ticking the ''apply max speed'' box and see the max speed I want working properly, but I understand it's not the focus at the moment.
I'm still carrying further investigation and trying other methods to crack this up! If you have any other ideas, please share, I will be happy to give them a shot!
Thank you one more time!
using the constrain behavior with min and max values would work better, wouldn’t it?
Hello @bob loblaw , thanks for joining the discussion. I tried adding a rule that constrain the linear velocity of my actor to the max speed when it is greater than the max speed. It didn't work, sadly. Same problem still happens.
Is this what you suggested? If not, would you mind elaborate it?
not quite. i was thinking more just using the constrain behaviour within your actor to constrain attribute linearVelocityX (min, ( ....)), no rule though.
i can’t recall of the top of my head what values to plug where to set your minimum and maximum limits, but i think it might work for what you’re asking.
i’ll take a look next time i fire up gamesalad, but there’s a function in the drop down box to set minimum and maximum values. if you do a quick search for it there should be a thread or youtube video, you might find something before i get back on here.
Sounds interesting... I'll definitely give it a try, thanks!
have a look at this tutorial from gshelper/tshirt booth about constraining min/max values. it's not exactly what you were asking, but it is the concept I was talking about. so instead of constraint self.position. x/y, you'd use self.motion.linearVelocity. x/y, keeping in mind (I am pretty sure you can use) negative values for the velocity if the object is moving down or left. fingers crossed that helps.
edit: so I just had a play around with it, testing it on an object with its own local gravity set to accelerate 200 @ 270 degrees (this behaviour will keep accelerating at 200 and increasing speed infinitely).
if you replace accelerate with the behaviour: constrain attribute: self.motion.linearVelocity.y to: min(-200) it will "fall" at a constant rate of 200 (or move at a speed of -200 on the y axis).
you shouldn't need any rules or more logic to keep the speed fixed using that.
you can also use the max function for an object that needs to move right/up, or combine the two, as shown in the linked video if moving +/- on both axis.
hope that helps.
@bob loblaw I appreciate it, I'm not at home right now so I'll take a look next weekend, thanks a lot!