Skip to content

Commit 2820034

Browse files
committed
Initial write
1 parent c85df0b commit 2820034

File tree

534 files changed

+46560
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

534 files changed

+46560
-1
lines changed

UnityProject/Assets/AsyncUtil.meta

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

UnityProject/Assets/AsyncUtil/Source.meta

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using UnityEngine;
6+
7+
public class AsyncMonoBehaviourEvents : MonoBehaviour
8+
{
9+
static AsyncMonoBehaviourEvents _instance;
10+
11+
public static AsyncMonoBehaviourEvents Instance
12+
{
13+
get
14+
{
15+
if (_instance == null)
16+
{
17+
_instance = new GameObject("AsyncMonoBehaviourEvents")
18+
.AddComponent<AsyncMonoBehaviourEvents>();
19+
}
20+
21+
return _instance;
22+
}
23+
}
24+
25+
void Awake()
26+
{
27+
// Don't show in scene hierarchy
28+
gameObject.hideFlags = HideFlags.HideAndDontSave;
29+
30+
DontDestroyOnLoad(gameObject);
31+
}
32+
}

UnityProject/Assets/AsyncUtil/Source/AsyncMonoBehaviourEvents.cs.meta

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Runtime.CompilerServices;
5+
using System.Threading.Tasks;
6+
using UnityEngine;
7+
8+
public static class AwaitExtensions
9+
{
10+
public static TaskAwaiter<int> GetAwaiter(this Process process)
11+
{
12+
var tcs = new TaskCompletionSource<int>();
13+
process.EnableRaisingEvents = true;
14+
15+
process.Exited += (s, e) => tcs.TrySetResult(process.ExitCode);
16+
17+
if (process.HasExited)
18+
{
19+
tcs.TrySetResult(process.ExitCode);
20+
}
21+
22+
return tcs.Task.GetAwaiter();
23+
}
24+
25+
// Any time you call an async method from sync code, you should call this method
26+
// as well, otherwise any exceptions that occur inside the async code will not be
27+
// received by Unity. (Unity only observes errors for async methods that have return type void)
28+
public static async void WrapErrors(this Task task)
29+
{
30+
await task;
31+
}
32+
}

UnityProject/Assets/AsyncUtil/Source/AwaitExtensions.cs.meta

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Runtime.CompilerServices;
5+
using System.Threading.Tasks;
6+
using UnityEngine;
7+
8+
// We could just add a generic GetAwaiter to YieldInstruction and CustomYieldInstruction
9+
// but instead we add specific methods to each derived class to allow for return values
10+
// that make the most sense for the specific instruction type
11+
public static class IEnumeratorAwaitExtensions
12+
{
13+
public static TaskAwaiter<AsyncOperation> GetAwaiter(this AsyncOperation instruction)
14+
{
15+
return GetAwaiterReturnSelf(instruction);
16+
}
17+
18+
public static TaskAwaiter<object> GetAwaiter(this WaitForSeconds instruction)
19+
{
20+
return GetAwaiterReturnNull(instruction);
21+
}
22+
23+
public static TaskAwaiter<object> GetAwaiter(this WaitForEndOfFrame instruction)
24+
{
25+
return GetAwaiterReturnNull(instruction);
26+
}
27+
28+
public static TaskAwaiter<object> GetAwaiter(this WaitForFixedUpdate instruction)
29+
{
30+
return GetAwaiterReturnNull(instruction);
31+
}
32+
33+
public static TaskAwaiter<object> GetAwaiter(this WaitForSecondsRealtime instruction)
34+
{
35+
return GetAwaiterReturnNull(instruction);
36+
}
37+
38+
public static TaskAwaiter<object> GetAwaiter(this WaitUntil instruction)
39+
{
40+
return GetAwaiterReturnNull(instruction);
41+
}
42+
43+
public static TaskAwaiter<object> GetAwaiter(this WaitWhile instruction)
44+
{
45+
return GetAwaiterReturnNull(instruction);
46+
}
47+
48+
public static TaskAwaiter<UnityEngine.Object> GetAwaiter(this ResourceRequest instruction)
49+
{
50+
var tcs = new TaskCompletionSource<UnityEngine.Object>();
51+
AsyncMonoBehaviourEvents.Instance.StartCoroutine(
52+
InstructionWrappers.ResourceRequest(tcs, instruction));
53+
return tcs.Task.GetAwaiter();
54+
}
55+
56+
public static TaskAwaiter<UnityEngine.iOS.OnDemandResourcesRequest> GetAwaiter(this UnityEngine.iOS.OnDemandResourcesRequest instruction)
57+
{
58+
return GetAwaiterReturnSelf(instruction);
59+
}
60+
61+
// Return itself so you can do things like (await new WWW(url)).bytes
62+
public static TaskAwaiter<WWW> GetAwaiter(this WWW instruction)
63+
{
64+
return GetAwaiterReturnSelf(instruction);
65+
}
66+
67+
public static TaskAwaiter<AssetBundle> GetAwaiter(this AssetBundleCreateRequest instruction)
68+
{
69+
var tcs = new TaskCompletionSource<AssetBundle>();
70+
AsyncMonoBehaviourEvents.Instance.StartCoroutine(
71+
InstructionWrappers.AssetBundleCreateRequest(tcs, instruction));
72+
return tcs.Task.GetAwaiter();
73+
}
74+
75+
public static TaskAwaiter<UnityEngine.Object> GetAwaiter(this AssetBundleRequest instruction)
76+
{
77+
var tcs = new TaskCompletionSource<UnityEngine.Object>();
78+
AsyncMonoBehaviourEvents.Instance.StartCoroutine(
79+
InstructionWrappers.AssetBundleRequest(tcs, instruction));
80+
return tcs.Task.GetAwaiter();
81+
}
82+
83+
public static TaskAwaiter<object> GetAwaiter(this IEnumerator coroutine)
84+
{
85+
var tcs = new TaskCompletionSource<object>();
86+
var wrapper = new CoroutineWrapper(coroutine, tcs);
87+
AsyncMonoBehaviourEvents.Instance.StartCoroutine(wrapper.Run());
88+
return tcs.Task.GetAwaiter();
89+
}
90+
91+
// We'd prefer to return TaskAwaiter here instead since there is never a return
92+
// value for yield instructions, but I'm not sure how to get that working here
93+
// since TaskAwaiter<> does not inherit from TaskAwaiter and there isn't a
94+
// non generic version of TaskCompletionSource<>
95+
static TaskAwaiter<object> GetAwaiterReturnNull(object instruction)
96+
{
97+
var tcs = new TaskCompletionSource<object>();
98+
AsyncMonoBehaviourEvents.Instance.StartCoroutine(
99+
InstructionWrappers.ReturnNullValue(tcs, instruction));
100+
return tcs.Task.GetAwaiter();
101+
}
102+
103+
static TaskAwaiter<T> GetAwaiterReturnSelf<T>(T instruction)
104+
{
105+
var tcs = new TaskCompletionSource<T>();
106+
AsyncMonoBehaviourEvents.Instance.StartCoroutine(
107+
InstructionWrappers.ReturnSelf(tcs, instruction));
108+
return tcs.Task.GetAwaiter();
109+
}
110+
111+
static class InstructionWrappers
112+
{
113+
public static IEnumerator ReturnNullValue(
114+
TaskCompletionSource<object> tcs, object instruction)
115+
{
116+
yield return instruction;
117+
tcs.SetResult(null);
118+
}
119+
120+
public static IEnumerator AssetBundleCreateRequest(
121+
TaskCompletionSource<AssetBundle> tcs, AssetBundleCreateRequest instruction)
122+
{
123+
yield return instruction;
124+
tcs.SetResult(instruction.assetBundle);
125+
}
126+
127+
public static IEnumerator AssetBundleRequest(
128+
TaskCompletionSource<UnityEngine.Object> tcs, AssetBundleRequest instruction)
129+
{
130+
yield return instruction;
131+
tcs.SetResult(instruction.asset);
132+
}
133+
134+
public static IEnumerator ResourceRequest(
135+
TaskCompletionSource<UnityEngine.Object> tcs, ResourceRequest instruction)
136+
{
137+
yield return instruction;
138+
tcs.SetResult(instruction.asset);
139+
}
140+
141+
public static IEnumerator ReturnSelf<T>(
142+
TaskCompletionSource<T> tcs, T instruction)
143+
{
144+
yield return instruction;
145+
tcs.SetResult(instruction);
146+
}
147+
}
148+
149+
class CoroutineWrapper
150+
{
151+
readonly TaskCompletionSource<object> _tcs;
152+
readonly Stack<IEnumerator> _processStack;
153+
154+
public CoroutineWrapper(
155+
IEnumerator coroutine, TaskCompletionSource<object> tcs)
156+
{
157+
_processStack = new Stack<IEnumerator>();
158+
_processStack.Push(coroutine);
159+
_tcs = tcs;
160+
}
161+
162+
public IEnumerator Run()
163+
{
164+
while (true)
165+
{
166+
var topWorker = _processStack.Peek();
167+
168+
bool isDone;
169+
170+
try
171+
{
172+
isDone = !topWorker.MoveNext();
173+
}
174+
catch (Exception e)
175+
{
176+
_tcs.SetException(e);
177+
yield break;
178+
}
179+
180+
if (isDone)
181+
{
182+
_processStack.Pop();
183+
184+
if (_processStack.Count == 0)
185+
{
186+
_tcs.SetResult(topWorker.Current);
187+
yield break;
188+
}
189+
}
190+
191+
// We could just yield return nested IEnumerator's here but we choose to do
192+
// our own handling here so that we can catch exceptions in nested coroutines
193+
// instead of just top level coroutine
194+
if (topWorker.Current is IEnumerator)
195+
{
196+
_processStack.Push((IEnumerator)topWorker.Current);
197+
}
198+
else
199+
{
200+
// Return the current value to the unity engine so it can handle things like
201+
// WaitForSeconds, WaitToEndOfFrame, etc.
202+
yield return topWorker.Current;
203+
}
204+
}
205+
}
206+
}
207+
}

UnityProject/Assets/AsyncUtil/Source/IEnumeratorAwaitExtensions.cs.meta

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Diagnostics;
5+
using System.Runtime.CompilerServices;
6+
using System.Threading.Tasks;
7+
using UnityEngine;
8+
9+
public static class TaskExtensions
10+
{
11+
public static IEnumerator AsIEnumerator(this Task task)
12+
{
13+
while (!task.IsCompleted)
14+
{
15+
yield return null;
16+
}
17+
18+
if (task.IsFaulted)
19+
{
20+
throw task.Exception;
21+
}
22+
}
23+
24+
public static IEnumerator<T> AsIEnumerator<T>(this Task<T> task)
25+
where T : class
26+
{
27+
while (!task.IsCompleted)
28+
{
29+
yield return null;
30+
}
31+
32+
if (task.IsFaulted)
33+
{
34+
throw task.Exception;
35+
}
36+
37+
yield return task.Result;
38+
}
39+
}

UnityProject/Assets/AsyncUtil/Source/TaskExtensions.cs.meta

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

0 commit comments

Comments
 (0)