Random Direction Changer
Randomly Change Directions
Our apple tree's movement is looking great! However, we have one final requirement: the ability to randomly change direction. Since this requirement may not be needed for every movable object, we will create a standalone class called RandomDirectionChanger
.
The RandomDirectionChanger
will randomly reverse a game object's direction based on a specified percentage chance, checked at regular intervals. When the condition is met, it will call the ReverseDirection
method that we have already implemented in the MovableObjectBase
. To access the ReverseDirection method, our RandomDirectionChanger will need to reference the MovableObjectBase
component.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static CSG.Utilities.TimeUtilities;
public class RandomDirectionChanger : MonoBehaviour
{
[SerializeField]
[Tooltip("Percentage chance of changing direction (e.g., 10%)"))]
private float _changeDirectionChance = 10f;
[SerializeField]
[Tooltip("Time interval (in seconds) to check for direction change")]
private float _checkInterval = 2f; // How often to check (in seconds)
// Property to get or set the ChangeDirectionChance of the object
public float ChangeDirectionChance
{
get => _changeDirectionChance;
set => _changeDirectionChance = value;
}
// Property to get or set the CheckItnerval
public float CheckInterval
{
get => _checkInterval;
set => _checkInterval = value;
}
private MovableObjectBase _movableObject; // Reference to the MovableObjectBase
private void Start()
{
// Get the MovableObjectBase component on the same game object
_movableObject = GetComponent<MovableObjectBase>();
// Start the coroutine to check for direction change at regular intervals
StartCoroutine(ChangeDirectionRandomly());
}//end Start()
// Coroutine to check for direction change at specified intervals
private IEnumerator ChangeDirectionRandomly()
{
while (true)
{
yield return new WaitForSecondsGametime(_checkInterval); // Wait for the next interval in game time
// Roll a random number between 0 and 100
float randomRoll = Random.Range(0f, 100f);
// If the roll is less than or equal to the changeDirectionChance, reverse direction
if (randomRoll <= _changeDirectionChance)
{
_movableObject.ReverseDirection();
Debug.Log("Direction Changed!");
}//end if (randomRoll <= _changeDirectionChance)
}//end While
}//end IEnumerator
}
WaitForSeconds
To check for random direction changes, we set up an IEnumerator
in our RandomDirectionChanger
class that waits based on our specified check interval. Unity provides two built-in wait methods, each with its own drawbacks:
-
WaitForSeconds
: This method waits for a specified amount of time but can drift over long durations, particularly if the game is paused or if the frame rate fluctuates significantly. -
WaitForSecondsRealtime
: This method waits based on real-time, continuing even when the game is paused. However, it is not suitable for scenarios where the wait needs to be tied to game activity.
Since there isn't a built-in option that combines accurate game timing with pause-aware functionality, we will implement a custom WaitForSecondsGameTime
class. Because this logic could be useful elsewhere, we will organize it within a TimeUtilities class
.