[Improvement] SpeedUp Guard

While playing I noticed that the velocity of the ball kept increasing, which made it very difficult to win large levels. This increase in velocity is due to the random tweak that was added during the course.
To fix this problem I’ve put a SpeedUp guard in my code that activates when a certain velocity is measured.

  float actualVelocity = Mathf.Sqrt(rigidbody2D.velocity.x*rigidbody2D.velocity.x + rigidbody2D.velocity.y*rigidbody2D.velocity.y);
 		if (actualVelocity > 10){
 			// print ("Before " + actualVelocity);
			Vector2 decreaseVelocity = GetComponent<Rigidbody2D>().velocity;
			decreaseVelocity.x += (-0.3f * Mathf.Sign(decreaseVelocity.x));
			decreaseVelocity.y += (-0.3f * Mathf.Sign(decreaseVelocity.y));
 			GetComponent<Rigidbody2D>().velocity = decreaseVelocity;
 			// actualVelocity = Mathf.Sqrt(rigidbody2D.velocity.x*rigidbody2D.velocity.x + rigidbody2D.velocity.y*rigidbody2D.velocity.y);
 			// print ("After " + actualVelocity);
 			// print ("velocity adjusted!");
 		}

I added this block of code in the Update() method of my Ball.cs script.

What does it do:

  1. First of all it calculates the actual velocity of the ball. This is done by using the Pythagorean theorem
    (a2 + b2 = c2) and found in the first line of code. Because it is located in the Update method it will calculate this velocity every frame.

  2. It checks if the actual velocity is above a certain threshold. In my case I’ve put this threshold at 10, but this value depends on the starting velocity you give the ball and the possible increase due to the tweak. Just test it to find the right value that fits with your build.

  3. If the velocity is too high it will decrease it. Therefor we need to make a new vector which can modified, in my case this is ‘decreaseVelocity’. Both the x and y-value of this vector will be incremented with +0.3 or -0.3. The sign is the opposite of the original velocity (that is why I put in -0.3f and not 0.3f). So if the ball was going in the positive x direction, we want to increment with a negative x-value and the other way around. The same goes up for the y-value.

  4. After the incrementation, it gives this incremented vector back to the object.

I used the lines in comments to test this code and notice the difference in actual velocity before and after the adjustment. These lines can also be used to playtest and find the best values for the threshold and adjustments. First I thought that this sudden decrease in velocity would tamper with the natural flow of the game, but if you choose the right adjustment values (0.3 in my case) this change is barely noticed.

I hope this helps other people that came across this problem and please comment if you find something that I overlooked!

2 Likes

The same code can be used to speed up the ball should it reach a too low velocity.

This was a big help to my game. The ball would speed up really fast and fly off the colliders before I added your code snipper. Thanks so much!

Thanks Jonas. I will write something like this to my script. It is very easy way to do SpeedUp Guard. But best thing is you taugh logic of codes with descriptions. So im sure nobody is gonna copy and paste it. :slight_smile: :+1:

For abridge some code you can use:
float actualVelocity = Mathf.Sqrt(Mathf.Pow(rigidbody2D.velocity.x, 2) + Mathf.Pow(rigidbody2D.velocity.y, 2));
Instead of:
float actualVelocity = Mathf.Sqrt(rigidbody2D.velocity.x*rigidbody2D.velocity.x + rigidbody2D.velocity.y*rigidbody2D.velocity.y);

I’m happy I could help you with my code! I was getting annoyed with the speeding up myself, so I thought ‘why not try to fix it?’ :wink:

Thank you for the praises! And yea that part of the code could be simplified in the way you show it. At that time I didn’t know that mathf.pow exist :wink:

I have just learned, too and write here immediately :smiley:

I used this code to avoid altering the speed at all

Rigidbody2D rigidbody = GetComponent<Rigidbody2D>();
float speed = rigidbody.velocity.magnitude;
Vector2 tweak = new Vector2(Random.Range(-0.1f, 0.1f), Random.Range(-0.1f, 0.1f));
rigidbody.velocity = (rigidbody.velocity.normalized + tweak).normalized * speed;

I’m just saving the ball’s speed before making any alterations, tweaking the velocity, normalizing the result, then restoring it to its previous speed. I think it works fine?

I chose to allow the random tweaks to be negative, so that it doesn’t constantly favor going to the right.

If someone likes the idea of the ball speeding up over time, that can still be implemented that here with more control.

Hi Zach,

I actually didn’t think about extracting the velocity magnitude from the ball, but I guess it works perfect.
I just got two questions:

  1. Does the .normalized behind (rigidbody.velocity.normalized + tweak) work, because it looks a bit of a strange construction?
  2. Why not change the magnitude of the veloctity back to the previous speed after the alterations, instead of multiplying the vector with the speed?

I haven’t tried your code yet, but I can imagine this to be working.

Ive added the code and tweaked it for unity 5. I’m finding the ball is a tiny bit too slow. What would i change to make the default speed faster?

Hi Sam,

If you want to increase the starting speed you just need the change the vector you give the ball in the start method.
On the other hand if you want to increase the maximum velocity the ball can reach (ie the velocity around it will stay during the game), you need to change the parameter in the if-function:

if (actualVelocity > xxxxxx) => x’s represent the default speed you want to give to the ball. To increase the overall velocity just increase it to something more than 10. You can also change this to a public variable and be able to tweak it in-game.

I hope this helps you a bit and else just ask.

1 Like

Excellent Jonas, Thanks for sharing this!

1 Like

Hi Zach,
I actually didn’t think about extracting the velocity magnitude from the ball, but I guess it works perfect.
I just got two questions:

  1. Does the .normalized behind (rigidbody.velocity.normalized + tweak) work, because it looks a bit of a strange construction?
  2. Why not change the magnitude of the veloctity back to the previous speed after the alterations, instead of multiplying the vector with the speed?
    I haven’t tried your code yet, but I can imagine this to be working.

As I understand it, normalized and magnitude are both computed properties of a Vector. Normalized is a version of the vector with a length/magnitude of 1 (when using vectors to represent velocities, length is equivalent to the speed).

(rigidbody.velocity.normalized + tweak).normalized works because I’m adding a vector to another vector, and since the result is a vector, it has the normalized property. If it helps to make it more readable, you could write it out as
Vector3 tweakedVelocity = (rigidbody.velocity.normalized + tweak);
rigidbody.velocity = tweakedVelocity.normalized * speed;

You cannot change the magnitude property directly, as it is read-only, but multiplying a normalized vector by a number has the same effect.

Thank you for the clear explanation Zach!