1. 项目概述当Fay遇见UE5一个超写实数字人的诞生如果你和我一样一直在寻找一个既能快速集成AI对话能力又能驱动高保真虚拟形象的开源方案那么Fay数字人框架与Unreal Engine 5的结合绝对是一个值得投入时间研究的“宝藏”组合。这不仅仅是把一个人物模型放到引擎里那么简单它打通了从后端智能决策到前端实时渲染的完整链路让你能亲手打造一个会思考、会表达、表情生动的“数字员工”或“虚拟伙伴”。简单来说Fay负责“大脑”和“神经系统”。它是一个集成了大语言模型LLM和语音技术的开源框架能处理自然语言对话、生成语音、分析情感并输出对应的表情和口型指令。而UE5则扮演着“身体”和“世界”的角色。凭借其Nanite虚拟几何体和Lumen全局光照等次世代技术它能以电影级的画质实时渲染出毛孔级精度的数字人并流畅地驱动其面部表情与肢体动作。我们的工作就是在这两者之间架起一座高速、稳定的“桥梁”——通过WebSocket等通信协议让Fay的指令精准地控制UE5中数字人的一颦一笑。这套方案适合谁对于虚拟主播、数字员工、沉浸式教育或导览应用的开发者来说它提供了一个从零到一的完整参考。对于技术美术TA或引擎程序员这是一个深入理解AI驱动动画与实时渲染结合的绝佳案例。即使你是个UE新手跟着教程一步步走也能亲眼见证一个静态模型如何“活”过来。接下来我会结合我实际对接中的经验拆解从环境搭建到高级优化的全流程并分享那些官方文档里不会写的“坑”和技巧。2. 核心思路与架构设计为什么是FayUE5在动手写第一行代码之前理解整个系统的设计思路至关重要。这能帮助你在遇到问题时快速定位是通信、渲染还是逻辑层的故障。2.1 技术选型背后的逻辑为什么选择Fay而不是其他数字人框架核心在于它的“AI原生”与“开源可定制”。许多商业数字人方案是黑盒你很难修改其内部的对话逻辑或情感分析模型。Fay则把LLM集成、语音合成TTS、语音识别ASR以及最重要的——情感与表情的映射逻辑——都开源了出来。这意味着你可以根据你的应用场景训练或微调专属的AI模型让数字人的反应更贴合你的业务需求。例如做一个法律咨询数字人你可以强化其严谨、冷静的语料和对应表情做一个游戏NPC则可以注入更多夸张和戏剧化的反应。为什么选择UE5而不是Unity或其他引擎答案在于“超写实”与“生产管线成熟度”。UE5的MetaHuman Creator生态是目前创建高保真数字人门槛最低、效果最好的方案没有之一。它提供了一整套从扫描数据级的面部模型、成千上万个Blendshape形变目标到高度完善的骨骼绑定Rig。这意味着你无需从零开始建模、绑定骨骼、雕刻表情而是可以直接在MetaHuman Creator里通过滑块“捏”出一个独一无二的角色并导出UE5完全兼容的资源。此外UE5的动画蓝图Animation Blueprint和控制绑定Control Rig系统为接收外部数据驱动面部动画提供了极其灵活和强大的节点化编程能力。2.2 系统架构拆解整个系统可以清晰地分为四个层次理解每一层的职责对接时才能有的放矢。AI与业务逻辑层Fay后端这是系统的大脑。它部署在服务器或本地通常是一个Python服务。它接收用户的文本或语音输入调用LLM如GPT、ChatGLM等生成回复文本再通过TTS引擎将文本转为语音音频流。同时Fay的核心功能在于它能分析生成文本的情感色彩如开心、悲伤、惊讶并将其量化为一系列面部动作单元Facial Action Units的强度值。这些数据音频流表情参数就是需要发送给UE5的“指令”。通信传输层WebSocket/HTTP这是连接大脑与身体的神经。为什么常用WebSocket而不是普通的HTTP因为数字人的交互需要双向、低延迟、持续的数据流。HTTP的“请求-响应”模式不适合实时推送表情参数和音频流。WebSocket建立一次连接后双方可以随时互发消息完美适配音频流传输和实时表情控制。消息格式通常采用轻量级的JSON结构清晰易于解析。渲染与驱动层UE5客户端这是系统的身体。UE5项目运行在用户终端PC、移动设备或云端串流。它需要做三件事建立连接启动一个WebSocket客户端连接到Fay后端服务。解析与驱动接收并解析JSON消息。将表情参数映射到角色面部的Morph Target形变目标或骨骼动画上将音频流数据送入音频组件播放并同步驱动基于音频分析的嘴唇同步Lip Sync动画。超写实渲染利用UE5的渲染管线对数字人模型进行实时渲染呈现皮肤次表面散射、眼球湿润感、发丝细节等效果。资源层包括数字人模型FBX/ABC格式、骨骼绑定、材质贴图、动画序列等所有静态资源。这部分的质量直接决定了最终效果的保真度。注意在实际架构中为了减轻UE5客户端的计算压力通常会将语音识别ASR放在Fay后端进行。即用户通过麦克风输入语音到UE5UE5将音频流发送给FayFay完成语音转文本后再走完整的AI生成流程。这样UE5只负责渲染、播放和简单的音频转发架构更清晰。3. 环境准备与项目初始化避开第一个坑万事开头难环境配置往往是劝退第一关。按照以下步骤可以确保你有一个干净、可用的起点。3.1 开发环境清单与版本控制软件清单Unreal Engine 5版本建议5.3或5.4。这两个是长期支持LTS版本稳定性和插件兼容性最好。务必通过Epic Games Launcher安装并勾选安装“Android”或“iOS”平台支持即使你目前不做移动端因为这会包含一些必要的编译工具链。Python版本3.8 到 3.11。Fay后端通常基于此版本范围。强烈建议使用conda或venv创建独立的虚拟环境避免包冲突。Git用于克隆Fay项目代码。IDEUE5开发推荐使用Visual Studio 2022(社区版即可) 并安装“使用C的游戏开发”工作负载。Python开发推荐VSCode或PyCharm。第一个实操心得UE5源码编译 vs 预编译版本如果你需要深度修改引擎或集成特定插件需要下载UE5源码进行编译。但这过程耗时可能数小时且对硬件要求高32GB内存是舒适起点。对于大多数对接开发直接使用Epic Games Launcher提供的预编译版本是最快最稳的选择。我们对接Fay99%的工作在项目层面无需动引擎源码。3.2 Fay后端服务部署详解获取代码git clone https://gitcode.com/GitHub_Trending/fay/Fay.git cd Fay进入目录后先别急着运行。花5分钟浏览一下项目结构。通常你会看到config配置文件、core核心逻辑、tts语音合成、llm大语言模型接口等目录。理解结构有助于后续自定义。安装依赖与常见坑pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple坑点一网络超时。使用国内镜像源如-i https://pypi.tuna.tsinghua.edu.cn/simple能极大提升成功率。坑点二特定版本冲突。如果遇到某个包如torch安装失败或版本不兼容先别慌。打开requirements.txt看看有时可以适当放宽版本限制如torch1.10.0改为torch让pip自动选择兼容版本。或者根据错误信息单独安装指定版本。坑点三系统级依赖缺失。在Windows上可能需要安装Microsoft Visual C Redistributable在Linux上可能需要libasound2-dev音频相关。根据报错提示搜索解决。配置与启动 找到配置文件可能是config.yaml或config.ini你需要配置几个关键项LLM API密钥如OpenAI的API Key或本地部署的ChatGLM等模型的访问地址。TTS服务选择并配置一个TTS服务如微软Azure Speech、Google TTS或开源的VITS等。Fay通常支持多种。WebSocket服务器设置指定服务监听的IP和端口如0.0.0.0:8080。 配置完成后启动服务python main.py --mode ue5 --port 8080看到类似“WebSocket server started on port 8080”的日志说明后端大脑已经就绪。3.3 UE5客户端项目搭建创建或打开项目如果你有Fay提供的UE5示例工程模板直接打开.uproject文件。如果没有就新建一个第三人称游戏C项目。选择C项目是因为后续我们大概率需要编写C代码或插件来高效处理WebSocket通信。启用必需插件进入编辑Edit - 插件Plugins。搜索并启用“WebSockets”插件。这是UE官方插件提供了WebSocket客户端功能。搜索并启用“Audio Synesthesia”插件。这个插件用于音频分析是实现嘴唇同步的关键。重启编辑器以使插件生效。项目设置关键项编辑 - 项目设置 - 引擎 - 网络确保相关网络功能正常。编辑 - 项目设置 - 平台 - Windows或其他目标平台在“打包Packaging”设置中将Fay后端可能用到的Python脚本或其他资源文件目录添加到“附加非资产Additional Non-Asset”目录中确保打包时这些文件能被包含。4. 数字人模型导入与资产准备从MetaHuman到UE5角色这是视觉效果的基础步骤繁琐但每一步都直接影响最终效果。4.1 使用MetaHuman Creator创建角色访问与准备通过Epic Games Launcher打开Quixel Bridge登录你的Epic账户。在MetaHuman标签页中你可以浏览大量预设角色。自定义角色选择一个基础模型后点击“在MetaHuman Creator中编辑”。这个基于浏览器的工具功能强大面部特征你可以像玩高级捏脸游戏一样调整五官、脸型、年龄特征。技巧不要调得过于夸张尽量在预设的“自然”范围内否则可能导致表情动画失真。发型与妆容选择发型、眉毛、胡须调整化妆和皮肤细节。身体选择体型、身高搭配服装。导出完成创作后点击“导出Export”。关键设置如下导出目标选择“Unreal Engine”。细节水平LOD勾选所有LOD确保不同距离下的模型质量。骨骼Rig必须勾选“包含骨骼Include Rig”。这是动画驱动的根本。动画蓝图建议勾选“生成MetaHuman动画蓝图”。这会自动创建一个基础的动画蓝图省去很多手动配置的麻烦。纹理分辨率根据你的项目性能要求选择通常2K是平衡画质与性能的好选择。 导出后你会得到一个包含FBX文件、纹理贴图和UE5工程文件的压缩包。4.2 在UE5中导入与配置导入资产在UE5内容浏览器中右键选择“导入到/Game...”选择导出的.fbx文件。在导入选项中保持默认设置即可引擎能很好地识别MetaHuman格式。创建角色蓝图导入后你会得到骨骼网格体Skeletal Mesh、材质、动画蓝图等资产。右键点击骨骼网格体选择“创建 - 角色蓝图Blueprint Class based on Skeletal Mesh”。这将以你的模型为基础创建一个可放置到关卡中的Actor。打开这个角色蓝图在组件面板中确保骨骼网格体组件已正确赋值。配置动画蓝图打开随模型一起导入或生成的动画蓝图通常命名为ABP_MetaHuman。这是数字人的“运动中枢”。我们后续从Fay接收的表情参数最终将输入到这里驱动面部形变。在动画蓝图中找到“事件图表Event Graph”和“动画图表Anim Graph”。事件图表用于处理逻辑如接收外部数据动画图表用于混合最终姿势。4.3 材质与光照初步优化材质检查MetaHuman的材质已经非常完善但你可以打开其材质实例进行微调例如皮肤红润度Rudiness、油脂感Specular等使其更符合场景色调。光照设置为了测试数字人建议创建一个简单的测试关卡。添加一个“定向光源Directional Light”作为主光源。添加一个“天光Sky Light”并点击“捕获场景Capture Scene”来获取环境光照。启用Lumen在项目设置 - 引擎 - 渲染中确保“全局光照Global Illumination”和“反射Reflections”方法都设置为“Lumen”。这是实现实时超写实光照的关键。调整光源角度和强度观察数字人面部的光影变化是否自然。好的布光能立刻提升角色的真实感。5. 核心通信与驱动实现让数字人“活”起来这是技术核心我们将建立Fay与UE5的对话通道并让数据驱动模型。5.1 WebSocket通信模块实现在UE5中我们通常需要编写一个C类或使用蓝图来管理WebSocket连接。这里以C为例因为它更稳定、高效。创建WebSocket客户端类 在UE5 C项目中新建一个继承自UObject的类例如FayWebSocketClient。在头文件中引入WebSocket模块并声明关键函数。// FayWebSocketClient.h #pragma once #include CoreMinimal.h #include UObject/NoExportTypes.h #include IWebSocket.h // 需要包含WebSocket头文件 #include FayWebSocketClient.generated.h UCLASS() class YOURPROJECT_API UFayWebSocketClient : public UObject { GENERATED_BODY() public: UFayWebSocketClient(); // 连接服务器 void Connect(const FString ServerUrl); // 发送消息 void SendMessage(const FString Message); // 关闭连接 void Close(); // 声明一个委托当收到消息时广播 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMessageReceived, const FString, Message); UPROPERTY(BlueprintAssignable) FOnMessageReceived OnMessageReceived; private: TSharedPtrIWebSocket WebSocket; void OnConnected(); void OnMessage(const FString Message); void OnError(const FString Error); };实现连接与消息处理// FayWebSocketClient.cpp #include FayWebSocketClient.h #include WebSocketsModule.h // 必须包含 #include Modules/ModuleManager.h void UFayWebSocketClient::Connect(const FString ServerUrl) { // 确保WebSocket模块已加载 if (!FModuleManager::Get().IsModuleLoaded(WebSockets)) { FModuleManager::Get().LoadModule(WebSockets); } // 创建WebSocket连接 WebSocket FWebSocketsModule::Get().CreateWebSocket(ServerUrl); // 绑定回调函数 WebSocket-OnConnected().AddLambda([this]() { OnConnected(); }); WebSocket-OnMessage().AddLambda([this](const FString Msg) { OnMessage(Msg); }); WebSocket-OnConnectionError().AddLambda([this](const FString Error) { OnError(Error); }); // 开始连接 WebSocket-Connect(); } void UFayWebSocketClient::OnMessage(const FString Message) { // 当收到Fay后端发来的消息时通过委托广播出去 UE_LOG(LogTemp, Log, TEXT(Received: %s), *Message); OnMessageReceived.Broadcast(Message); }将这个类实例化并保存到你的GameInstance或某个全局管理器中在游戏开始时调用Connect(ws://localhost:8080)。5.2 表情数据解析与映射Fay后端发送的表情数据通常是JSON格式包含了表情类型和强度。我们需要在UE5中解析它并应用到模型的Morph Target上。定义数据结构与解析 首先定义与Fay协议匹配的数据结构并使用UE5的Json解析库。// 在某个头文件或.cpp中定义 struct FExpressionData { FString Type; // 如 smile, blink_left float Intensity; // 强度 0.0 ~ 1.0 float Duration; // 可选持续时间 }; // 解析JSON字符串到FExpressionData bool ParseExpressionJson(const FString JsonString, TArrayFExpressionData OutExpressions) { TSharedPtrFJsonObject JsonObject; TSharedRefTJsonReader Reader TJsonReaderFactory::Create(JsonString); if (FJsonSerializer::Deserialize(Reader, JsonObject) JsonObject.IsValid()) { // 根据Fay实际的JSON结构进行解析 // 示例假设数据在 {expressions: [{type:smile, intensity:0.7}, ...]} 中 const TArrayTSharedPtrFJsonValue* ExpressionArray; if (JsonObject-TryGetArrayField(TEXT(expressions), ExpressionArray)) { for (auto Elem : *ExpressionArray) { auto Obj Elem-AsObject(); FExpressionData Data; Obj-TryGetStringField(TEXT(type), Data.Type); Obj-TryGetNumberField(TEXT(intensity), Data.Intensity); OutExpressions.Add(Data); } return true; } } return false; }在动画蓝图中驱动Morph Target在角色蓝图中获取到WebSocket客户端解析出的FExpressionData数组。在角色的动画蓝图事件图表中每帧Event Tick或收到新数据时通过委托事件遍历这个数组。对于每个FExpressionData使用“设置形变目标Set Morph Target”节点。你需要将Data.Type如“smile”转换为对应的形变目标名称Morph Target Name并将Data.Intensity作为值输入。关键技巧MetaHuman的面部有数百个形变目标名称是标准化的如browsInnerUpeyeBlinkLeft。你需要事先在UE5中打开角色的骨骼网格体资产在“形变目标Morph Targets”预览面板中查看所有可用的名称并与Fay输出的表情类型做好映射。这个映射关系可以预先配置在一个数据表DataTable或Map中。5.3 语音播放与嘴唇同步集成让数字人说话时嘴唇同步动起来是沉浸感的关键。播放接收到的音频Fay后端通常会以音频流如PCM、WAV格式或Base64编码的音频数据通过WebSocket发送。在UE5中你需要编写代码将接收到的音频数据解码并填充到一个USoundWave动态资源中然后通过UAudioComponent播放。这是一个相对底层的音频操作过程。一个更简单稳定的替代方案是Fay后端将TTS生成的音频保存为临时文件如.wav并通过一个简单的HTTP服务器提供访问。UE5端则使用UMediaSoundComponent或通过FFileHelper加载音频文件后播放。虽然略有延迟但实现复杂度大大降低。配置嘴唇同步Lip Sync确保已启用“Audio Synesthesia”插件。在内容浏览器中右键选择“声音 - 嘴唇同步分析Lip Sync Analysis”。这会创建一个.lip文件的分析器。将你的角色动画蓝图中的嘴唇骨骼通常是jawmouth_leftmouth_right等与控制绑定Control Rig或直接与动画蓝图的动画图表连接。使用“嘴唇同步Lip Sync”动画节点。将该节点与播放的音频组件关联它会自动分析音频的振幅和频率输出驱动嘴唇骨骼的值。实操心得MetaHuman自带的面部控制绑定Rig对嘴唇同步有很好的支持。你可以直接使用MetaHuman动画蓝图中的“Face Controls”图表其中已经集成了基于音频的嘴唇驱动逻辑。你只需要将音频流输入进去即可。这比从头开始驱动每个嘴唇骨骼要高效和准确得多。6. 高级功能与性能优化从“能用”到“好用”基础功能跑通后我们需要关注稳定性、真实感和性能。6.1 情感化语音与表情联动单纯的嘴唇同步还不够结合情感的语音和表情才能打动人心。集成情感TTS在Fay的后端配置中选择支持情感合成SSML的TTS服务如微软Azure Neural TTS。你可以在发送给TTS的文本中嵌入情感标签例如speak version\1.0\ xmlns\http://www.w3.org/2001/10/synthesis\ xml:lang\en-US\voice name\en-US-JennyNeural\prosody rate\fast\ pitch\high\Im so excited!/prosody/voice/speak。这样生成的语音本身就带有兴奋的语调。情感参数传递Fay在调用TTS时除了文本还应生成一个代表情感类型如excited和强度如0.9的参数。这个参数需要和音频数据一起打包发送给UE5。UE5端情感映射UE5在收到情感参数后不应只驱动嘴部。它可以驱动面部表情将情感类型映射到一组更丰富的面部Morph Target组合上。例如“兴奋”可以同时增强“眉毛上扬”、“眼睛睁大”、“嘴角上扬”的强度。驱动肢体动画触发一个短暂的“兴奋”身体动画蒙太奇Montage比如身体前倾、手势变化。调整语音播放参数虽然音调已由TTS决定但UE5可以微调播放时的音量或空间化效果来配合情绪。6.2 性能优化全策略数字人系统是资源消耗大户优化至关重要。优化方向具体措施预期收益与注意事项渲染优化启用Nanite将数字人模型和主要场景静态网格体转换为Nanite。大幅降低Draw Call和三角形处理压力。注意Nanite适用于静态或刚性动画物体对于面部表情变化的部位需形变通常不适用Nanite但身体部分可以。合理使用LOD为数字人模型设置多个细节级别LOD距离远时自动切换低模。减少远处角色的渲染开销。MetaHuman导出时已自带LOD。材质优化合并材质纹理使用材质实例Material Instance而非动态材质参数频繁更新。减少状态切换和纹理采样开销。面部表情通过Morph Target驱动而非动态修改材质参数是正确做法。动画优化动画蓝图优化避免在动画蓝图的“事件图表”中进行每帧的复杂计算或蓝图节点遍历。将解析WebSocket数据等逻辑放在角色Tick或单独的Actor中。动画蓝图每帧对每个角色实例执行逻辑过重会严重拖累性能。使用动画蒙太奇将眨眼、点头等小动作制作成动画蒙太奇由逻辑触发播放而非持续混合。比在动画蓝图中持续混合某些骨骼更高效。网络优化数据压缩与频率控制对发送给UE5的JSON数据进行压缩如gzip。降低表情参数发送频率如从60Hz降至30Hz并对参数进行平滑插值。减少网络带宽占用提升连接稳定性。人眼对表情的细微高频变化不敏感30Hz足够流畅。实现心跳与断线重连WebSocket连接定期发送心跳包。检测到断开后自动尝试重连并恢复状态。保障系统长期稳定运行避免因网络波动导致数字人“僵死”。逻辑优化异步处理将Fay后端的LLM推理、TTS生成等耗时操作放在异步线程中避免阻塞主通信线程。提升系统整体响应速度避免语音卡顿。资源异步加载数字人的高精度模型、纹理等资源使用异步加载流。避免在角色出现时造成游戏卡顿。6.3 常见问题排查实录这里记录几个我踩过的坑和解决方案问题WebSocket连接成功但收不到任何数据。排查首先在Fay后端日志中确认消息是否已发送。然后在UE5端检查OnMessage回调是否被触发打印接收到的原始字符串。解决最常见的原因是JSON格式不匹配。仔细对比Fay发送的JSON结构和UE5解析代码中预期的结构。使用在线JSON格式化工具校验Fay发出的数据。确保字段名大小写完全一致。问题表情动画僵硬、不自然或抽搐。排查检查从Fay收到的表情Intensity值是否在剧烈跳变如0.3, 0.8, 0.1, 0.9。解决在UE5端对接收到的强度值进行线性插值Lerp或平滑处理。不要直接用最新值设置Morph Target而是每帧向目标值平滑过渡。这能消除因网络延迟或AI输出波动导致的动画抽搐。// 伪代码示例平滑处理 float CurrentSmileValue 0.0f; float TargetSmileValue 0.0f; // 从网络接收的目标值 float SmoothSpeed 5.0f; // 平滑速度 // 每帧Tick中 void Tick(float DeltaTime) { CurrentSmileValue FMath::FInterpTo(CurrentSmileValue, TargetSmileValue, DeltaTime, SmoothSpeed); SkeletalMeshComponent-SetMorphTarget(FName(smile), CurrentSmileValue); }问题嘴唇同步动画对不上或根本不动。排查确认音频组件是否在正常播放声音。检查嘴唇同步分析节点是否正确关联了音频组件和嘴唇骨骼。解决确保播放的音频采样率与嘴唇同步分析器预期的采样率一致通常为16000Hz或44100Hz。如果使用动态生成的USoundWave务必正确设置其采样率参数。另一个常见原因是音频播放延迟。确保从收到音频数据到开始播放的延迟尽可能小必要时对音频流进行缓冲处理以消除网络抖动。问题打包Packaging后程序无法连接到本地Fay服务。排查开发时用localhost或127.0.0.1打包后程序是一个独立的exelocalhost指向它自己。解决将连接地址改为你运行Fay后端机器的实际局域网IP地址如192.168.1.100:8080。并确保防火墙允许该端口的连接。7. 实战扩展构建一个虚拟导览员案例让我们把上述所有技术整合到一个简单场景中一个博物馆展厅里的虚拟导览员。场景搭建在UE5中创建一个简单的展厅内部场景放置一些展示品静态网格体。将你的MetaHuman角色放置其中并调整好光照使其与环境融合。交互逻辑设计触发对话玩家走到导览员附近时按“E”键或自动触发对话。输入玩家通过键盘输入文本或通过集成的语音识别模块如UE5的UWindowsSpeechRecognition插件或第三方SDK进行语音输入。流程玩家输入 - UE5客户端将文本/音频发送给Fay后端 - Fay调用LLM生成符合“导览员”身份的回复 - Fay调用TTS生成带情感的语音 - Fay将语音流和表情参数打包发送回UE5 - UE5播放语音并驱动数字人表情和口型。内容生成可以在Fay的提示词Prompt中精心设计让LLM扮演一个知识渊博、语气亲切的博物馆导览员并限制其回答与展厅展品相关。核心代码片段UE5端交互触发// 在角色蓝图或交互Actor中 void AInteractiveGuide::OnPlayerInteract() { // 1. 显示一个输入UI获取玩家文本 FString PlayerText GetPlayerInputText(); // 2. 构建发送给Fay的消息 FString JsonPayload FString::Printf(TEXT({\type\: \user_query\, \content\: \%s\}), *PlayerText); // 3. 通过WebSocket客户端发送 if (FayWebSocketClient FayWebSocketClient-IsConnected()) { FayWebSocketClient-SendMessage(JsonPayload); } else { UE_LOG(LogTemp, Warning, TEXT(WebSocket not connected!)); } }通过这个案例你将完整走通从用户输入、AI处理、到最终超写实数字人呈现的闭环。这不仅仅是技术的堆砌更是创造有温度、有灵魂的数字交互体验的开始。