实时音视频
  • iOS
  • Android
  • macOS
  • Windows
  • HarmonyOS
  • Linux
  • Web
  • 小程序
  • Flutter
  • Electron
  • Unity3D : C#
  • uni-app
  • React Native
  • Cocos Creator
  • 产品简介
  • 下载
  • 快速开始
    • 跑通示例源码
    • 集成 SDK
    • 实现视频通话
    • 实时音视频 SDK 与实时语音 SDK 差异
    • 场景化音视频配置
  • 基础功能
  • 进阶功能
  • 常见错误码
  • 服务端 API
  • 客户端 API
  • 常见问题

集成 SDK

更新时间:2022-12-01 19:13

1 准备环境

在开始集成 ZEGO Express SDK 前,请确保开发环境满足以下要求:

  • Unity 2018.4.21f1 或以上版本(建议通过 Unity Hub 下载最新的 LTS 版本)。安装 Unity 时,请根据需要运行的平台,勾选对应的 "Plaforms" 模块一起下载。

  • 根据需要运行的平台,确保对应的开发环境和设备。

    • Android:Android 4.4 或以上版本且支持音视频的 Android 设备或模拟器(推荐使用真机),如果为真机,请开启“允许调试”选项。
    • iOS:Xcode 13.0 或以上版本,iOS 9.0 或以上版本且支持音视频的 iOS 设备或模拟器(推荐使用真机)。
    • macOS:macOS 10.11 或以上版本且支持音视频的 macOS 设备。
    • Windows:Windows 7 或以上版本且支持音视频的 Windows 设备;并安装 Visual Studio 2015 或以上版本。
    • Linux: 任意具有 GLIBC 2.16 或以上版本的 Linux 发行版系统(目前仅支持 x86_64 架构),libasound(ALSA),libv4l2(v4l utils),CMake 3.7 或以上版本。
  • 确保运行设备已经连接到 Internet。

2 集成 SDK

2.1 新建项目(可选)

此步骤以如何创建新项目为例,如果是集成到已有项目,可忽略此步。

单击 “新建” 按钮,选择 “3D” 模版,填写 “项目名称”,选择 “位置” 存放项目,单击 “创建” 按钮创建项目。

2.2 导入 SDK

目前,Unity 支持 Android、iOS、macOS、Windows、Linux 平台。

  1. 请参考 下载SDK包,下载最新版本的 SDK,下载完成后进行解压。

  2. 手动将 "Plugins", "Scripts" 两个目录到拷贝到开发者项目的 "Assets" 目录下,即可集成 SDK。

  3. 对于不同的运行平台,需要做一些额外处理。

    • Windows

      Unity 项目中不能存在同名的 .dll 文件,否则在 Build 时会出现 "Multiple plugins with the same name 'zegoexpressengine'" 错误。开发者需根据实际业务情况删除 Plugins/Windows 文件夹下的 x64 文件夹或 x86 文件夹,不准备运行到 Windows 平台则可以直接删除 Plugins/Windows 文件夹。

    • macOS

      在 Unity 2019.3 之前版本不支持将 macOS dylib 作为 Plugins,需要手动将 "libZegoExpressEngine.dylib" 重命名为 "ZegoExpressEngine.bundle" 才能正确导入 SDK,且 macOS 版本不能低于 10.5。

    • iOS

      导出 Xcode 工程后,直接运行可能会报如下错误:

      iOS 平台的 XCFramework 中有三个文件夹:

      • "ios-arm64_armv7" 是真机架构,用于真机运行调试以及上架发布。当需要在真机上运行时请保留此文件夹并删除其他两个。

      • "ios-arm64_×86_64-simulator" 是模拟器架构,用于模拟器运行调试。如果需要运行 iOS 模拟器请保留此文件夹并删除其他两个。(即当工程配置 iOS Target SDK 指定为 Simulator SDK 时)

      • "ios-arm64_×86_64-maccatalyst" 是 iOS MacCatalyst 架构,目前 Unity 暂不支持此架构,请直接删除。参考 https://forum.unity.com/threads/mac-catalyst.1183951/

    • Android

      构建 Android App 时也可能会提示存在多个 Windows dll 文件的问题。请按照上述 Windows 的处理方式操作。

3 设置权限

根据实际应用平台,设置 SDK 所需的摄像头和麦克风权限。

3.1 Android 平台

在 UNITY_2018_3_OR_NEWER 或以上版本中,Unity 不会主动获取摄像头和麦克风权限,需要开发者调用获取权限。

#if(UNITY_2018_3_OR_NEWER)
using UnityEngine.Android;
#endif
void Start()
{
#if (UNITY_2018_3_OR_NEWER)
    permissionList.Add(Permission.Microphone);
    permissionList.Add(Permission.Camera);
#endif
}
void Update()
{
#if (UNITY_2018_3_OR_NEWER)
    // 获取设备权限
    CheckPermission();
#endif
}
private void CheckPermission()
{
#if (UNITY_2018_3_OR_NEWER)
    foreach (string permission in permissionList)
    {
        if (Permission.HasUserAuthorizedPermission(permission))
        {
        }
        else
        {
            Permission.RequestUserPermission(permission);
        }
    }
#endif
}

3.2 iOS 平台

需要运行到 iOS 设备的项目,导出 Xcode 工程后,选择 Info.plist 文件,添加摄像头和麦克风权限。

4 界面自适应

由于 Android 设备和 iOS 设备的屏幕方向存在 Portrait、PortraitUpsideDown、LandscapeLeft、LandscapeRight 四种方向,为保证推流预览和拉流的显示界面始终在正确的方向,推荐在 Update 方法中添加以下代码。

private DeviceOrientation preOrientation=DeviceOrientation.Unknown;
void Update()
{
    #if UNITY_ANDROID||  UNITY_IPHONE
        if (engine != null)
        {
            if (preOrientation != Input.deviceOrientation)
            {

                if (Input.deviceOrientation == DeviceOrientation.Portrait)
                {
                    engine.SetAppOrientation(ZegoOrientation.ZegoOrientation_0);
                }
                else if (Input.deviceOrientation == DeviceOrientation.PortraitUpsideDown)
                {
                    engine.SetAppOrientation(ZegoOrientation.ZegoOrientation_180);
                }
                else if (Input.deviceOrientation == DeviceOrientation.LandscapeLeft)
                {
                    engine.SetAppOrientation(ZegoOrientation.ZegoOrientation_90);
                }
                else if (Input.deviceOrientation == DeviceOrientation.LandscapeRight)
                {
                    engine.SetAppOrientation(ZegoOrientation.ZegoOrientation_270);
                }
                preOrientation = Input.deviceOrientation;

            }
        }
    #endif
}

开发者也可根据实际业务情况,参考上述代码,通过调用 SetAppOrientation 接口传入对应角度,保证推流预览和拉流的显示界面始终在正确的方向。

5 常见问题

  1. 为什么在多次启用、停止编辑器调试过程中,Unity 会出现卡死的情况?

在编辑器运行程序调试时,请务必添加以下代码,避免 Unity 出现卡死的问题。

void OnApplicationQuit() {
    //It must be added for unity editor debugging, otherwise it will cause unity to be stuck
    ZegoExpressEngine.DestroyEngine();
}
  1. 导出 iOS Xcode 工程后还需要集成 ZegoExpressEngine.framework 吗?

需要集成,以 Unity 2019.4 导出的 Xcode 工程为例,需要在 “TARGETS > Build Phases > Embed Frameworks” 菜单集成 ZegoExpressEngine.framework。

否则运行到设备上时,可能会报出如下的错误:

no suitable image found.  Did find:
/private/var/containers/Bundle/Application/3CC0EE65-89C9-45F5-8E22-A4AC194DF260/hello.app/Frameworks/UnityFramework.framework/Frameworks/ZegoExpressEngine.framework/ZegoExpressEngine: code signature in (/private/var/containers/Bundle/Application/3CC0EE65-89C9-45F5-8E22-A4AC194DF260/hello.app/Frameworks/UnityFramework.framework/Frameworks/ZegoExpressEngine.framework/ZegoExpressEngine) not valid for use in process using Library Validation: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.

开发者也可参考以下的 ZEGO_BuildPostProcess.cs 文件,根据实际情况调整代码后,将文件放置在 Unity 的 Assets 目录下的 Editor 目录下,Unity 导出 Xcode 项目的过程中将自动完成 ZegoExpressEngine.framework 的集成,无须手动添加即可实现自动配置集成 ZegoExpressEngine.framework。

using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System.Collections;
#if UNITY_IOS
using UnityEditor.iOS.Xcode.Extensions;
using UnityEditor.iOS.Xcode;
#endif
using System.IO;

public class ZEGO_BuildPostProcess
{

    [PostProcessBuild]
    public static void OnPostprocessBuild(BuildTarget buildTarget, string path) {

        if (buildTarget == BuildTarget.iOS) {
            LinkLibraries (path);
        }
    }

    public static void LinkLibraries (string path) {
#if UNITY_IOS
        // linked library
        string projPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj";
        PBXProject proj = new PBXProject();
        proj.ReadFromFile(projPath);
        string target;
        string unityTargetGuid;

        var unityMainTargetGuidMethod = proj.GetType().GetMethod("GetUnityMainTargetGuid");

        if (unityMainTargetGuidMethod != null)
        {    
            target = (string)unityMainTargetGuidMethod.Invoke(proj, null);
        }
        else
        {
            target = proj.TargetGuidByName("Unity-iPhone");
        }

        var unityFrameworkTargetGuidMethod = proj.GetType().GetMethod("GetUnityFramworkTargetGuid");
        if(unityFrameworkTargetGuidMethod != null)
        {
            unityTargetGuid = (string)unityFrameworkTargetGuidMethod.Invoke(proj, null);
        }
        else
        {
            unityTargetGuid = proj.TargetGuidByName("UnityFramework");
        }

        // Disable bitcode
        proj.SetBuildProperty(unityTargetGuid, "ENABLE_BITCODE", "false");
        proj.SetBuildProperty(target, "ENABLE_BITCODE", "false");

        // Add default framework to main proj
        string defaultLocationInProj = path + "/Frameworks/Plugins/iOS/ZegoExpressEngine.xcframework/ios-arm64_armv7";//实际ZegoExrpessFramework路径
        string coreFrameworkName = "ZegoExpressEngine.framework";
        string framework = Path.Combine(defaultLocationInProj, coreFrameworkName);
        string fileGuid = proj.AddFile(framework, "/" + coreFrameworkName, PBXSourceTree.Source);
        PBXProjectExtensions.AddFileToEmbedFrameworks(proj, target, fileGuid);

        // Write proj
        File.WriteAllText(projPath, proj.WriteToString());

        // Add permission
        string pListPath = path + "/Info.plist";
        PlistDocument plist = new PlistDocument();
        plist.ReadFromString(File.ReadAllText(pListPath));
        PlistElementDict rootDic = plist.root;
        var cameraPermission = "NSCameraUsageDescription";
        var micPermission = "NSMicrophoneUsageDescription";
        rootDic.SetString(cameraPermission, "Video need to use camera");
        rootDic.SetString(micPermission, "Voice call need to user mic");
        File.WriteAllText(pListPath, plist.WriteToString());

#endif
    }

}
  1. 为什么集成 SDK 后在 Unity Editor 调试过程中创建 SDK 经常失败?

如果仅在 Unity Editor 中出现创建 SDK 失败,请检查 Unity Editor 是否有如下的配置:

/Pics/Unity3D/ZegoExpressEngine/Unity_Editor.png

如果按图中勾选了对应设置,Unity Editor 在停止调试后一段时间会缓存静态变量,导致 SDK 内部静态变量没有重置而出现异常,表现为首次 CreateEngine 成功,Unity Player 停止运行后再启动 CreateEngine 失败,详情请参考 域重新加载