- Home /
Increase ball speed by time
I am making a similar game to pong and wants to increase the speed by time like every ten seconds. I thought i could do it through my game timer, but I don't know were to start.
I am quite new to this and would really appreciate some help from you pros.
Here is my code:
Ball:
public static float speed = 500;
Rigidbody2D rb;
bool isPlay;
int randInt;
void Awake ()
{
rb = gameObject.GetComponent<Rigidbody2D> ();
randInt = Random.Range (1, 3);
}
void Update ()
{
if (Input.GetMouseButton (0) == true && isPlay == false)
{
transform.parent = null; //keeping the ball at (0,0,0) in worldspace
isPlay = true; //telling the game that the game is playing
rb.isKinematic = false; // making isKinematic box unchecked when the game is playing
if (randInt == 1)
{
rb.AddForce (new Vector3 (speed, speed, 0));
}
if (randInt == 2)
{
rb.AddForce (new Vector3 (-speed, -speed, 0));
}
}
And here is my timer script:
public Text timer; public float myTimer;
void Start () {
}
// Update is called once per frame
void Update ()
{
myTimer += Time.deltaTime;
int minutes = (int)myTimer / 60;
int seconds = (int)myTimer % 60;
timer.text = "Time: " + minutes.ToString() + ":" + seconds.ToString("00");
/*if (seconds += 10) // My try to do it
{
IncreaseBallSpeed = true
}
}
public static void IncreaseBallSpeed (bool speedIncrease)
{
if (speedIncrease = true)
{
Ball1.speed += 10;
}
}*/
Answer by DoTA_KAMIKADzE · Sep 26, 2015 at 05:06 PM
So you use static speed variable (don't forget to reset that one when needed - e.g. at the end of round or match) that you have in the other class, alternatively you could also use reference to that ball script if needed (would go that way for sure if you need to have more than 1 ball with different speed, just keep that in mind).
using System.Collections; //this is needed only for example #3
using UnityEngine;
using UnityEngine.UI;
//first of all few additions to Ball class
public class Ball : MonoBehaviour
{
public static float speed = 500f;
//here I've added few "constants" but not all of them should necessary be constant for that matter, that is just in order to keep things more polished, less prone to misstyping, expandability, etc...
public const float ballBaseSpeed = 500f;//this should be constant, use it to reset speed variable and/or as a reference to complex speed calculations
public const float ballUpgradeSpeed = 10f;//you can make this not constant if you'll need to tweak speed upgrades as time passes by
public const float ballUpgradeTime = 10f;//this one could also be not constant if you'll need to tweak upgrade timings as time passes by
//that's all
Rigidbody2D rb;
bool isPlay;
int randInt;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
randInt = Random.Range(1, 3);
}
void Update()
{
if (Input.GetMouseButton(0) == true && isPlay == false)
{
transform.parent = null; //keeping the ball at (0,0,0) in worldspace
isPlay = true; //telling the game that the game is playing
rb.isKinematic = false; // making isKinematic box unchecked when the game is playing
if (randInt == 1)
{
rb.AddForce(new Vector3(speed, speed, 0));
}
if (randInt == 2)
{
rb.AddForce(new Vector3(-speed, -speed, 0));
}
}
}
}
//this will be example using grading
//it will behave a bit strangely if your ballUpgradeSpeed will change over time
public class YourScriptExample1 : MonoBehaviour
{
public Text timer;
public float myTimer;
private int grade = 1;//current grade of speed, you can display it somewhere or upgrade/degrade on some events
private float lastTime = 0;//last time we upgraded speed
void Update()
{
myTimer += Time.deltaTime;
if (myTimer >= lastTime + Ball.ballUpgradeTime)
{
lastTime += Ball.ballUpgradeTime;
grade += 1;
Ball.speed = Ball.ballBaseSpeed + (Ball.ballUpgradeSpeed * grade);
//you can come up with even more complex stuff ))) for example by adding some Random speed upgrade value, and you could do that not only for this example
}
int minutes = (int)myTimer / 60;
int seconds = (int)myTimer % 60;
timer.text = "Time: " + minutes.ToString() + ":" + seconds.ToString("00");
}
}
//this will be example using just timing
public class YourScriptExample2 : MonoBehaviour
{
public Text timer;
public float myTimer;
private float lastTime = 0;//last time we upgraded speed
void Update()
{
myTimer += Time.deltaTime;
if (myTimer >= lastTime + Ball.ballUpgradeTime)
{
lastTime += Ball.ballUpgradeTime;
Ball.speed += Ball.ballUpgradeSpeed;
}
int minutes = (int)myTimer / 60;
int seconds = (int)myTimer % 60;
timer.text = "Time: " + minutes.ToString() + ":" + seconds.ToString("00");
}
}
//this will be example using coroutine
public class YourScriptExample3 : MonoBehaviour
{
public Text timer;
public float myTimer;
bool keepUpgrading = true; //if you need to stop upgrading speed at some point, otherwise can be removed and you can use simply while(true) instead (also alternatively you could use break; to stop the loop)
void Start()
{
StartCoroutine(Fade());
}
void Update()
{
myTimer += Time.deltaTime;
int minutes = (int)myTimer / 60;
int seconds = (int)myTimer % 60;
timer.text = "Time: " + minutes.ToString() + ":" + seconds.ToString("00");
}
IEnumerator Fade()
{
while (keepUpgrading)
{
yield return new WaitForSeconds(Ball.ballUpgradeTime);//wait ballUpgradeTime seconds and then upgrade speed
Ball.speed += Ball.ballUpgradeSpeed;
}
}
}
As you probably guessed already - there are tons of ways to do what you want in one way or the other, obviously I just showed only few of them, you could also merge them and whatnot. Example#2 is probably what you thought of when posting this question, the other 2 examples are there just to show you that you could do things differently depending on what you expect in terms of versatility, etc. etc.
Thank you so much for such a detailed answer! It all feels a lot clearer right now. I will test this as soon as possible tomorrow.
@DoTA_$$anonymous$$A$$anonymous$$I$$anonymous$$ADzE I have found one problem when I play the game. The ball only increase speed when the ball is instantiated. Not while I'm playing. I thought this maybe has something to do with my instantiate code but I can't find anything that should effect the ball when the game is playing . I have tried all the example codes that you gave me with the same result. Right know i am using your grading example. I would really appreciate your help.
Here is my instantiate code:
public GameObject ball;
void Update ()
{
ball = GameObject.FindGameObjectWithTag ("Ball");
}
void OnTriggerEnter2D(Collider2D other)
//INSTANTIATING THE BALL WHEN IT HITS BOUNDARY2
{
if (other.tag == "Ball")
{
GameObject ballClone = (GameObject) Instantiate (ball, new Vector3 (0,0,0), transform.rotation);
ballClone.GetComponent<Ball1>();
ballClone.name = "Ball";
ballClone.tag = "Ball";
}
}
//DESTROY THE BALL
void OnTriggerExit2D (Collider2D other)
{
if (other.tag == "Ball")
{
Destroy(ball);
}
}
Your code is a bit frustrating, as well as your explanation, so if I didn't understood you correctly let me know.
First of all - this line:
ballClone.GetComponent<Ball1>();
it is useless and you do nothing with that, if your script is not needed in that part of code then just remove that line.
Secondly - if I understood your code correctly there is somewhere trigger at "the end of play field" which spawns clone of your ball and then deletes original one - I have no idea why would you do that.
If you want to keep the ball with its current speed then just "teleport" it to 0,0,0, something like:
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Ball")
{
other.transform.position = new Vector3(0f, 0f, 0f);
}
}
and don't delete it on trigger exit.
If you also need it to remove its speed and wait for clickidy click again then just set its velocity to 0,0,0 and isPlay to false.
If for some reason you still want to delete that instance of ball and create new then make prefab of ball and assign it to your ball variable in your "instantiate code", that way you'll spawn a fresh copy without any movement and with isPlay set to false.
And finally - speed should be increasing as long as your timer script is active or whichever one that holds code with Ball.speed = or += something and your Ball.speed variable is static (both of which is true from what you say). You can verify that by adding this code to any active script:
void Update()
{
Debug.Log(Ball.speed);
}
you'll see current speed in console log.
What you're referring to as speed is your velocity - a momentum which you set by adding force in your code, if you want that velocity to be constantly equal to your speed variable then just assign velocity directly in FixedUpdate function and only change vector by multiplying -1 when needed.
Thank you for all your help. Your feedback is much appreciated. I realize you are completely correct, my code was a total mess. It worked much better to just teleport it back to (0,0,0).
I added debug.log and also saw that the speed was increasing every ten seconds as it was supposed to.
I thought the velocity constantly was equal to the speed when i wrote this code. So it makes perfect sense that I should make them both equal to each other to make the ball increase speed. As I said before, I am quite new to program$$anonymous$$g