How to make my powerup last for about five seconds then go back to normal?

Hey guys, I’ve made a PacMan and I’ve got a powerup that speeds you up. But what I need help with is that I only want it to last about 5 seconds then it returns to normal speed. The game is in 2D if that matters which I doubt it. Here is my script below.

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class PacmanMove : MonoBehaviour
{
public float speed = 0.4f;
Vector2 dest = Vector2.zero;
public Text countText;
private int count;
private Rigidbody2D rb;

void Start()
{
    dest = transform.position;
    rb = GetComponent<Rigidbody2D>();
    count = 0;
    SetCountText();

}

void FixedUpdate()
{
    // Move closer to Destination
    Vector2 p = Vector2.MoveTowards(transform.position, dest, speed);
    GetComponent<Rigidbody2D>().MovePosition(p);

    // Check for Input if not moving, this is also all the movement
    if ((Vector2)transform.position == dest)
    {
        if (Input.GetKey(KeyCode.UpArrow) && valid(Vector2.up))
            dest = (Vector2)transform.position + Vector2.up;
        if (Input.GetKey(KeyCode.RightArrow) && valid(Vector2.right))
            dest = (Vector2)transform.position + Vector2.right;
        if (Input.GetKey(KeyCode.DownArrow) && valid(-Vector2.up))
            dest = (Vector2)transform.position - Vector2.up;
        if (Input.GetKey(KeyCode.LeftArrow) && valid(-Vector2.right))
            dest = (Vector2)transform.position - Vector2.right;
    }

    // Animation Parameters
    Vector2 dir = dest - (Vector2)transform.position;
    GetComponent<Animator>().SetFloat("DirX", dir.x);
    GetComponent<Animator>().SetFloat("DirY", dir.y);
}

bool valid(Vector2 dir)
{
    // Cast Line from 'next to Pac-Man' to 'Pac-Man'
    Vector2 pos = transform.position;
    RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos);
    return (hit.collider == GetComponent<Collider2D>());
}

void  OnTriggerEnter2D(Collider2D other)
{
    if (other.gameObject.CompareTag("Pacdot"))
    {
        other.gameObject.SetActive(false);
        count = count + 10;
        SetCountText();
    }

    // if Pacman collides with "PowerUp" his speed becomes that
    if (other.gameObject.CompareTag("PowerUp"))
    {
        speed = 2f;
    }
}

//shows the score that you have from the PacDots
void SetCountText()
{
    countText.text = "Count: " + count.ToString();
}

}

But it was what I did, I rotate it under the influence tab (on blender) packed and saved on the unity asset folder, but when putting everything together on unity it won't go rotated. But I'll test here if it would needed to rotate all uvs separately

3 Answers

3

You could use boolean for determining if powerup state is on. or int/string with multiple states for like normal, faster speed, bigger jump… etc…
and check the state with if statement and do the stuff inside it.
You can use simple timer/counterdown while the powerup is on.

int state = 0; // 0 = normal, 1 = faster
public float speedupgrade  = 2f;
public float normalspeed = 1f;
private float speed;
float speedUpgradeLeft = 0;
public float speedUpgradeLenght = 5f; //5 seconds
...

...
if(state == 1) { // or you could use switch-statement if you have many states
    speed = normalspeed + speedupgrade; // 1f + 2f = 3f
} else if (state == 2) {
     // do other stuff
} else {
    speed = normalspeed; // 1f
}

// then just use speed variable
Vector2 p = Vector2.MoveTowards(transform.position, dest, speed);

 // then use timer to change state
 if(speedUpgradeLeft  > 0) {
      speedUpgradeLeft -= Time.deltatime;
 }
 else {
     state = 0;
 }
...

...
//On your powerup trigger:
// then trigger speedupgrade by setting time on it.
speedUpgradeLeft = speedUpgradeLenght;
// or adding more time on it
speedUpgradeLeft += speedUpgradeLenght;
// And change the state accordingly
state = 1;
...

I’m soo confused @PizzaPie. I’m not the best coder so I don’t understand the vocabulary that you were using. I know that I have to put it the couritine somewhere but I don’t know when. Would you be clearer or, (i know this isn’t really helping,) could you just do it for me. I mean that in the nicest way possible. I honestly have no idea where to put the script that you gave me.

Ohhh... Im an idiot... Random.Range (1,3) means any number in BETWEEN 1 and 3... Thank you so much for clearing it up lol

Use a coroutine

IEnumerator PowerUp()
    {
        speed = 2f;
        yield return new WaitForSeconds(5f);
        speed = 1f;
        
    }

And Call it OnTriggerEnter() where you have the speed =2f like this:

    if (other.gameObject.CompareTag("PowerUp"))
         {
           StopCoroutine(PowerUp());  
           StartCoroutine(PowerUp());
         }

Now in case you encounter a 2nd PowerUp before the first is finished it will stop the first and initiate a second one. Of course if you don’t want that behaviour and want the PowerUp only to last 5 secs even if you pick one more, while on the effect is on, then you need a bool to determine if you are on a PowerUp or not. Hope that helps.

yes just as you said. The model in question was a tabel and I needed to rotate the texture for it's legs, but I needed to rotate each leg on the uv editor (So I rotate the UV) instead of rotating the texture on the influence tab wich I rotated only the texture not the UV. Thanks!