unity3d 在Unity中将协程转换为异步Await方法?

3htmauhk  于 2022-11-16  发布在  其他
关注(0)|答案(2)|浏览(387)

假设在Unity中,我使用一个Web API来获得JSON响应。

public IEnumerator GetCompletion(string prompt, System.Action<string> callback, float temperature = 0.8f)
{
    UnityWebRequest www = UnityWebRequest.Post("https://api.openai.com/v1/completions", "");
    // ... snip ....

    yield return www.SendWebRequest();
    if (www.result == UnityWebRequest.Result.ConnectionError)
    {
        Debug.Log(www.error);
        www.Dispose();
        yield return null;
    }
    else
    {
        www.Dispose();
        callback?.Invoke(GetResultFromJson(www.downloadHandler.text));
    }
}

我可以通过

const string prompt = "Albert Einstein was";
StartCoroutine(
    textAI.GetCompletion(prompt, (string result) =>
    {
        Debug.Log(result);
    },
    temperature: 0.5f
));

我如何重构这个协程方法以使用C#的Await和Async方法?
我没有任何特别的最终目标,除了可能使事情更容易阅读,因为在调用时嵌套较少(当协程需要另一个coutroutine时,或者当我需要同时等待多个coutroutine时也是如此)。谢谢!

wn9m85ua

wn9m85ua1#

如果你有时间的话,Unity正计划使用现代的C#技术。Await/async正在规划中。

IEnumerator Start() {
    yield return SceneManager.LoadSceneAsync("somescene");
    var task = SomeTaskBasedApi(CancellationToken.None);
    yield return null
}

应该是这样的:

async void Start() {
    var result = await PrepareSceneAndCallAPI();
    await AwaitableCoroutine.NextFrameAsync(CancellationToken);
}

来源:Unity and .NET Whats next

pkln4tw6

pkln4tw62#

我不知道是否有更简单的答案,但是可以从Asset Store导入免费的UniRx

using UnityEngine;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;

public static class Extensions
{
    public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp)
    {
        var tcs = new TaskCompletionSource<object>();
        asyncOp.completed += obj => { tcs.SetResult(null); };
        return ((Task)tcs.Task).GetAwaiter();
    }
}

现在可以使用以下功能代码:

using System.Threading.Tasks;
// ... snip ...

public async Task<string> GetCompletion(string prompt, float temperature = 0.8f)
{
    UnityWebRequest www = UnityWebRequest.Post("https://api.openai.com/v1/completions", "");
    // ... snip ...

    await www.SendWebRequest();
    if (www.result == UnityWebRequest.Result.ConnectionError)
    {
        Debug.Log(www.error);
        www.Dispose();
        return null;
    }
    else
    {
        www.Dispose();
        return GetResultFromJson(www.downloadHandler.text);
    }

    return null;
}

它可以这样命名

async void Test()
{
    string result = await textAI.GetCompletion_Async("Albert Einstein was");
    Debug.Log("Result:");
}

相关问题