Skip to content

Commit

Permalink
Add custom package settings (#5027)
Browse files Browse the repository at this point in the history
  • Loading branch information
dongruoping authored Mar 18, 2021
1 parent 1d2806d commit 3762dd2
Show file tree
Hide file tree
Showing 22 changed files with 682 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
# Environemnt logfile
*Project.log

# Custom settings asset
*.settings.asset*

# Visual Studio 2015 cache directory
/Project/.vs/

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Unity.ML-Agents.Performance.Tests",
"name": "Unity.ML-Agents.DevTests.Editor",
"references": [
"Unity.ML-Agents.Editor",
"Unity.ML-Agents",
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Editor;


namespace MLAgentsExamples.Tests.Settings
{
[TestFixture]
public class MLAgentsSettingsTests
{
string EditorBuildSettingsConfigKey = MLAgentsSettingsManager.EditorBuildSettingsConfigKey;
string tempSettingsRootPath = "Assets/ML-Agents/Scripts/Tests/Editor/MLAgentsSettings";
MLAgentsSettings storedConfigObject;
[SetUp]
public void SetUp()
{
if (EditorBuildSettings.TryGetConfigObject(EditorBuildSettingsConfigKey,
out MLAgentsSettings settingsAsset))
{
if (settingsAsset != null)
{
storedConfigObject = settingsAsset;
EditorBuildSettings.RemoveConfigObject(EditorBuildSettingsConfigKey);
}
}
MLAgentsSettingsManager.Destroy();
ClearSettingsAssets();
}

[TearDown]
public void TearDown()
{
if (storedConfigObject != null)
{
EditorBuildSettings.AddConfigObject(EditorBuildSettingsConfigKey, storedConfigObject, true);
storedConfigObject = null;
}
MLAgentsSettingsManager.Destroy();
ClearSettingsAssets();
}

internal void ClearSettingsAssets()
{
var assetsGuids = AssetDatabase.FindAssets("t:MLAgentsSettings", new string[] { tempSettingsRootPath });
foreach (var guid in assetsGuids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
AssetDatabase.DeleteAsset(path);
}
}

[Test]
public void TestMLAgentsSettingsManager()
{
Assert.AreNotEqual(null, MLAgentsSettingsManager.Settings);
Assert.AreEqual(5004, MLAgentsSettingsManager.Settings.EditorPort); // default port
MLAgentsSettingsManager.Settings.EditorPort = 6000;
Assert.AreEqual(6000, MLAgentsSettingsManager.Settings.EditorPort);

var settingsObject = ScriptableObject.CreateInstance<MLAgentsSettings>();
settingsObject.EditorPort = 7000;
var tempSettingsAssetPath = tempSettingsRootPath + "/test.mlagents.settings.asset";
AssetDatabase.CreateAsset(settingsObject, tempSettingsAssetPath);
EditorBuildSettings.AddConfigObject(EditorBuildSettingsConfigKey, settingsObject, true);
// destroy manager instantiated as a side effect by accessing MLAgentsSettings directly without manager
MLAgentsSettingsManager.Destroy();
Assert.AreEqual(7000, MLAgentsSettingsManager.Settings.EditorPort);
}

// A mock class that can invoke private methods/fields in MLAgentsSettingsProvider
internal class MockSettingsProvider
{
public MLAgentsSettingsProvider Instance
{
get
{
return (MLAgentsSettingsProvider)typeof(MLAgentsSettingsProvider).GetField("s_Instance",
BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
}
}

public MLAgentsSettings Settings
{
get
{
return (MLAgentsSettings)typeof(MLAgentsSettingsProvider).GetField("m_Settings",
BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Instance);
}
}

public void CreateMLAgentsSettingsProvider()
{
MLAgentsSettingsProvider.CreateMLAgentsSettingsProvider();
}

public void Reinitialize()
{
var method = typeof(MLAgentsSettingsProvider).GetMethod("Reinitialize",
BindingFlags.Instance | BindingFlags.NonPublic);
method.Invoke(Instance, null);
}

public string[] FindSettingsInProject()
{
var method = typeof(MLAgentsSettingsProvider).GetMethod("FindSettingsInProject",
BindingFlags.Static | BindingFlags.NonPublic);
return (string[])method.Invoke(null, null);
}

public void CreateNewSettingsAsset(string relativePath)
{
var method = typeof(MLAgentsSettingsProvider).GetMethod("CreateNewSettingsAsset",
BindingFlags.Static | BindingFlags.NonPublic);
method.Invoke(null, new object[] { relativePath });
}
}

[Test]
public void TestMLAgentsSettingsProviderCreateAsset()
{
var mockProvider = new MockSettingsProvider();
mockProvider.CreateMLAgentsSettingsProvider();
Assert.AreNotEqual(null, mockProvider.Instance);

// mimic MLAgentsSettingsProvider.OnActivate()
MLAgentsSettingsManager.OnSettingsChange += mockProvider.Reinitialize;

mockProvider.Instance.InitializeWithCurrentSettings();
Assert.AreEqual(0, mockProvider.FindSettingsInProject().Length);

var tempSettingsAssetPath1 = tempSettingsRootPath + "/test.mlagents.settings.asset";
mockProvider.CreateNewSettingsAsset(tempSettingsAssetPath1);
Assert.AreEqual(1, mockProvider.FindSettingsInProject().Length);
Assert.AreEqual(5004, mockProvider.Settings.EditorPort);
MLAgentsSettingsManager.Settings.EditorPort = 6000; // change to something not default
// callback should update the field in provider
Assert.AreEqual(6000, mockProvider.Settings.EditorPort);

var tempSettingsAssetPath2 = tempSettingsRootPath + "/test2.mlagents.settings.asset";
mockProvider.CreateNewSettingsAsset(tempSettingsAssetPath2);
Assert.AreEqual(2, mockProvider.FindSettingsInProject().Length);
// manager should set to the new (default) one, not the previous modified one
Assert.AreEqual(5004, MLAgentsSettingsManager.Settings.EditorPort);

// mimic MLAgentsSettingsProvider.OnDeactivate()
MLAgentsSettingsManager.OnSettingsChange -= mockProvider.Reinitialize;
mockProvider.Instance.Dispose();
}

[Test]
public void TestMLAgentsSettingsProviderLoadAsset()
{
var mockProvider = new MockSettingsProvider();
var tempSettingsAssetPath1 = tempSettingsRootPath + "/test.mlagents.settings.asset";
mockProvider.CreateNewSettingsAsset(tempSettingsAssetPath1);
MLAgentsSettingsManager.Settings.EditorPort = 8000; // change to something not default

mockProvider.Instance?.Dispose();
MLAgentsSettingsManager.Destroy();

mockProvider.CreateMLAgentsSettingsProvider();
Assert.AreEqual(8000, MLAgentsSettingsManager.Settings.EditorPort);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class AcademyStepperTest
[SetUp]
public void Setup()
{
Academy.Instance.Dispose();
SceneManager.LoadScene("ML-Agents/Scripts/Tests/Runtime/AcademyTest/AcademyStepperTestScene");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Runtime",
"name": "Unity.ML-Agents.DevTests.Runtime",
"references": [
"Unity.ML-Agents"
],
Expand Down
1 change: 1 addition & 0 deletions com.unity.ml-agents/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ details.
#### com.unity.ml-agents / com.unity.ml-agents.extensions (C#)
- The `.onnx` models input names have changed. All input placeholders will now use the prefix `obs_` removing the distinction between visual and vector observations. Models created with this version will not be usable with previous versions of the package (#5080)
- The `.onnx` models discrete action output now contains the discrete actions values and not the logits. Models created with this version will not be usable with previous versions of the package (#5080)
- Added ML-Agents package settings. (#5027)
#### ml-agents / ml-agents-envs / gym-unity (Python)

### Bug Fixes
Expand Down
75 changes: 75 additions & 0 deletions com.unity.ml-agents/Editor/MLAgentsSettingsBuildProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System.Linq;
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;


namespace Unity.MLAgents.Editor
{
internal class MLAgentsSettingsBuildProvider : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
private MLAgentsSettings m_SettingsAddedToPreloadedAssets;

public int callbackOrder => 0;

public void OnPreprocessBuild(BuildReport report)
{
var wasDirty = IsPlayerSettingsDirty();
m_SettingsAddedToPreloadedAssets = null;

var preloadedAssets = PlayerSettings.GetPreloadedAssets().ToList();
if (!preloadedAssets.Contains(MLAgentsSettingsManager.Settings))
{
m_SettingsAddedToPreloadedAssets = MLAgentsSettingsManager.Settings;
preloadedAssets.Add(m_SettingsAddedToPreloadedAssets);
PlayerSettings.SetPreloadedAssets(preloadedAssets.ToArray());
}

if (!wasDirty)
ClearPlayerSettingsDirtyFlag();
}

public void OnPostprocessBuild(BuildReport report)
{
if (m_SettingsAddedToPreloadedAssets == null)
return;

var wasDirty = IsPlayerSettingsDirty();

var preloadedAssets = PlayerSettings.GetPreloadedAssets().ToList();
if (preloadedAssets.Contains(m_SettingsAddedToPreloadedAssets))
{
preloadedAssets.Remove(m_SettingsAddedToPreloadedAssets);
PlayerSettings.SetPreloadedAssets(preloadedAssets.ToArray());
}

m_SettingsAddedToPreloadedAssets = null;

if (!wasDirty)
ClearPlayerSettingsDirtyFlag();
}


private static bool IsPlayerSettingsDirty()
{
#if UNITY_2019_OR_NEWER
var settings = Resources.FindObjectsOfTypeAll<PlayerSettings>();
if (settings != null && settings.Length > 0)
return EditorUtility.IsDirty(settings[0]);
return false;
#else
return false;
#endif
}

private static void ClearPlayerSettingsDirtyFlag()
{
#if UNITY_2019_OR_NEWER
var settings = Resources.FindObjectsOfTypeAll<PlayerSettings>();
if (settings != null && settings.Length > 0)
EditorUtility.ClearDirty(settings[0]);
#endif
}
}
}
11 changes: 11 additions & 0 deletions com.unity.ml-agents/Editor/MLAgentsSettingsBuildProvider.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3762dd2

Please sign in to comment.