Skip to content

Commit 5b5a360

Browse files
committed
v1.0.0-preview candidate
Added: - Switching between an asynchronous model `.Net` / `UniTask` - Complete Coroutine base operations for addressables management - Complete UniTask base operations for addressables management
1 parent e211326 commit 5b5a360

12 files changed

+348
-96
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
# v1.0.0-preview
4+
5+
### Added
6+
7+
- Switching between an asynchronous model `.Net` / `UniTask`
8+
- Complete Coroutine base operations for addressables management
9+
- Complete UniTask base operations for addressables management
10+
311
## v0.1.2
412

513
### Fixed

Editor.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Editor/UseUniTaskAsyncModel.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using System.Collections.Generic;
2+
using UnityEditor;
3+
4+
namespace AddressablesMasterDevelopment.Editor
5+
{
6+
internal static class UseUniTaskAsyncModel
7+
{
8+
private const string uniTaskSymbol = "USE_UNITASK";
9+
10+
11+
[MenuItem("Tools/Addressables Master/UniTask/On")]
12+
internal static void IncludeToSymbols()
13+
{
14+
if (DefineActivity())
15+
{
16+
EditorUtility.DisplayDialog("UniTask is supported",
17+
"UniTask is already used", "OK");
18+
}
19+
else
20+
{
21+
if (EditorUtility.DisplayDialog("Use UniTask Async Model?",
22+
"If UniTask support is enabled then all asynchronous code will use the UniTask async operations", "Yes", "No"))
23+
{
24+
DefineSymbols(true);
25+
}
26+
}
27+
}
28+
[MenuItem("Tools/Addressables Master/UniTask/Off")]
29+
internal static void ExcludeFromSymbols()
30+
{
31+
if (!DefineActivity())
32+
{
33+
EditorUtility.DisplayDialog("UniTask support is already turned off",
34+
"The .NET default async model is used", "OK");
35+
}
36+
else
37+
{
38+
if (EditorUtility.DisplayDialog("Disable UniTask support?",
39+
"This action will cause the use of the standard .NET async model", "Yes", "No"))
40+
{
41+
DefineSymbols(false);
42+
}
43+
}
44+
}
45+
46+
private static bool DefineActivity()
47+
{
48+
BuildTargetGroup currentTarget = EditorUserBuildSettings.selectedBuildTargetGroup;
49+
50+
List<string> scriptingSymbols =
51+
new List<string>(PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTarget).Split(';'));
52+
53+
return scriptingSymbols.Contains(uniTaskSymbol);
54+
}
55+
56+
private static void DefineSymbols(bool state)
57+
{
58+
BuildTargetGroup currentTarget = EditorUserBuildSettings.selectedBuildTargetGroup;
59+
60+
List<string> scriptingSymbols =
61+
new List<string>(PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTarget).Split(';'));
62+
63+
if (state)
64+
{
65+
if (!scriptingSymbols.Contains(uniTaskSymbol)) scriptingSymbols.Add(uniTaskSymbol);
66+
else return;
67+
}
68+
else
69+
{
70+
if (scriptingSymbols.Contains(uniTaskSymbol)) scriptingSymbols.Remove(uniTaskSymbol);
71+
else return;
72+
}
73+
74+
string finalScriptingSymbols = string.Join(";", scriptingSymbols.ToArray());
75+
PlayerSettings.SetScriptingDefineSymbolsForGroup(currentTarget, finalScriptingSymbols);
76+
}
77+
}
78+
}

Editor/UseUniTaskAsyncModel.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "inc8877.AddressablesMaster.Editor",
3+
"rootNamespace": "",
4+
"references": [],
5+
"includePlatforms": [
6+
"Editor"
7+
],
8+
"excludePlatforms": [],
9+
"allowUnsafeCode": false,
10+
"overrideReferences": false,
11+
"precompiledReferences": [],
12+
"autoReferenced": true,
13+
"defineConstraints": [],
14+
"versionDefines": [],
15+
"noEngineReferences": false
16+
}

Editor/inc8877.AddressablesMaster.Editor.asmdef.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 108 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,12 @@ If you find this project useful, star it, I will be grateful!
1616
- [Install via OpenUPM](#install-via-openupm)
1717
- [Install via Git URL](#install-via-git-url)
1818
- [How to use](#how-to-use)
19-
- [Sync](#sync)
20-
- [Examples](#examples)
21-
- [Async](#async)
22-
- [Examples](#examples-1)
19+
- [Intro](#intro)
20+
- [Short examples](#short-examples)
2321
- [Lifetime managment](#lifetime-managment)
2422
- [Addressables Extensions](#addressables-extensions)
25-
- [Examples](#examples-2)
26-
- [Examples](#examples-3)
23+
- [Management operations](#management-operations)
24+
- [Short examples](#short-examples-1)
2725
- [Credits](#credits)
2826

2927
## Roadmap
@@ -58,7 +56,9 @@ Open `Packages/manifest.json` with your favorite text editor. Add the following
5856

5957
## How to use
6058

61-
Plugin nampespace first.
59+
### Intro
60+
61+
Plug in namespace first.
6262

6363
```c#
6464
using AddressablesMaster;
@@ -70,24 +70,30 @@ All basic features for asset management are available along the following path:
7070
ManageAddressables.[SOME_COMMAND];
7171
```
7272

73-
The `AddressablesMaster` implements the ability to manage assets in several ways, synchronously, asynchronously and coroutines.
73+
Below is a list of operations that are available in each control model:
7474

75-
> Important! The use of an asynchronous model depends on the presence of `UniTask` in the project, if it does not exist in the project, then the `.NET` async system is used by default, if the project has `UniTask`, then it is used.
75+
- Initialize
76+
- LoadLocations
77+
- LoadAsset
78+
- LoadScene
79+
- UnloadScene
80+
- Instantiate
81+
- InstantiateWithAutoRelease
7682

77-
No matter which management model you use, each has basic control operations with its own unique implementation. For example this is how initialization looks like on each model:
83+
If you are using the `UniTask` in a project and want to use it in an asynchronous control model, then connect it by following the path `Tools > Addressables Master > UniTask > On`.
84+
`.NET` asynchronous operating model is used by default.
85+
> Carefully! If you switch the asynchronous model, all existing code will be invalidated as each model has its own implementation.
7886
79-
```c#
80-
ManageAddressables.InitializeSync();
81-
ManageAddressables.InitializeAsync();
82-
StartCoroutine(ManageAddressables.InitializeCoroutine());
83-
```
87+
### Short examples
8488

85-
For all examples we will use the following data:
89+
For examples we will take some data:
8690

8791
```c#
88-
public string keyOfAddressablesFigure;
89-
public AssetReferenceGameObject figureAssetRefGO;
90-
public AssetReferenceMaterial assetReferenceMaterial;
92+
// Some data for examples
93+
public string startupSound;
94+
public AssetReferenceGameObject props;
95+
public AssetReferenceMaterial material;
96+
public AudioSource audioSource;
9197

9298
[Serializable]
9399
public class AssetReferenceMaterial : AssetReferenceT<Material>
@@ -96,35 +102,45 @@ public class AssetReferenceMaterial : AssetReferenceT<Material>
96102
}
97103
```
98104

99-
### Sync
105+
`Sync`
100106

101-
When using a synchronous operation script, in response to a command output that has a return value, you will receive a value of the type specified in the signature of the operation being called, this seems obvious, but for example, by calling the same operation using the asynchronous model, you will get a custom type similar to an `AsyncOperationHandle`.
107+
```c#
108+
audioSource.PlayOneShot(ManageAddressables.LoadAssetSync<AudioClip>(startupSound));
109+
110+
var _material = ManageAddressables.LoadAssetSync(material);
111+
112+
ManageAddressables.InstantiateSync(props).GetComponent<MeshRenderer>().material = _material;
113+
```
102114

103-
#### Examples
115+
`Async .NET`
104116

105117
```c#
106-
ManageAddressables.InstantiateSync(keyOfAddressablesFigure).transform.position = Vector3.back;
107-
ManageAddressables.InstantiateSync(figureAssetRefGO);
108-
Debug.Log(ManageAddressables.LoadAssetSync(assetReferenceMaterial).color.a);
118+
ManageAddressables.LoadAssetAsync(material, _material => ManageAddressables.InstantiateAsync(props,
119+
onCompletion: _go => _go.GetComponent<MeshRenderer>().material = _material));
109120
```
110121

111-
### Async
122+
`Async UniTask`
112123

113-
When using a synchronous operation script, in response to a command output that has a return value, you will get a `Task` that contains as a result a custom class named `OperationResult` with several fields, `Succeeded` and `Value`. You can process this data in accordance with the logic of your project.
124+
```c#
125+
ManageAddressables.LoadAssetAsync(material).ContinueWith(result =>
126+
ManageAddressables.InstantiateAsync(props).ContinueWith(x =>
127+
x.Value.GetComponent<MeshRenderer>().material = result));
128+
```
114129

115-
#### Examples
130+
`Coroutine`
116131

117132
```c#
118-
ManageAddressables.InstantiateAsync(figureAssetRefGO, onCompletion: (go =>
119-
{
120-
ManageAddressables.LoadAssetAsync(assetReferenceMaterial, material => go.GetComponent<MeshRenderer>().material = material);
121-
}));
133+
StartCoroutine(ManageAddressables.LoadAssetCoroutine(material, (key1, result1) =>
134+
StartCoroutine(ManageAddressables.InstantiateCoroutine(props,
135+
onSucceeded: (key2, result2) => result2.GetComponent<MeshRenderer>().material = result1))));
122136
```
123137

124138
### Lifetime managment
125139

126140
When you load an addressable asset, you should release it as soon as you don't need it anymore, forgetting to do this can lead to many bad processes at runtime. Using the `Addressables Master` you can bind a release to the `GameoObject` that will do it for you automatically as soon as it is destroyed.
127141

142+
The `Addressables Master` has two ways to manage the release of objects, the first is to use [methods of extending the basic operations](#addressables-extensions) of the Addressables, the second is to use separate methods of life management.
143+
128144
#### Addressables Extensions
129145

130146
If you need to use standard operations for working with addressables assets, then you can use the extensions.
@@ -141,7 +157,7 @@ public static async Task<AsyncOperationHandle<T>> AddAutoRelease<T>(this AsyncOp
141157
public static async Task<AsyncOperationHandle<GameObject>> AddReleaseOnDestroy(this AsyncOperationHandle<GameObject> operationHandle)
142158
```
143159

144-
##### Examples
160+
Examples:
145161

146162
```c#
147163
GameObject go = new GameObject("Temp");
@@ -151,19 +167,75 @@ assetReferenceMaterial.LoadAssetAsync().AddAutoRelease(go);
151167
figureAssetRefGO.InstantiateAsync().AddReleaseOnDestroy();
152168
```
153169

170+
#### Management operations
171+
154172
`Sync`
155173

156174
```c#
157-
public static GameObject InstantiateSyncWithAutoRelease(AssetReference assetReference, Transform parent = null, bool inWorldSpace = false)
175+
public static GameObject InstantiateSyncWithAutoRelease(string key, Transform parent = null,
176+
bool inWorldSpace = false)
158177
```
159178

160-
`Async`
179+
```c#
180+
public static GameObject InstantiateSyncWithAutoRelease(AssetReference assetReference, Transform parent = null,
181+
bool inWorldSpace = false)
182+
```
183+
184+
`Async .NET`
185+
186+
```c#
187+
public static async Task<GameObject> InstantiateAsyncWithAutoRelease(string key, Transform parent = null,
188+
bool inWorldSpace = false, Action<GameObject> onCompletion = null)
189+
```
161190

162191
```c#
163192
public static async Task<GameObject> InstantiateAsyncWithAutoRelease(AssetReference assetReference, Transform parent = null, bool inWorldSpace = false)
164193
```
165194

166-
#### Examples
195+
`Async UniTask`
196+
197+
```c#
198+
public static async UniTask<GameObject> InstantiateAsyncWithAutoRelease(string key, Transform parent = null,
199+
bool inWorldSpace = false, Action<GameObject> onCompletion = null)
200+
```
201+
202+
```c#
203+
public static async UniTask<GameObject> InstantiateAsyncWithAutoRelease(AssetReference assetReference,
204+
Transform parent = null, bool inWorldSpace = false, Action<GameObject> onCompletion = null)
205+
```
206+
207+
`Coroutine`
208+
209+
```c#
210+
public static IEnumerator InstantiateWithAutoReleaseCoroutine(string key, Transform parent = null,
211+
bool inWorldSpace = false, bool trackHandle = true, Action<string, GameObject> onSucceeded = null,
212+
Action<string> onFailed = null)
213+
```
214+
215+
```c#
216+
public static IEnumerator InstantiateWithAutoReleaseCoroutine(AssetReference reference, Transform parent = null,
217+
bool inWorldSpace = false, Action<string, GameObject> onSucceeded = null, Action<string> onFailed = null)
218+
```
219+
220+
`Methods not tied to a specific management model`
221+
222+
```c#
223+
public static void AddAutoReleaseAssetTrigger(string key, GameObject targetGO)
224+
```
225+
226+
```c#
227+
public static void AddAutoReleaseAssetTrigger(AssetReference assetReference, GameObject targetGO)
228+
```
229+
230+
```c#
231+
public static void AddAutoReleaseInstanceTrigger(string key, GameObject targetGO)
232+
```
233+
234+
```c#
235+
public static void AddAutoReleaseInstanceTrigger(AssetReference assetReference, GameObject targetGO)
236+
```
237+
238+
#### Short examples
167239

168240
```c#
169241
ManageAddressables.InstantiateSyncWithAutoRelease(figureAssetRefGO);

Runtime/ManageAddressables.Async.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if !ADDRESSABLES_UNITASK
1+
#if !USE_UNITASK
22

33
using System;
44
using System.Runtime.CompilerServices;
@@ -123,14 +123,6 @@ public static async Task<OperationResult<T>> LoadAssetAsync<T>(AssetReferenceT<T
123123
}
124124
}
125125

126-
private static async Task ActivateAsync(SceneInstance scene, int priority)
127-
{
128-
var operation = scene.ActivateAsync();
129-
operation.priority = priority;
130-
131-
await operation;
132-
}
133-
134126
public static async Task<OperationResult<SceneInstance>> LoadSceneAsync(string key,
135127
LoadSceneMode loadMode = LoadSceneMode.Single,
136128
bool activateOnLoad = true,
@@ -320,7 +312,14 @@ public static async Task<GameObject> InstantiateAsyncWithAutoRelease(
320312

321313
return instantiatedGO;
322314
}
315+
316+
private static async Task ActivateAsync(SceneInstance scene, int priority)
317+
{
318+
var operation = scene.ActivateAsync();
319+
operation.priority = priority;
323320

321+
await operation;
322+
}
324323
}
325324

326325
internal static partial class AsyncOperationExtensions

0 commit comments

Comments
 (0)