0
\$\begingroup\$

I'm working on a Super Hexagon-like game and the goal is to survive as long as possible. The game is working fine but I want to add a new feature that increases the spawn rate of the obstacles and also beside that, I want to increase the player speed. For example, let's say I want to change the spawn rate to 2 if the player survives 1 minute or change the player speed to 610 after lasting 50 seconds. But the point is that the player should play that 1 minute (or 50 seconds) without dying in order for values to be changed and if he dies in that time, then the values won't change and the timer will be reset. I don't know how I can implement this but I guess I should use coroutines. Any help would be appreciated.

Player script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Player : MonoBehaviour
{
    public float moveSpeed = 600f;
    float movement = 0f;

    void Update()
    {
        movement = Input.GetAxisRaw("Horizontal");
    }

    void FixedUpdate()
    {
        transform.RotateAround(Vector3.zero, Vector3.forward, movement * Time.fixedDeltaTime * -moveSpeed);
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
        SoundManager.playSound();
    }

}

Spawner script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Spawner : MonoBehaviour
{
    public float spawnRate = 1f;

    public GameObject hexagonPrefab;

    private float nextTimeToSpawn = 0f;

    // Update is called once per frame
    void Update()
    {
        if (Time.time >= nextTimeToSpawn)
        {
            Instantiate(hexagonPrefab, Vector3.zero, Quaternion.identity);
            nextTimeToSpawn = Time.time + 1f / spawnRate;
        }
    }
}

enter image description here The game looks like this. When the spawn rate increases, the obstacles duplicate faster.

enter image description here

\$\endgroup\$
1
\$\begingroup\$

One convenient way to define changes in variables over time is using the AnimationCurve class. This creates a curve you can edit in the inspector, freely adjusting the value the variable should have at each moment in time, and how it should ramp up/down or jump between those keyframes.

Since you need to access the duration of the current life from multiple different places, let's make one separate script whose job it is to track that:

public class LifeTime : MonoBehaviour {

    public float TimeAlive { get; private set; }

    void FixedUpdate() {
        TimeAlive += Time.deltaTime;
    }

    // In case you ever want to start a new life without re-loading the scene from scratch.
    public void DieAndRespawn() {
        TimeAlive = 0f;
    }
}

Then your other scripts can hold a reference to this one, and ask it for the time value to use. We'll pass this time value into the animation curve to get the speed or spawn rate value we should be using in this moment.

public class Player : MonoBehaviour
{
    public float moveSpeed = 600f;
    public AnimationCurve moveSpeedOverTime;
    public LifeTime life;

    void FixedUpdate()
    {
        float speed = moveSpeed * moveSpeedOverTime.Evaluate(life.TimeAlive);
        float movement = Input.GetAxisRaw("Horizontal") * speed * Time.deltaTime;

        transform.RotateAround(Vector3.zero, Vector3.back, movement);
    }

    // etc...
}

You can make a similar adjustment to your spawner script.

If assigning a reference to the LifeTime instance in both classes is too fussy (maybe you destroy and respawn your Player instance), then you can instead use a Singleton pattern so they can access it via a static reference.

The advantage of doing it this way is that you don't need to complicate your code every time you want to change the difficulty progression of the game. The ramp-up rates can all live in the curve data. You can even have multiple scenes or prefabs with different curves to use for different game modes or difficulty settings, all sharing exactly the same code.

\$\endgroup\$
8
  • \$\begingroup\$ Thank you for your answer. As you mentioned, assigning a reference to the LifeTime in inspector is a bit fussy. What kind of object do I need to use? It can't find anything in the project that can be assigned. \$\endgroup\$
    – Ali
    May 29 at 19:45
  • \$\begingroup\$ You attach the LifeTime component to an object in your scene, as you would with any other MonoBehaviour. \$\endgroup\$
    – DMGregory
    May 29 at 19:46
  • \$\begingroup\$ Okay, I attached the script to the player game object and then used it as a reference. I just wanted to ask that how can I know when the value changes from the curve? I think I need to know when it increases the value. I added an image of the spawn curve to the question. \$\endgroup\$
    – Ali
    May 29 at 20:01
  • \$\begingroup\$ In this image the value starts at 0, then climbs to 0.5 on the vertical axis by the time 0.5 seconds have passed on the horizontal axis, and levels off at 1.0 on the vertical axis after 1.0 seconds have passed on the horizontal axis. You can literally just read these numbers off the image you shared. \$\endgroup\$
    – DMGregory
    May 29 at 20:04
  • 1
    \$\begingroup\$ Your current design never spawns more than once per frame. I don't expect you'll have problems with that, but testing always trumps hearsay from strangers on the Internet. \$\endgroup\$
    – DMGregory
    May 29 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.