Skip to content

Commit 8c1bb80

Browse files
com.utilities.extensions 1.2.0 (#26)
- refactored addressables extensions with modernized async patterns - updated editor to latest 2021 LTS - updated package deps - updated workflows
1 parent 55c35bd commit 8c1bb80

File tree

3 files changed

+76
-46
lines changed

3 files changed

+76
-46
lines changed

Documentation~/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ The recommended installation method is though the unity package manager and [Ope
1212

1313
### Via Unity Package Manager and OpenUPM
1414

15+
#### Terminal
16+
17+
```terminal
18+
openupm add com.utilities.extensions
19+
```
20+
21+
#### Manual
22+
1523
- Open your Unity project settings
1624
- Select the `Package Manager`
1725
![scoped-registries](images/package-manager-scopes.png)

Runtime/Addressables/AddressablesExtensions.cs

Lines changed: 67 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using UnityEngine.AddressableAssets;
1010
using UnityEngine.ResourceManagement.AsyncOperations;
1111
using Utilities.Async;
12-
using Utilities.Async.Addressables;
1312

1413
namespace Utilities.Extensions
1514
{
@@ -38,110 +37,133 @@ public static void Release(this AsyncOperationHandle handle)
3837
/// </summary>
3938
/// <param name="key">Path.</param>
4039
/// <param name="progress">Optional, <see cref="IProgress{T}"/></param>
41-
public static async Task DownloadAddressableAsync(object key, IProgress<float> progress = null)
40+
/// <param name="cancellationToken">Optional, <see cref="CancellationToken"/></param>
41+
public static async Task DownloadAddressableAsync(object key, IProgress<float> progress = null, CancellationToken cancellationToken = default)
4242
{
4343
var downloadSizeOp = Addressables.GetDownloadSizeAsync(key);
44-
var downloadSize = await downloadSizeOp;
45-
downloadSizeOp.Release();
44+
long downloadSize;
45+
46+
try
47+
{
48+
downloadSize = await downloadSizeOp.Task.WithCancellation(cancellationToken);
49+
}
50+
finally
51+
{
52+
downloadSizeOp.Release();
53+
}
4654

4755
if (downloadSize > 0)
4856
{
49-
await Addressables.DownloadDependenciesAsync(key).AwaitWithProgress(progress);
57+
await Addressables.DownloadDependenciesAsync(key).AwaitWithProgress(progress, true, cancellationToken);
5058
}
5159
}
5260

5361
/// <summary>
5462
/// Wait on the <see cref="AsyncOperationHandle{T}"/> with the provided <see cref="IProgress{T}"/>
5563
/// </summary>
5664
/// <typeparam name="T"></typeparam>
57-
/// <param name="operation"></param>
58-
/// <param name="progress"></param>
59-
/// <param name="autoRelease"></param>
60-
public static async Task<T> AwaitWithProgress<T>(this AsyncOperationHandle<T> operation, IProgress<float> progress, bool autoRelease = true)
65+
/// <param name="operation"><see cref="AsyncOperationHandle{T}"/></param>
66+
/// <param name="progress">Optional, <see cref="IProgress{T}"/></param>
67+
/// <param name="autoRelease">Should the <see cref="AsyncOperationHandle{T}"/> be automatically released? Defaults to true.</param>
68+
/// <param name="cancellationToken">Optional, <see cref="CancellationToken"/></param>
69+
public static async Task<T> AwaitWithProgress<T>(this AsyncOperationHandle<T> operation, IProgress<float> progress, bool autoRelease = true, CancellationToken cancellationToken = default)
6170
{
6271
Thread backgroundThread = null;
6372

6473
if (progress != null)
6574
{
66-
backgroundThread = new Thread(() => ProgressThread(operation, progress))
75+
backgroundThread = new Thread(() => ProgressThread(operation, progress, cancellationToken))
6776
{
6877
IsBackground = true
6978
};
7079
}
7180

72-
backgroundThread?.Start();
73-
var result = await operation.Task;
74-
backgroundThread?.Join();
75-
76-
var opException = operation.OperationException;
81+
T result;
7782

78-
if (autoRelease)
83+
try
7984
{
80-
operation.Release();
85+
backgroundThread?.Start();
86+
result = await operation.Task.WithCancellation(cancellationToken);
8187
}
82-
83-
if (opException != null)
88+
finally
8489
{
85-
throw opException;
86-
}
90+
backgroundThread?.Join();
91+
progress?.Report(100f);
92+
93+
var opException = operation.OperationException;
8794

88-
progress?.Report(100f);
95+
if (autoRelease)
96+
{
97+
operation.Release();
98+
}
99+
if (opException != null)
100+
{
101+
throw opException;
102+
}
103+
}
89104

90105
return result;
91106
}
92107

93108
/// <summary>
94109
/// Wait on the <see cref="AsyncOperationHandle"/> with the provided <see cref="IProgress{T}"/>
95110
/// </summary>
96-
/// <param name="operation"></param>
97-
/// <param name="progress"></param>
98-
/// <param name="autoRelease"></param>
99-
public static async Task AwaitWithProgress(this AsyncOperationHandle operation, IProgress<float> progress, bool autoRelease = true)
111+
/// <param name="operation"><see cref="AsyncOperationHandle"/></param>
112+
/// <param name="progress">Optional, <see cref="IProgress{T}"/></param>
113+
/// <param name="autoRelease">Should the <see cref="AsyncOperationHandle"/> be automatically released? Defaults to true.</param>
114+
/// <param name="cancellationToken">Optional, <see cref="CancellationToken"/></param>
115+
public static async Task AwaitWithProgress(this AsyncOperationHandle operation, IProgress<float> progress, bool autoRelease = true, CancellationToken cancellationToken = default)
100116
{
101117
Thread backgroundThread = null;
102118

103119
if (progress != null)
104120
{
105-
backgroundThread = new Thread(() => ProgressThread(operation, progress))
121+
backgroundThread = new Thread(() => ProgressThread(operation, progress, cancellationToken))
106122
{
107123
IsBackground = true
108124
};
109125
}
110126

111-
backgroundThread?.Start();
112-
await operation.Task;
113-
backgroundThread?.Join();
114-
115-
var opException = operation.OperationException;
116-
117-
if (autoRelease)
127+
try
118128
{
119-
operation.Release();
129+
backgroundThread?.Start();
130+
await operation.Task.WithCancellation(cancellationToken);
120131
}
121-
122-
if (opException != null)
132+
finally
123133
{
124-
throw opException;
125-
}
134+
backgroundThread?.Join();
135+
var opException = operation.OperationException;
136+
137+
if (autoRelease)
138+
{
139+
operation.Release();
140+
}
141+
142+
if (opException != null)
143+
{
144+
throw opException;
145+
}
126146

127-
progress?.Report(100f);
147+
progress?.Report(100f);
148+
}
128149
}
129150

130-
private static async void ProgressThread(AsyncOperationHandle handle, IProgress<float> progress)
151+
private static async void ProgressThread(AsyncOperationHandle handle, IProgress<float> progress, CancellationToken cancellationToken)
131152
{
132-
await Awaiters.UnityMainThread;
133-
134153
try
135154
{
136-
while (handle.IsValid() && !handle.IsDone)
155+
// ensure we're on main thread.
156+
await Awaiters.UnityMainThread;
157+
158+
while (handle.IsValid() && !handle.IsDone && !cancellationToken.IsCancellationRequested)
137159
{
138160
if (handle.OperationException != null)
139161
{
140162
break;
141163
}
142164

143165
progress.Report(handle.PercentComplete * 100f);
144-
await Awaiters.UnityMainThread;
166+
await Task.Yield();
145167
}
146168
}
147169
catch (Exception)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "Utilities.Extensions",
44
"description": "Common extensions for Unity types (UPM)",
55
"keywords": [],
6-
"version": "1.1.17",
6+
"version": "1.2.0",
77
"unity": "2021.3",
88
"documentationUrl": "https://github.com/RageAgainstThePixel/com.utilities.extensions#documentation",
99
"changelogUrl": "https://github.com/RageAgainstThePixel/com.utilities.extensions/releases",

0 commit comments

Comments
 (0)