Lingara Lingara 文档 学习指南 API 库 应用 构建 嵌入 网页版
语言: 中文简体

Unity

本页译自英文。如两者有出入,以英文页面为准。 阅读英文页面

Lingara.Embed 是构建在 Lingara 玩家核心之上的 NuGet 软件包。它为玩家工具包支持的五个平台分别携带原生库:Windows、macOS、Linux、Android 和 iOS。

安装软件包

Unity 本身不会读取 NuGet 软件包,所以先安装 NuGetForUnity。然后按下方所示,把 Lingara.Embed 添加到 Assets/packages.config 中。NuGetForUnity 会还原该软件包,并把每个平台的原生库放到 Unity 期望的位置。

下方的示例组件 LingaraEmbedBehaviour 不属于该软件包:把它的源代码放入你的项目,挂到一个 GameObject 上,并监听它的 C# 事件。它在唤醒时创建客户端,并在被销毁时、游戏退出时以及编辑器重新加载你的脚本之前释放客户端。

从你的服务器获取令牌

该软件包从不持有密钥。当客户端需要令牌时,会通过 TokenNeeded 事件告知。组件用一个协程响应它,该协程向你自己服务器的令牌路由发送 POST 请求,服务器用服务器工具包签发令牌,并返回令牌及其过期时间。如果你的服务器无法响应,请调用 TokenUnavailable,让等待令牌的调用立即失败,而不是等到超时。

在 Update 中清空事件

核心在自己的线程上执行网络 I/O。在 Update 中,组件清空自上一帧以来到达的内容,每帧最多 256 个事件,并逐一分发:令牌请求、流式的 NPC 回复(见 NPC 对话)、练习更新(见练习结果)、关于玩家的事件,或者失败。

Unity

<?xml version="1.0" encoding="utf-8"?>
<!-- Assets/packages.config, after installing NuGetForUnity: it restores Lingara.Embed and places each platform's native library. -->
<packages>
  <package id="Lingara.Embed" version="0.1.0-alpha.6" manuallyInstalled="true" />
</packages>

Unity

[Serializable]
private struct Handoff { public string token; public string expires_at; }

// Your own server mints the token: never put a client secret in a game.
private IEnumerator FetchToken()
{
    using (var request = UnityWebRequest.PostWwwForm(tokenUrl, string.Empty))
    {
        yield return request.SendWebRequest();
        if (Client == null) yield break;
        if (request.result != UnityWebRequest.Result.Success)
        {
            Client.TokenUnavailable(request.error); // fail the waiting calls now
            yield break;
        }
        var handoff = JsonUtility.FromJson<Handoff>(request.downloadHandler.text);
        Client.ProvideToken(handoff.token, handoff.expires_at);
    }
}

Unity

private void Update()
{
    if (Client == null) return;
    events.Clear();
    Client.Drain(events); // at most 256 a frame; the rest wait for the next
    foreach (var e in events)
    {
        switch (e)
        {
            case EmbedEvent.TokenNeeded _: StartCoroutine(FetchToken()); break;
            case EmbedEvent.NpcTurn turn: NpcTurn?.Invoke(turn); break;
            case EmbedEvent.Practice practice: Practice?.Invoke(practice); break;
            case EmbedEvent.LingaraReceived received: LingaraReceived?.Invoke(received); break;
            case EmbedEvent.Failed failed: Failed?.Invoke(failed); break;
            case EmbedEvent.Log log: Debug.Log($"[lingara] {log.Level} {log.Target}: {log.Message}"); break;
        }
    }
}