Create and configure a custom provider for Adaptive Performance.
Adaptive Performance relies on providers to act as a bridge between the Unity Engine and a device’s hardware sensors. Creating a custom provider involves building a self-contained package that’s discoverable by the Adaptive Performance system.
Follow these steps to create a new provider:
The AdaptivePerformanceManagerSettings
class manages the lifecycle of your provider’s subsystems. Your provider needs a loader, which acts as the main driver for these management features.
To create a loader:
Create a subclass of AdaptivePerformanceLoader
. This class is a ScriptableObject
that defines the subsystems your provider requires and their load order. To handle subsystem management in a type-safe manner, derive from the AdaptivePerformanceLoaderHelper
class instead.
Implement the lifecycle methods. AdaptivePerformanceManagerSettings
calls these methods to initialize, start, stop, and deinitialize (clean up) your loader’s subsystems. For example:
using UnityEngine;
using UnityEngine.AdaptivePerformance;
public abstract class AdaptivePerformanceLoader : ScriptableObject
{
public virtual bool Initialize() { return false; }
public virtual bool Start() { return false; }
public virtual bool Stop() { return false; }
public virtual bool Deinitialize() { return false; }
public abstract T GetLoadedSubsystem<T>() where T : class, ISubsystem;
public abstract ISubsystem GetDefaultSubsystem();
public abstract IAdaptivePerformanceSettings GetSettings();
}
Add the loader to the manager settings. In the Unity Editor, add your AdaptivePerformanceLoader
instance to the Loaders list in the Adaptive Performance Manager Settings. You can add multiple loaders and arrange them by priority. At runtime, the manager attempts to initialize each loader in order. The first one that initializes successfully becomes the active loader.
(Optional) Query the static AdaptivePerformanceManagerSettings.ActiveLoader
instance to access the active loader. If all loaders fail to initialize, Unity sets activeLoader
to null.
A provider might need additional settings to help manage build issues or runtime configuration.
To configure build and runtime settings through Project SettingsA broad collection of settings which allow you to configure how Physics, Audio, Networking, Graphics, Input and many other areas of your project behave. More info
See in Glossary:
Add the AdaptivePerformanceConfigurationData
attribute to a ScriptableObject
.
Define properties in the ScriptableObject
to control the provider’s configuration. Unity displays these options in the Adaptive Performance section of the Project Settings window.
Note: Unity manages the lifecycle of one instance of the class marked with the attribute through the EditorBuildSettings
config object API. If you don’t provide a dedicated interface, configuration settings display in the Project Settings window using the standard Scriptable Object InspectorA Unity window that displays information about the currently selected GameObject, asset or project settings, allowing you to inspect and edit the values. More info
See in Glossary. You can create a custom Editor for your configuration settings type to replace the standard Inspector in the Project Settings window.
Inherit from AdaptivePerformanceBuildHelper<T>
in a build script to pass settings from the Editor into your runtime loader. The following is an example of a simple build script:
using UnityEngine.AdaptivePerformance.Editor;
using UnityEngine;
public class MySettings : ScriptableObject { }
public class MyBuildProcessor : AdaptivePerformanceBuildHelper<MySettings>
{
public override string BuildSettingsKey { get { return "MyPackageSettingsKey"; } }
}
You can also override build processing steps like OnPreprocessBuild
and OnPostprocessBuild
. Make sure to call the base class implementation to ensure your settings transfer to the built application. For example:
using UnityEditor.Build.Reporting;
using UnityEngine.AdaptivePerformance.Editor;
using UnityEngine;
public class MySettings : ScriptableObject { }
public class MyBuildProcessor : AdaptivePerformanceBuildHelper<MySettings>
{
public override string BuildSettingsKey { get { return "MyPackageSettingsKey"; } }
public override void OnPreprocessBuild(BuildReport report)
{
base.OnPreprocessBuild(report);
// Do your work here
}
public override void OnPostprocessBuild(BuildReport report)
{
base.OnPreprocessBuild(report);
// Do your work here
}
}
If you want to support different settings per platform at build time, you can override AdaptivePerformanceBuildHelper<T0>.SettingsForBuildTargetGroup
and use the buildTargetGroup
attribute to retrieve the appropriate platform settings. By default, this method uses the key associated with the settings instance to copy the entire settings object from EditorUserBuildSettings
to PlayerSettings
.
using UnityEditor;
using UnityEngine;
using UnityEngine.AdaptivePerformance.Editor;
public class MySettings : ScriptableObject { }
public class MyBuildProcessor : AdaptivePerformanceBuildHelper<MySettings>
{
public override string BuildSettingsKey { get { return "MyPackageSettingsKey"; } }
public override UnityEngine.Object SettingsForBuildTargetGroup(BuildTargetGroup buildTargetGroup)
{
// Get platform specific settings and return them. Use something like the following
// for simple settings data that isn't platform specific.
UnityEngine.Object settingsObj = null;
EditorBuildSettings.TryGetConfigObject(BuildSettingsKey, out settingsObj);
if (settingsObj == null || !(settingsObj is T))
return null;
return settingsObj;
}
}
For the Adaptive Performance provider management system to use your provider, you must supply metadata.
To do this, create a class that implements the following interfaces:
The system uses .NET reflection to find all types implementing the IAdaptivePerformancePackage
interface. It then attempts to instantiate each one and populate the metadata store with the information provided by each instance.
Implementing the package metadata allows the Adaptive Performance provider management system to automatically create and initialize your loaders and settings instances. The system passes any new instances of your settings to the PopulateNewSettingsInstance
method to allow your provider to initialize the new instance data after it’s created, if needed.
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.AdaptivePerformance;
using UnityEngine.AdaptivePerformance.Editor.Metadata;
// The following are minimal placeholder classes required for this snippet to compile.
// In your project, 'MyPackageSettings' and 'MyLoader' would contain your actual custom logic and definitions.
public class MyPackageSettings : ScriptableObject { }
public class MyLoader : AdaptivePerformanceLoader
{
public override bool Initialize() { return true; }
public override bool Start() { return true; }
public override bool Stop() { return true; }
public override bool Deinitialize() { return true; }
public override T GetLoadedSubsystem<T>() { return null; }
public override ISubsystem GetDefaultSubsystem() { return null; }
public override IAdaptivePerformanceSettings GetSettings() { return null; }
}
class MyPackage : IAdaptivePerformancePackage
{
private class MyLoaderMetadata : IAdaptivePerformanceLoaderMetadata
{
public string loaderName { get; } = "My Loader";
public string loaderType { get; } = typeof(MyLoader).AssemblyQualifiedName;
public List<BuildTargetGroup> supportedBuildTargets { get; } = new List<BuildTargetGroup>()
{
BuildTargetGroup.Standalone,
BuildTargetGroup.Android,
BuildTargetGroup.iOS
};
}
private class MyPackageMetadata : IAdaptivePerformancePackageMetadata
{
public string packageName { get; } = "My AdaptivePerformance Provider";
public string packageId { get; } = "my.adaptiveperformance.package";
public string settingsType { get; } = typeof(MyPackageSettings).AssemblyQualifiedName;
public List<IAdaptivePerformanceLoaderMetadata> loaderMetadata { get; } = new List<IAdaptivePerformanceLoaderMetadata>()
{
new MyLoaderMetadata()
};
}
private static IAdaptivePerformancePackageMetadata s_Metadata = new MyPackageMetadata();
public IAdaptivePerformancePackageMetadata metadata => s_Metadata;
public bool PopulateNewSettingsInstance(ScriptableObject obj)
{
MyPackageSettings packageSettings = obj as MyPackageSettings;
if (packageSettings != null)
{
return true;
}
return false;
}
}
You can display provider settings under both Project Settings and Build ProfilesA set of customizable configuration settings to use when creating a build for your target platform. More info
See in Glossary, so you can edit the settings in both locations. Provide the custom UI code by inheriting from the ProviderSettingsEditor
and adding a custom attribute.
The following example demonstrates how provider settings function if only the default UI is necessary.
Note: ShowTargetGroupSelection
hides the platform selection group tab if you’re using the default DisplayProviderSettings()
function.
using UnityEditor;
using UnityEditor.Localization;
using UnityEngine;
using UnityEngine.AdaptivePerformance.Editor;
public class BasicProviderSettings : ScriptableObject { }
[CustomEditor(typeof(BasicProviderSettings))]
internal class BasicProviderSettingsEditor : ProviderSettingsEditor
{
protected override BuildTargetGroup CurrentTargetGroup => BuildTargetGroup.Unknown;
public override bool ShowTargetGroupSelection => false;
public override string UnsupportedInfo => L10n.Tr("Adaptive Performance Basic provider is not supported on this platform");
protected override bool IsAutoPerformanceModeAvailable => false;
protected override bool IsBoostAvailable => false;
protected override bool IsThermalActionDelayAvailable => false;
public override void OnInspectorGUI()
{
DisplayProviderSettings();
}
}