# Magic Time User

**Magic Time User** is a `MonoBehaviour` which implements `IUseMagicTime`. Objects which will utilize the **Magic Time** system should inherit from `MagicTimeUser`, so they automatically work.&#x20;

{% hint style="info" %}
You can create your own implementation logic either by creating your own [`IUseMagicTime`](https://infinitypbr.gitbook.io/infinity-pbr/magic-time-local-time-scale/magic-time-user/ihavelocaltime) class, or creating a new class which derives from `MagicTimeUser` and overrides the methods you'd like to customize.
{% endhint %}

## "Local" `LocalTimeScale`

Each `MagicTimeUser` object will have its own `LocalTimeScale` automatically. This is unique and specific to this object, and its value will be combined with any other Local Time Scales that this object subscribes to.

## Main Methods and Properties

These are the main methods and properties you'll likely interact with most often.&#x20;

### Time Properties

**`DeltaTime`**, **`FixedDeltaTime`**, and **`UnscaledDeltaTime`** will replace `Time.deltaTime`, `Time.fixedDeltaTime`, and `Time.unscaledDeltaTime` in your code. Anywhere that you would have used `Time.deltaTime`, you should use `DeltaTime` instead.

**`TimeScale`** is the actual scale currently set based on all of the subscribed `LocalTimeScale` objects, compared to normal speed (`Time.timeScale` = `1f`).&#x20;

**`InverseTimeScale`** is the value you would need to multiple `TimeScale` by in order to get `Time.timeScale`. This is useful for multiplying things that you don't want to be slowed down, when they otherwise would. *(See the "animation" example in the* [*Magic Time User Scripting*](https://infinitypbr.gitbook.io/infinity-pbr/magic-time-local-time-scale/magic-time-user/magic-time-user-scripting) *page.)*

```csharp
// 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!

// 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.
//...

// 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}");

// 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 IUseMagicTime
protected virtual void OnCollisionEnter(Collider other)
{
    if (other.isTrigger) return;
            
    var magicTimeUser = other.GetComponentInParent<IUseMagicTime>();
    if (magicTimeUser != null)
    {
        GameObject otherObject = magicTimeUser.GameObject;
    }
}
```

Check the [Magic Time User Scripting](https://infinitypbr.gitbook.io/infinity-pbr/magic-time-local-time-scale/magic-time-user/magic-time-user-scripting) page for more scripting documentation.&#x20;

## Inspector Options

Once added to your class, some fields will be exposed in the Inspector.

<figure><img src="https://2431624982-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY3N_li2jPq7az6mYfq%2Fuploads%2Faiw9QbZoiUU6PEDhBd7V%2FScreenshot%202024-09-15%20at%208.14.06%E2%80%AFPM.png?alt=media&#x26;token=f0b69950-2783-47da-9a38-85d084268661" alt=""><figcaption></figcaption></figure>

## Initial Time Scales

These are `LocalTimeScale` Scriptable Objects which you want to subscribe to at runtime. These will connect to the instances of those objects via the [Magic Time Manager](https://infinitypbr.gitbook.io/infinity-pbr/magic-time-local-time-scale/magic-time-manager) in your scene.

## Transition Settings

Whenever the combined `TimeScale` value changes, the value of `TimeScale` will transition to the new value.

### Transition Duration

This is how long the transition lasts. Set this value to `0f` to skip transitioning altogether.

### Transition Curve

This is the curve used for the transition, if you'd like to customize the experience.

### Default Time Scale

This is the default time scale value for this objects `LocalTimeScale` object.

## Customization Example

Often you may want your object to subscribe to some `LocalTimeScales`, but not others, depending on the type of object it is in your game. In my own project, I have "Enemy" and "Player" Local Time Scales, and characters of those types will subscribe to one or the other.

<figure><img src="https://2431624982-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY3N_li2jPq7az6mYfq%2Fuploads%2FQBvJMDbWVuxuuHlg3EzZ%2FScreenshot%202024-09-15%20at%208.21.21%E2%80%AFPM.png?alt=media&#x26;token=abd2128f-29c3-4185-8cfc-836d71f52636" alt=""><figcaption></figcaption></figure>

Here I have exposed two additional lists, one for the "Player" and one for the "Enemy". In my code, I ensure the character only subscribes to the correct list of `LocalTimeScales`.

<pre class="language-csharp"><code class="lang-csharp"><strong>// Note that this overrides the coroutine on MagicTimeUser!
</strong><strong>public override IEnumerator SubscribeToInitialTimeScales()
</strong>{
    // Wait for the base class coroutine to finish [Don't forget this step!]
    yield return base.SubscribeToInitialTimeScales();
    
    // Subscribe to the additional time scales based on the IsPlayer value
    foreach (var timeScale in IsPlayer ? playerTimeScales : enemyTimeScales)
    {
        var localTimeScale = MagicTimeManager.Instance.TimeScale(timeScale.name);
        SubscribeToLocalTimeScale(localTimeScale);
    }
}
</code></pre>

{% content-ref url="magic-time-user/magic-time-user-scripting" %}
[magic-time-user-scripting](https://infinitypbr.gitbook.io/infinity-pbr/magic-time-local-time-scale/magic-time-user/magic-time-user-scripting)
{% endcontent-ref %}

{% content-ref url="magic-time-user/ihavelocaltime" %}
[ihavelocaltime](https://infinitypbr.gitbook.io/infinity-pbr/magic-time-local-time-scale/magic-time-user/ihavelocaltime)
{% endcontent-ref %}
