#UniTask Completion issue
1 messages ยท Page 1 of 1 (latest)
I'm not sure what you trying to achieve. Why do you have two StartSpawn, when the second should by ignored?
Two calls is for example.
In my project spawner creates objects until it fills up. When player triggers the trigger objects pops out from storage and spawner should fill up again
I'm trying to prevent double spawn task
At the moment thats how it works
private void OnEnable()
{
_stash.OnRemove += (c) => StartSpawn();
StartSpawn();
}
private void OnDisable()
{
_stash.OnRemove -= (c) => StartSpawn();
}
private async void StartSpawn()
{
if (_spawnFlag) return;
_spawnFlag = true;
while (!_stash.IsFull())
{
await UniTask.Delay(TimeSpan.FromSeconds(_spawnRate));
Spawn();
}
_spawnFlag = false;
}
private void Spawn()
{
var point = _stash.GetPoint();
var pickupable = _cubePool.Pull(point.position);
pickupable.DisableCollider();
_stash.Add(pickupable);
}
Oh, i got it now. Let me think a minute
Each time when Object got removed from stash spawner class should fill up again
Probably thats not how to work with async and you can get result only after completion but I wonder if its possible to cache already existing task and check if its completed or not
Yeah, It's possible and it's probably the best way. I'm trying to get some example for you, but I don't have a UniTask currently in any project, so it's a little pain
private void StartSpawn()
{
if (_spawningTask?.Status == Pending)
{
return;
}
_spawningTask = ActualSpawn().Forget();
}
private async UniTask ActualSpawn()
{
await UniTask.Delay(TimeSpan.FromSeconds(_spawnRate));
Spawn();
}```
I'm not sure if Forget will return the UniTask
"Also UniTask has the Forget method, it is similar to UniTaskVoid and has the same effects. However UniTaskVoid is more efficient if you completely don't use awaitใ"
" If you don't require awaiting (fire and forget), using UniTaskVoid is better. Unfortunately to dismiss warning, you're required to call Forget()."
From docs
So Forget() means that you can execute and return void (i mean nothing)?
Yeah, when you don't wanna wait for result
Ok, let my try to implement it and share results
Good luck ๐
With a few changes it now works like i wanted.
- Removed Forget() coz its gives me exception (Token version is not matched)
private UniTask _spawningTask;
private void StartSpawn()
{
if (_spawningTask.Status == UniTaskStatus.Pending)
{
Debug.Log("Already started");
return;
}
_spawningTask = ActualSpawn();
}
private async UniTask ActualSpawn()
{
while (!_stash.IsFull())
{
await UniTask.Delay(TimeSpan.FromSeconds(_spawnRate));
Spawn();
}
Debug.Log("Done");
}
UniTask is the struct so thats why im not getting null exception when checking status?
oh right, I completly forget about it. Yeah, thats why
But does this mean that UniTask variable is "empty" and can create problems?
Yeah, it has some default value it could be problematic, I'm not sure what defualt status it is
default status is Succeeded
If you await empty variable it gives nothing. Interesting how it can be tracked (something like nullref)
It's probably not possible to be tracked
maybe the better way will be to use that Awaiter, and check for this status
I just feel wrong when comparing status to variable that not associated with method yet
Yeah, feels kinda dangerous
Yea
Gonna check this code right now
var awaiter = _spawningTask.GetAwaiter();
if (!awaiter.Equals(ActualSpawn()))
{
_spawningTask = ActualSpawn();
}
if (_spawningTask.Status == UniTaskStatus.Pending)
{
return;
}
_spawningTask.Forget();
I found some my old code with UniTask. We use UniTask.CompletedTask as initial value
so, it can be private UniTask _spawningTask = UniTask.CompletedTask and thats seems a lot better for me
Hm, yeah looks like
Im made something, gonna test out, share results with you and make conclusion
Feels like i just gonna use your method
I'm not sure if there is some discord or something dedicated for UniTask, but maybe someone has a better way for this
but we use it UniTask.CompletedTask as initial value in production code, so it should be somehow valid ๐
Maybe, but im not trying to make everything perfect at the moment because lack of knowledge
good enough it's always the best ๐
Yea
interesting thread people, im also using Unitask
adopted it like 1 month ago, before i was using mostly coroutines and normal Tasks
When i was playing around with our result i found out that every time when you trying to spawn, it creates a new task that stores garbage. I saw it in UniTask Tracker.
The solution is to add Preserve().
private void StartSpawn()
{
if (_spawningTask.Status == UniTaskStatus.Pending) return;
_spawningTask = ActualSpawn().Preserve();
_spawningTask.Forget();
}
"Store to the class field, you can use UniTask.Lazy that supports calling multiple times. .Preserve() allows for multiple calls (internally cached results). This is useful when there are multiple calls in a function scope."
Now it clears out after success and gives no errors after new call
Cool, I didn't know that
please see #archived-code-advanced message because what was discussed here is really verbose and complicated