11using System ;
22using System . Collections ;
33using UnityEngine ;
4+ using Action = System . Action ;
45using Object = UnityEngine . Object ;
56
67// ReSharper disable once CheckNamespace
@@ -13,6 +14,10 @@ namespace GameLovers.Services
1314 /// </summary>
1415 public interface IAsyncCoroutine
1516 {
17+ /// <summary>
18+ /// Get the execution status of the coroutine
19+ /// </summary>
20+ bool IsRunning { get ; }
1621 /// <summary>
1722 /// Get the complete operation status of the coroutine
1823 /// </summary>
@@ -21,30 +26,34 @@ public interface IAsyncCoroutine
2126 /// Get the current coroutine being executed
2227 /// </summary>
2328 Coroutine Coroutine { get ; }
29+ /// <summary>
30+ /// The Unity time the coroutine started
31+ /// </summary>
32+ float StartTime { get ; }
2433
2534 /// <summary>
2635 /// Sets the action <paramref name="onComplete"/> callback to be invoked when the coroutine is completed
2736 /// </summary>
2837 void OnComplete ( Action onComplete ) ;
38+ /// <summary>
39+ /// Stops the execution of this coroutine
40+ /// </summary>
41+ void StopCoroutine ( bool triggerOnComplete = false ) ;
2942 }
3043
31- /// <inheritdoc cref="IAsyncCoroutine" />
32- public interface IAsyncCoroutine < T >
44+ /// <inheritdoc />
45+ public interface IAsyncCoroutine < T > : IAsyncCoroutine
3346 {
34- /// <inheritdoc cref="IAsyncCoroutine.IsCompleted"/>
35- bool IsCompleted { get ; }
36- /// <inheritdoc cref="IAsyncCoroutine.Coroutine"/>
37- Coroutine Coroutine { get ; }
3847 /// <summary>
3948 /// The data to be returned on the coroutine completion
4049 /// </summary>
41- T Data { get ; }
50+ T Data { get ; set ; }
4251
4352 /// <summary>
4453 /// Sets the action <paramref name="onComplete"/> callback to be invoked when the coroutine is completed with the
45- /// <paramref name="data "/> reference in the callback
54+ /// <seealso cref="Data "/> reference in the callback
4655 /// </summary>
47- void OnComplete ( T data , Action < T > onComplete ) ;
56+ void OnComplete ( Action < T > onComplete ) ;
4857 }
4958
5059 /// <summary>
@@ -70,9 +79,20 @@ public interface ICoroutineService : IDisposable
7079 IAsyncCoroutine StartAsyncCoroutine ( IEnumerator routine ) ;
7180 /// <summary>
7281 /// Follows the same principle and execution of <see cref="MonoBehaviour.StartCoroutine(IEnumerator)"/> but returns
73- /// a <see cref="IAsyncCoroutine{T}"/> to provide a callback on complete of the coroutine with given <typeparamref name="T "/> type
82+ /// a <see cref="IAsyncCoroutine{T}"/> to provide a callback on complete of the coroutine with given <paramref name="data "/>
7483 /// </summary>
75- IAsyncCoroutine < T > StartAsyncCoroutine < T > ( IEnumerator routine ) ;
84+ IAsyncCoroutine < T > StartAsyncCoroutine < T > ( IEnumerator routine , T data ) ;
85+ /// <summary>
86+ /// Executes <paramref name="call"/> in a <see cref="StartAsyncCoroutine"/> with the given <paramref name="delay"/>.
87+ /// Useful for delay callbacks
88+ /// </summary>
89+ IAsyncCoroutine StartDelayCall ( Action call , float delay ) ;
90+ /// <summary>
91+ /// Executes <paramref name="call"/> in a <see cref="StartAsyncCoroutine"/> with the given <paramref name="delay"/>
92+ /// and <paramref name="data"/> data type.
93+ /// Useful for delay callbacks
94+ /// </summary>
95+ IAsyncCoroutine < T > StartDelayCall < T > ( Action < T > call , T data , float delay ) ;
7696 /// <inheritdoc cref="MonoBehaviour.StopCoroutine(Coroutine)"/>
7797 void StopCoroutine ( Coroutine coroutine ) ;
7898 /// <inheritdoc cref="MonoBehaviour.StopAllCoroutines"/>
@@ -86,7 +106,7 @@ public class CoroutineService : ICoroutineService
86106
87107 public CoroutineService ( )
88108 {
89- var gameObject = new GameObject ( typeof ( CoroutineServiceMonoBehaviour ) . Name ) ;
109+ var gameObject = new GameObject ( nameof ( CoroutineServiceMonoBehaviour ) ) ;
90110
91111 _serviceObject = gameObject . AddComponent < CoroutineServiceMonoBehaviour > ( ) ;
92112
@@ -120,23 +140,45 @@ public Coroutine StartCoroutine(IEnumerator routine)
120140 /// <inheritdoc />
121141 public IAsyncCoroutine StartAsyncCoroutine ( IEnumerator routine )
122142 {
123- var asyncCoroutine = new AsyncCoroutine ( ) ;
143+ var asyncCoroutine = new AsyncCoroutine ( this ) ;
124144
125145 asyncCoroutine . SetCoroutine ( _serviceObject . ExternalStartCoroutine ( InternalCoroutine ( routine , asyncCoroutine ) ) ) ;
126146
127147 return asyncCoroutine ;
128148 }
129149
130150 /// <inheritdoc />
131- public IAsyncCoroutine < T > StartAsyncCoroutine < T > ( IEnumerator routine )
151+ public IAsyncCoroutine < T > StartAsyncCoroutine < T > ( IEnumerator routine , T data )
132152 {
133- var asyncCoroutine = new AsyncCoroutine < T > ( ) ;
153+ var asyncCoroutine = new AsyncCoroutine < T > ( this , data ) ;
134154
135155 asyncCoroutine . SetCoroutine ( _serviceObject . ExternalStartCoroutine ( InternalCoroutine ( routine , asyncCoroutine ) ) ) ;
136156
137157 return asyncCoroutine ;
138158 }
139-
159+
160+ /// <inheritdoc />
161+ public IAsyncCoroutine StartDelayCall ( Action call , float delay )
162+ {
163+ var asyncCoroutine = new AsyncCoroutine ( this ) ;
164+
165+ asyncCoroutine . OnComplete ( call ) ;
166+ asyncCoroutine . SetCoroutine ( _serviceObject . ExternalStartCoroutine ( InternalDelayCoroutine ( delay , asyncCoroutine ) ) ) ;
167+
168+ return asyncCoroutine ;
169+ }
170+
171+ /// <inheritdoc />
172+ public IAsyncCoroutine < T > StartDelayCall < T > ( Action < T > call , T data , float delay )
173+ {
174+ var asyncCoroutine = new AsyncCoroutine < T > ( this , data ) ;
175+
176+ asyncCoroutine . OnComplete ( call ) ;
177+ asyncCoroutine . SetCoroutine ( _serviceObject . ExternalStartCoroutine ( InternalDelayCoroutine ( delay , asyncCoroutine ) ) ) ;
178+
179+ return asyncCoroutine ;
180+ }
181+
140182 /// <inheritdoc />
141183 public void StopCoroutine ( Coroutine coroutine )
142184 {
@@ -165,22 +207,38 @@ private static IEnumerator InternalCoroutine(IEnumerator routine, ICompleteCorou
165207
166208 completed . Completed ( ) ;
167209 }
210+
211+ private static IEnumerator InternalDelayCoroutine ( float delayInSeconds , ICompleteCoroutine completed )
212+ {
213+ yield return new WaitForSeconds ( delayInSeconds ) ;
214+
215+ completed . Completed ( ) ;
216+ }
168217
169218 #region Private Interfaces
170219
171220 private interface ICompleteCoroutine
172221 {
173222 void Completed ( ) ;
174-
175- void SetCoroutine ( Coroutine coroutine ) ;
176223 }
177224
178225 private class AsyncCoroutine : IAsyncCoroutine , ICompleteCoroutine
179226 {
227+ private readonly ICoroutineService _coroutineService ;
228+
180229 private Action _onComplete ;
181230
231+ public bool IsRunning => Coroutine != null ;
182232 public bool IsCompleted { get ; private set ; }
183233 public Coroutine Coroutine { get ; private set ; }
234+ public float StartTime { get ; } = Time . time ;
235+
236+ private AsyncCoroutine ( ) { }
237+
238+ public AsyncCoroutine ( ICoroutineService coroutineService )
239+ {
240+ _coroutineService = coroutineService ;
241+ }
184242
185243 public void SetCoroutine ( Coroutine coroutine )
186244 {
@@ -192,6 +250,13 @@ public void OnComplete(Action onComplete)
192250 _onComplete = onComplete ;
193251 }
194252
253+ public void StopCoroutine ( bool triggerOnComplete = false )
254+ {
255+ _coroutineService . StopCoroutine ( Coroutine ) ;
256+
257+ OnCompleteTrigger ( ) ;
258+ }
259+
195260 public void Completed ( )
196261 {
197262 if ( IsCompleted )
@@ -201,41 +266,35 @@ public void Completed()
201266
202267 IsCompleted = true ;
203268 Coroutine = null ;
204-
269+
270+ OnCompleteTrigger ( ) ;
271+ }
272+
273+ protected virtual void OnCompleteTrigger ( )
274+ {
205275 _onComplete ? . Invoke ( ) ;
206276 }
207277 }
208278
209- private class AsyncCoroutine < T > : IAsyncCoroutine < T > , ICompleteCoroutine
279+ private class AsyncCoroutine < T > : AsyncCoroutine , IAsyncCoroutine < T >
210280 {
211281 private Action < T > _onComplete ;
212-
213- public bool IsCompleted { get ; private set ; }
214- public Coroutine Coroutine { get ; private set ; }
215- public T Data { get ; private set ; }
282+
283+ public T Data { get ; set ; }
216284
217- public void SetCoroutine ( Coroutine coroutine )
285+ public AsyncCoroutine ( ICoroutineService coroutineService , T data ) : base ( coroutineService )
218286 {
219- Coroutine = coroutine ;
287+ Data = data ;
220288 }
221289
222- public void OnComplete ( T data , Action < T > onComplete )
290+ public void OnComplete ( Action < T > onComplete )
223291 {
224292 _onComplete = onComplete ;
225-
226- Data = data ;
227293 }
228294
229- public void Completed ( )
295+ protected override void OnCompleteTrigger ( )
230296 {
231- if ( IsCompleted )
232- {
233- return ;
234- }
235-
236- IsCompleted = true ;
237- Coroutine = null ;
238-
297+ base . OnCompleteTrigger ( ) ;
239298 _onComplete ? . Invoke ( Data ) ;
240299 }
241300 }
0 commit comments