Magic Time User Scripting

v1.0

I hope you find it easy to interact with a MagicTimeUser object, using the properties and methods provided.

Check out the full MagicTimeUser class for all the details on the methods and properties available.

Time Control

Most times you would usually use Time.deltaTime to handle something related to this object, you will probably want to use the DeltaTime property instead. This will return Time.deltaTime scaled down by the magicTimeUser.TimeScale. There are similar properties for FixedTime and UnscaledDeltaTime.

Time.unscaledDeltaTime will return the last frame time without taking Time.timeScale into account.

Main Time Properties

Here are some simple exampels of how you might use the main time properties.

// From a class that is IUseMagicTime or inherits from MagicTimeUser
float speedThisFrame = speed * DeltaTime
float fixedSpeedThisFrame = fixedSpeed * FixedDeltaTime;
float speedThisFrameVersion2 = speed * UnscaledDeltaTime;
Debug.Log($"TimeScale for this object is currently {TimeScale}"); // a float!

Moving based on DeltaTime

In this example, we have a generic Move() method which handles objects that may or may not have a MagicTimeUser component on them, selecting the appropriate DeltaTime to use.

private void Move()
{
    var deltaTime = MagicTimeUser == null ? Time.deltaTime : MagicTimeUser.DeltaTime;
    transform.Translate(LocalDirection * (speed * deltaTime), Space.Self);
}

Adjusting object locomotion speed with InverseTimeScale

We may not always want to scale values by the TimeScale value. To achieve a "running in slow motion" effect, where the "Locomotion" animation is determined by the distance a character is moving, we must account for the TimeScale.

We use the InverseTimeScale to multiply the metersPerSecond value. If TimeScale is not exactly 1f, then InverseTimeScale will either increase or decrease the metersPerSecond value.

Then, we set the locomotion float value on the Animator to this animationSpeed.

// Accounting for TimeScale changes in the Animation speed using InverseTimeScale
//...
var metersPerSecond = distance / deltaTimeToUse;
var animationSpeed = 0f;
if (metersPerSecond > 0 && Owner.TimeScale > 0)
    animationSpeed = metersPerSecond * Owner.InverseTimeScale;
animator.SetFloat(locomotionString, animationSpeed, animatorDampTime, Time.deltaTime);
// The above example ensures the "locomotion" speed remains steady, even as the
// object slows down. This gives it the "running in slow motion" effect.
//...

Subscribing and Unsubscribing to other LocalTimeScale objects

Often you may want to manually subscribe an object to another LocalTimeScale. Or perhaps unsubscribe from one.

// Subscribe to a specific LocalTimeScale
LocalTimeScale otherTimeScale;
Debug.Log($"TimeScale before adding {otherTimeScale.name}: {magicTimeUser.TimeScale}");
magicTimeUser.SubscribeToLocalTimeScale(otherTimeScale);
Debug.Log($"TimeScale after adding {otherTimeScale.name}: {magicTimeUser.TimeScale}");

// Unsubscribing from a specific LocalTimeScale
LocalTimeScale otherTimeScale;
Debug.Log($"TimeScale before removing {otherTimeScale.name}: {magicTimeUser.TimeScale}");
magicTimeUser.UnsubscribeFromLocalTimeScale(otherTimeScale);
Debug.Log($"TimeScale after removing {otherTimeScale.name}: {magicTimeUser.TimeScale}");

Grabbing and using the LocalTimeScale of one object, from another class

Sometimes you may wish to do something with the LocalTimeScale of another object.

// Interacting with the LocalTimeScale on the object from another class
if (otherObject is IUseMagicTime magicTimeUser)
{
    LocalTimeScale otherTimeScale = magicTimeUser.LocalTimeScale;
    float otherObjectsTimeScale = otherTimeScale.LocalTimeScaleValue;
}

Getting the GameObject from a MagicTimeUser

In cases where you're interacting with MagicTimeUser objects, you may have a need to get the GameObject associated with that object. The GameObject property on MagicTimeUser does just that!

Of course, if you create your own class which derives from MagicTimeUser, you could add new logic in order to return a different value, if that fits your game.

// Getting the gameObject from IUseMagicTime
protected virtual void OnCollisionEnter(Collider other)
{
    if (other.isTrigger) return;
            
    var magicTimeUser = other.GetComponentInParent<IUseMagicTime>();
    if (magicTimeUser != null)
    {
        GameObject otherObject = magicTimeUser.GameObject;
    }
}

Last updated