Version: Unity 6.7 Alpha (6000.7)
Language : English
Operation modes
Create a custom operation mode

Battery mode idle detection

Use the battery mode to detect player inactivity to save additional power, and to keep idle detection working with your input system.

While battery mode is active, Adaptive Performance tracks player idle time and reduces workload to save power. When the player interacts again, the more it drops in performance. When the player interacts with the application again, Adaptive Performance restores the previous quality. Idle detection only works in battery mode.

How idle detection works

Adaptive Performance measures idle time with the AdaptivePerformanceIdleTimeTracker class. A player is considered idle when no key or mouse button receives input and the cursor stops moving.

The following settings control the behavior of the battery mode provider:

Setting Description
Idle Time Threshold The number of seconds the player must be idle before idle-based scaling begins. The default value is 60.
Save Target The fraction of frame time that battery mode tries to save, in the range 0 to 1. The default value is 0.1, which targets a 10% reduction.

After the player exceeds the idle threshold, the Indexer increases the idle scale by calculating:

idle scale = ceil(idle time / idle time threshold)

For example, with the default 60-second threshold, the idle scale increases by one for every sixty seconds of inactivity. Higher idle scale means battery-oriented scalers cut more work. The following battery-oriented scalers respond to the idle scale:

Input system requirement

By default, idle detection uses the legacy Input Manager to detect key presses and cursor movement. If your project disables the legacy Input Manager, idle detection stops working and battery mode’s idle-based scaling becomes inactive. When this happens, Adaptive Performance logs a warning and the rest of battery mode continues to work. To re-enable idle detection with a different input system, assign the static delegates as follows:

Assign the static IsAnyKeyPressedProvider and IsCursorMovingProvider delegates with implementations backed by your input system. Each delegate returns a bool and Adaptive Performance queries it once per frame.

The following example wires idle detection to the Input System package:

using UnityEngine;
using UnityEngine.AdaptivePerformance;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

public class AdaptivePerformanceIdleInput : MonoBehaviour
{
    void OnEnable()
    {
        // Report a press on any button of the current keyboard, mouse, or gamepad.
        AdaptivePerformanceIdleTimeTracker.IsAnyKeyPressedProvider = () =>
            AnyButtonPressed(Keyboard.current) ||
            AnyButtonPressed(Mouse.current) ||
            AnyButtonPressed(Gamepad.current);

        // Report cursor movement.
        AdaptivePerformanceIdleTimeTracker.IsCursorMovingProvider = () =>
            (Mouse.current?.delta.ReadValue().sqrMagnitude ?? 0f) > 0f;
    }

    // Returns true if any button on the device is pressed. This covers every key,
    // mouse button, gamepad face/shoulder button, trigger, d-pad direction, and
    // stick press. It doesn't cover analog stick or scroll-wheel movement; handle
    // those separately if idle detection needs to account for them.
    static bool AnyButtonPressed(InputDevice device)
    {
        if (device == null)
            return false;

        foreach (var control in device.allControls)
        {
            if (control is ButtonControl button && button.isPressed)
                return true;
        }

        return false;
    }
}

Additional resources

Operation modes
Create a custom operation mode