Skip to content

Commit 3762dd2

Browse files
author
Ruo-Ping Dong
authored
Add custom package settings (#5027)
1 parent 1d2806d commit 3762dd2

22 files changed

+682
-4
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
# Environemnt logfile
1313
*Project.log
1414

15+
# Custom settings asset
16+
*.settings.asset*
17+
1518
# Visual Studio 2015 cache directory
1619
/Project/.vs/
1720

DevProject/Assets/ML-Agents/Scripts/Tests/Editor/Tests.asmdef renamed to DevProject/Assets/ML-Agents/Scripts/Tests/Editor/Editor.asmdef

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "Unity.ML-Agents.Performance.Tests",
2+
"name": "Unity.ML-Agents.DevTests.Editor",
33
"references": [
44
"Unity.ML-Agents.Editor",
55
"Unity.ML-Agents",

DevProject/Assets/ML-Agents/Scripts/Tests/Editor/Tests.asmdef.meta renamed to DevProject/Assets/ML-Agents/Scripts/Tests/Editor/Editor.asmdef.meta

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

DevProject/Assets/ML-Agents/Scripts/Tests/Editor/MLAgentsSettings.meta

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using System.Reflection;
5+
using NUnit.Framework;
6+
using UnityEditor;
7+
using UnityEngine;
8+
using Unity.MLAgents;
9+
using Unity.MLAgents.Editor;
10+
11+
12+
namespace MLAgentsExamples.Tests.Settings
13+
{
14+
[TestFixture]
15+
public class MLAgentsSettingsTests
16+
{
17+
string EditorBuildSettingsConfigKey = MLAgentsSettingsManager.EditorBuildSettingsConfigKey;
18+
string tempSettingsRootPath = "Assets/ML-Agents/Scripts/Tests/Editor/MLAgentsSettings";
19+
MLAgentsSettings storedConfigObject;
20+
[SetUp]
21+
public void SetUp()
22+
{
23+
if (EditorBuildSettings.TryGetConfigObject(EditorBuildSettingsConfigKey,
24+
out MLAgentsSettings settingsAsset))
25+
{
26+
if (settingsAsset != null)
27+
{
28+
storedConfigObject = settingsAsset;
29+
EditorBuildSettings.RemoveConfigObject(EditorBuildSettingsConfigKey);
30+
}
31+
}
32+
MLAgentsSettingsManager.Destroy();
33+
ClearSettingsAssets();
34+
}
35+
36+
[TearDown]
37+
public void TearDown()
38+
{
39+
if (storedConfigObject != null)
40+
{
41+
EditorBuildSettings.AddConfigObject(EditorBuildSettingsConfigKey, storedConfigObject, true);
42+
storedConfigObject = null;
43+
}
44+
MLAgentsSettingsManager.Destroy();
45+
ClearSettingsAssets();
46+
}
47+
48+
internal void ClearSettingsAssets()
49+
{
50+
var assetsGuids = AssetDatabase.FindAssets("t:MLAgentsSettings", new string[] { tempSettingsRootPath });
51+
foreach (var guid in assetsGuids)
52+
{
53+
var path = AssetDatabase.GUIDToAssetPath(guid);
54+
AssetDatabase.DeleteAsset(path);
55+
}
56+
}
57+
58+
[Test]
59+
public void TestMLAgentsSettingsManager()
60+
{
61+
Assert.AreNotEqual(null, MLAgentsSettingsManager.Settings);
62+
Assert.AreEqual(5004, MLAgentsSettingsManager.Settings.EditorPort); // default port
63+
MLAgentsSettingsManager.Settings.EditorPort = 6000;
64+
Assert.AreEqual(6000, MLAgentsSettingsManager.Settings.EditorPort);
65+
66+
var settingsObject = ScriptableObject.CreateInstance<MLAgentsSettings>();
67+
settingsObject.EditorPort = 7000;
68+
var tempSettingsAssetPath = tempSettingsRootPath + "/test.mlagents.settings.asset";
69+
AssetDatabase.CreateAsset(settingsObject, tempSettingsAssetPath);
70+
EditorBuildSettings.AddConfigObject(EditorBuildSettingsConfigKey, settingsObject, true);
71+
// destroy manager instantiated as a side effect by accessing MLAgentsSettings directly without manager
72+
MLAgentsSettingsManager.Destroy();
73+
Assert.AreEqual(7000, MLAgentsSettingsManager.Settings.EditorPort);
74+
}
75+
76+
// A mock class that can invoke private methods/fields in MLAgentsSettingsProvider
77+
internal class MockSettingsProvider
78+
{
79+
public MLAgentsSettingsProvider Instance
80+
{
81+
get
82+
{
83+
return (MLAgentsSettingsProvider)typeof(MLAgentsSettingsProvider).GetField("s_Instance",
84+
BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
85+
}
86+
}
87+
88+
public MLAgentsSettings Settings
89+
{
90+
get
91+
{
92+
return (MLAgentsSettings)typeof(MLAgentsSettingsProvider).GetField("m_Settings",
93+
BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Instance);
94+
}
95+
}
96+
97+
public void CreateMLAgentsSettingsProvider()
98+
{
99+
MLAgentsSettingsProvider.CreateMLAgentsSettingsProvider();
100+
}
101+
102+
public void Reinitialize()
103+
{
104+
var method = typeof(MLAgentsSettingsProvider).GetMethod("Reinitialize",
105+
BindingFlags.Instance | BindingFlags.NonPublic);
106+
method.Invoke(Instance, null);
107+
}
108+
109+
public string[] FindSettingsInProject()
110+
{
111+
var method = typeof(MLAgentsSettingsProvider).GetMethod("FindSettingsInProject",
112+
BindingFlags.Static | BindingFlags.NonPublic);
113+
return (string[])method.Invoke(null, null);
114+
}
115+
116+
public void CreateNewSettingsAsset(string relativePath)
117+
{
118+
var method = typeof(MLAgentsSettingsProvider).GetMethod("CreateNewSettingsAsset",
119+
BindingFlags.Static | BindingFlags.NonPublic);
120+
method.Invoke(null, new object[] { relativePath });
121+
}
122+
}
123+
124+
[Test]
125+
public void TestMLAgentsSettingsProviderCreateAsset()
126+
{
127+
var mockProvider = new MockSettingsProvider();
128+
mockProvider.CreateMLAgentsSettingsProvider();
129+
Assert.AreNotEqual(null, mockProvider.Instance);
130+
131+
// mimic MLAgentsSettingsProvider.OnActivate()
132+
MLAgentsSettingsManager.OnSettingsChange += mockProvider.Reinitialize;
133+
134+
mockProvider.Instance.InitializeWithCurrentSettings();
135+
Assert.AreEqual(0, mockProvider.FindSettingsInProject().Length);
136+
137+
var tempSettingsAssetPath1 = tempSettingsRootPath + "/test.mlagents.settings.asset";
138+
mockProvider.CreateNewSettingsAsset(tempSettingsAssetPath1);
139+
Assert.AreEqual(1, mockProvider.FindSettingsInProject().Length);
140+
Assert.AreEqual(5004, mockProvider.Settings.EditorPort);
141+
MLAgentsSettingsManager.Settings.EditorPort = 6000; // change to something not default
142+
// callback should update the field in provider
143+
Assert.AreEqual(6000, mockProvider.Settings.EditorPort);
144+
145+
var tempSettingsAssetPath2 = tempSettingsRootPath + "/test2.mlagents.settings.asset";
146+
mockProvider.CreateNewSettingsAsset(tempSettingsAssetPath2);
147+
Assert.AreEqual(2, mockProvider.FindSettingsInProject().Length);
148+
// manager should set to the new (default) one, not the previous modified one
149+
Assert.AreEqual(5004, MLAgentsSettingsManager.Settings.EditorPort);
150+
151+
// mimic MLAgentsSettingsProvider.OnDeactivate()
152+
MLAgentsSettingsManager.OnSettingsChange -= mockProvider.Reinitialize;
153+
mockProvider.Instance.Dispose();
154+
}
155+
156+
[Test]
157+
public void TestMLAgentsSettingsProviderLoadAsset()
158+
{
159+
var mockProvider = new MockSettingsProvider();
160+
var tempSettingsAssetPath1 = tempSettingsRootPath + "/test.mlagents.settings.asset";
161+
mockProvider.CreateNewSettingsAsset(tempSettingsAssetPath1);
162+
MLAgentsSettingsManager.Settings.EditorPort = 8000; // change to something not default
163+
164+
mockProvider.Instance?.Dispose();
165+
MLAgentsSettingsManager.Destroy();
166+
167+
mockProvider.CreateMLAgentsSettingsProvider();
168+
Assert.AreEqual(8000, MLAgentsSettingsManager.Settings.EditorPort);
169+
}
170+
}
171+
}

DevProject/Assets/ML-Agents/Scripts/Tests/Editor/MLAgentsSettings/MLAgentsSettingsTests.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

DevProject/Assets/ML-Agents/Scripts/Tests/Runtime/AcademyTest/AcademyStepperTest.cs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class AcademyStepperTest
1515
[SetUp]
1616
public void Setup()
1717
{
18+
Academy.Instance.Dispose();
1819
SceneManager.LoadScene("ML-Agents/Scripts/Tests/Runtime/AcademyTest/AcademyStepperTestScene");
1920
}
2021

DevProject/Assets/ML-Agents/Scripts/Tests/Runtime/Runtime.asmdef

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "Runtime",
2+
"name": "Unity.ML-Agents.DevTests.Runtime",
33
"references": [
44
"Unity.ML-Agents"
55
],

com.unity.ml-agents/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ details.
2525
#### com.unity.ml-agents / com.unity.ml-agents.extensions (C#)
2626
- 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)
2727
- 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)
28+
- Added ML-Agents package settings. (#5027)
2829
#### ml-agents / ml-agents-envs / gym-unity (Python)
2930

3031
### Bug Fixes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System.Linq;
2+
using UnityEngine;
3+
using UnityEditor;
4+
using UnityEditor.Build;
5+
using UnityEditor.Build.Reporting;
6+
7+
8+
namespace Unity.MLAgents.Editor
9+
{
10+
internal class MLAgentsSettingsBuildProvider : IPreprocessBuildWithReport, IPostprocessBuildWithReport
11+
{
12+
private MLAgentsSettings m_SettingsAddedToPreloadedAssets;
13+
14+
public int callbackOrder => 0;
15+
16+
public void OnPreprocessBuild(BuildReport report)
17+
{
18+
var wasDirty = IsPlayerSettingsDirty();
19+
m_SettingsAddedToPreloadedAssets = null;
20+
21+
var preloadedAssets = PlayerSettings.GetPreloadedAssets().ToList();
22+
if (!preloadedAssets.Contains(MLAgentsSettingsManager.Settings))
23+
{
24+
m_SettingsAddedToPreloadedAssets = MLAgentsSettingsManager.Settings;
25+
preloadedAssets.Add(m_SettingsAddedToPreloadedAssets);
26+
PlayerSettings.SetPreloadedAssets(preloadedAssets.ToArray());
27+
}
28+
29+
if (!wasDirty)
30+
ClearPlayerSettingsDirtyFlag();
31+
}
32+
33+
public void OnPostprocessBuild(BuildReport report)
34+
{
35+
if (m_SettingsAddedToPreloadedAssets == null)
36+
return;
37+
38+
var wasDirty = IsPlayerSettingsDirty();
39+
40+
var preloadedAssets = PlayerSettings.GetPreloadedAssets().ToList();
41+
if (preloadedAssets.Contains(m_SettingsAddedToPreloadedAssets))
42+
{
43+
preloadedAssets.Remove(m_SettingsAddedToPreloadedAssets);
44+
PlayerSettings.SetPreloadedAssets(preloadedAssets.ToArray());
45+
}
46+
47+
m_SettingsAddedToPreloadedAssets = null;
48+
49+
if (!wasDirty)
50+
ClearPlayerSettingsDirtyFlag();
51+
}
52+
53+
54+
private static bool IsPlayerSettingsDirty()
55+
{
56+
#if UNITY_2019_OR_NEWER
57+
var settings = Resources.FindObjectsOfTypeAll<PlayerSettings>();
58+
if (settings != null && settings.Length > 0)
59+
return EditorUtility.IsDirty(settings[0]);
60+
return false;
61+
#else
62+
return false;
63+
#endif
64+
}
65+
66+
private static void ClearPlayerSettingsDirtyFlag()
67+
{
68+
#if UNITY_2019_OR_NEWER
69+
var settings = Resources.FindObjectsOfTypeAll<PlayerSettings>();
70+
if (settings != null && settings.Length > 0)
71+
EditorUtility.ClearDirty(settings[0]);
72+
#endif
73+
}
74+
}
75+
}

com.unity.ml-agents/Editor/MLAgentsSettingsBuildProvider.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)