You can create a custom operation mode to define your own strategy for how Adaptive Performance adjusts application quality.
The built-in operation modes cover the most common goals. Normal mode targets the highest frame rate, while battery mode targets longer battery life. If you need a different strategy, such as a mode for a specific scene or a target thermal budget, you can implement your own operation mode and activate it at runtime.
A custom operation mode is a class that implements the IAdaptivePerformanceModeProvider interface. Unlike a custom provider supplies device data, an operation mode decides how Adaptive Performance reacts to that data.
Important: A custom mode provider replaces the default mode provider, but doesn’t change the scaler settings. The Adaptive Performance settings depend on the current operation mode, not on the provider. If the Indexer is in battery mode, your custom mode provider runs in place of the default battery mode provider and still uses the battery mode settings. If the Indexer is in normal mode, it runs in place of the default normal mode provider and uses the normal mode settings. To change which settings apply, change the operation mode.
Create a class that implements IAdaptivePerformanceModeProvider. The interface has the following members:
| Member | Description |
|---|---|
ModeName |
The name of the operation mode. |
ThermalAction |
The action to apply in response to the device’s thermal state. |
PerformanceAction |
The action to apply in response to the device’s performance state. |
OnOperationModeStart |
Called when the mode becomes active. Use it to prepare the Indexer and enable scalers. |
OnOperationModeEnd |
Called when the mode is replaced. Use it to restore any state you changed. |
ApplyModeActions |
Called every frame while the mode is active. Use it to set the thermal and performance actions and apply them to the scalers. |
To adjust quality from a custom mode, set each scaler’s OverrideLevel. A value forces the scaler to that level, and -1 returns control of the scaler to the Indexer. OverrideLevel takes effect regardless of the scaler state. Only override scalers that are enabled for the current profile and mode. Use AdaptivePerformanceIndexer.GetAllRegisteredScalers to enumerate every registered scaler, including disabled ones, then filter on AdaptivePerformanceScaler.Enabled.
To implement a custom operation mode:
IAdaptivePerformanceModeProvider.ApplyModeActions, set ThermalAction and PerformanceAction, and set the OverrideLevel of the scalers you want to control.OnOperationModeEnd, reset the OverrideLevel of those scalers to -1 to return control to the Indexer.The following example implements a mode that forces all scalers to their maximum level to reduce quality and keep the device cool:
using System.Collections.Generic;
using UnityEngine.AdaptivePerformance;
public class CoolingOperationMode : IAdaptivePerformanceModeProvider
{
public string ModeName => "Cooling";
public StateAction ThermalAction { get; private set; }
public StateAction PerformanceAction { get; private set; }
readonly List<AdaptivePerformanceScaler> m_Scalers = new List<AdaptivePerformanceScaler>();
public void OnOperationModeStart() { }
public void OnOperationModeEnd()
{
// Return control of every scaler to the Indexer.
var indexer = Holder.Instance?.Indexer;
if (indexer == null)
return;
indexer.GetAllRegisteredScalers(ref m_Scalers);
foreach (var scaler in m_Scalers)
{
if (!scaler.Enabled)
continue;
scaler.OverrideLevel = -1;
}
}
public void ApplyModeActions()
{
var indexer = Holder.Instance?.Indexer;
if (indexer == null)
return;
ThermalAction = StateAction.Decrease;
PerformanceAction = StateAction.Decrease;
// Force every enabled scaler to its maximum level to reduce quality.
indexer.GetAllRegisteredScalers(ref m_Scalers);
foreach (var scaler in m_Scalers)
{
if (!scaler.Enabled)
continue;
scaler.OverrideLevel = scaler.MaxLevel;
}
}
}
Assign an instance to IOperationModeStatus.CurrentOperationalModeProvider to activate your custom operation mode. Adaptive Performance calls OnOperationModeEnd on the previous mode and OnOperationModeStart on your active mode.
For example:
using UnityEngine;
using UnityEngine.AdaptivePerformance;
public class ActivateCoolingMode : MonoBehaviour
{
void Start()
{
var ap = Holder.Instance;
if (ap == null || !ap.Active)
return;
ap.OperationModeStatus.CurrentOperationalModeProvider = new CoolingOperationMode();
}
}
After you assign the provider, Adaptive Performance calls ApplyModeActions on your active mode in every frame until you change to another mode.