# 在 Unity C#、JavaScript 和 C/C++/C# 代码之间创建回调

> Learn how to use callbacks to communicate between your plug-in, browser, and Unity project.

回调是 Web 开发的重要组成部分，因为它们可以改善 Unity 项目与 JavaScript 浏览器、JavaScript 插件和 C/C++/C# 插件之间的通信。您可能希望在 Unity C# 代码中从 C/C++/C# 或 JavaScript 代码调用函数，回调就是执行此操作的有效方法。

## 使用 makeDynCall 函数进行回调##use-the-makedyncall-function-to-make-callbacks

使用 `makeDynCall` 从 JavaScript 代码调用 C、C++ 或 C# 回调。例如，以下 JavaScript 代码调用函数 "callback"：

```js
{{{ makeDynCall('vii', 'callback') }}}(1, 2)
```

* `'vii'` 是参数的签名。例如，回调函数是 `void` 类型 (v)，而 `(1,2)` 都是整数 (ii)。
* `'callback'` 是回调函数的名称。
* `(1, 2)` 是要传递给函数的参数。

以下代码是使用函数 "onresponse" 执行回调并传入浮点 (f) 和多个整数类型值的另一个代码示例：

```js
{{{ makeDynCall('vfii', 'onresponse') }}}(2.8, arg, 0);
```

## 在脚本中使用回调##use-callbacks-in-your-scripts

以下脚本展示了如何使用回调函数在 JavaScript、C++ 和 C# 代码之间进行通信的示例。

### Javascript 插件代码##javascript-plug-in-code

以下代码是调度超时并调用回调的 `.jslib` 文件的示例。

```js
mergeInto(LibraryManager.library, {
    JsSetTimeout: function (message, timeout, callback) {
        // Create copy of message because it might be deleted before callback is run
        var stringMessage = UTF8ToString(message);
        var buffer = stringToNewUTF8(stringMessage);
        setTimeout(function () {
            {{{ makeDynCall('vi', 'callback') }}} (buffer);
            _free(buffer);
        }, timeout);
    }
});
```

### C++ 插件代码##c++-plug-in-code

以下代码是 C++ 文件的示例，该文件：

* 调用外部 JavaScript 函数 (`JsSetTimeout`)
* 包含发生超时时 JavaScript 调用的回调函数。

```cpp

// CallbackExample.cpp
#include <stdio.h>

typedef void (*OnTimeOutCallback)(char* message);

extern "C"
{
    void JsSetTimeout(char* message, int timeout, OnTimeOutCallback callback);
}

void CCallback(char* message)
{
    printf("C callback received \"%s\"\n", message);
}

extern "C" void SetCTimeout()
{
    JsSetTimeout("Hello World", 1000, CCallback);
}
```

### Unity C# 代码##unity-c-code

以下代码是 C# Unity 代码的示例，用于接收来自 C++ 和 JavaScript 回调的消息。

```cs
using AOT;
using System;
using System.Text;
using System.Runtime.InteropServices;
using UnityEngine;

public class CallbackExample : MonoBehaviour
{
    void Awake()
    {
        SetCSharpTimeout();
        SetCTimeout();
    }

    void SetCSharpTimeout()
    {
        JsSetTimeout("Hello World", 500, CSSharpCallback);
    }

    [DllImport("__Internal")]
    public static extern void SetCTimeout();    
    
    [DllImport("__Internal")]
    public static extern void JsSetTimeout(string message, int timeout, Action<string> action);

    [MonoPInvokeCallback(typeof(Action<string>))]
    public static void CSSharpCallback(string message)
    {
       Debug.Log($"C# callback received \"{message}\"");
    }
}
```

## 其他资源##additional-resources

* [与浏览器脚本交互](/engine/6000.0/manual/platform-specific/webgl/develop/interactingwithbrowserscripting.md)

* [设置 JavaScript 插件](/engine/6000.0/manual/platform-specific/webgl/develop/interactingwithbrowserscripting/web-interacting-browser-js.md)

* [从 Unity C# 脚本调用 JavaScript 函数](/engine/6000.0/manual/platform-specific/webgl/develop/interactingwithbrowserscripting/web-interacting-browser-js-to-unity.md)

* [从 JavaScript 调用 Unity C# 脚本函数](/engine/6000.0/manual/platform-specific/webgl/develop/interactingwithbrowserscripting/web-interacting-browser-unity-to-js.md)

* [从 Unity C# 脚本调用 C/C++/C# 函数](/engine/6000.0/manual/platform-specific/webgl/develop/interactingwithbrowserscripting/web-interacting-browsers-c-to-unity.md)

* [替换已弃用的浏览器交互代码](/engine/6000.0/manual/platform-specific/webgl/develop/interactingwithbrowserscripting/web-interacting-browser-deprecated.md)
