Unity中使用Alembic Exporter导出时动态网格冻结问题求助
Unity代码驱动Mesh导出Alembic冻结问题解决方案
问题根源
Unity Alembic Exporter默认仅捕获静态Mesh数据或通过Animator/AnimationClip驱动的动画。直接在Update中修改Mesh顶点时,若未正确标记Mesh为动态、未更新Mesh边界,或导出器设置为仅抓取初始状态,导出器会无法追踪后续的Mesh修改,导致录制时网格冻结在初始帧。
解决方案
1. 修改CustomMesh脚本,确保Mesh动态更新被追踪
在Start中标记Mesh为动态,同时优化UpdateMesh方法,避免重置整个Mesh,确保导出器能感知顶点变化:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CustomMesh : MonoBehaviour { private Mesh mesh; private Vector3[] vertices; private int[] triangles; void Start() { mesh = new Mesh(); GetComponent<MeshFilter>().mesh = mesh; mesh.MarkDynamic(); // 关键:标记Mesh为动态,告知Unity会频繁更新 CreateShape(); UpdateMesh(); } void CreateShape() { vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0), new Vector3(1, 0, 0) }; triangles = new int[] { 0, 1, 2, 0, 2, 3 }; // 只在初始化时赋值三角形,后续拓扑不变无需重复设置 mesh.triangles = triangles; } void UpdateMesh() { // 无需Clear,直接更新顶点 mesh.SetVertices(vertices); // 比直接赋值更高效,适合动态更新 mesh.RecalculateNormals(); mesh.RecalculateBounds(); // 必须更新边界,确保导出器捕捉到变化 } void Update() { vertices[0] = new Vector3(Mathf.Sin(Time.time), 0, 0); UpdateMesh(); } }
2. 调整Alembic Exporter组件设置
在Inspector面板中修改AlembicExporter的参数:
- Capture Type:选择
GameObject(单个对象)或Hierarchy(多个对象) - Capture Mesh:设置为
Every Frame(默认是Once,仅抓取初始状态) - Dynamic Objects:勾选该选项,确保动态修改的对象被正确录制
- Topology:保持
Static(你的动画仅顶点移动,拓扑未变化)
3. 修正自定义导出脚本的帧同步逻辑
原脚本的等待逻辑会导致帧不同步,改用Time.captureFramerate强制Unity以目标帧率运行,确保导出帧与Mesh更新完全同步:
using System.Collections; using UnityEngine; using UnityEngine.Formats.Alembic.Exporter; public class AlembicCustomExporter : MonoBehaviour { public AlembicExporter alembicExporter; public float exportDuration = 5f; public float frameRate = 30f; private bool isExporting = false; void Start() { StartCoroutine(CaptureAnimation()); } IEnumerator CaptureAnimation() { isExporting = true; // 保存原帧率,导出后恢复 int originalCaptureFramerate = Time.captureFramerate; Time.captureFramerate = (int)frameRate; // 强制Unity以目标帧率运行 float startTime = Time.realtimeSinceStartup; alembicExporter.BeginRecording(); // 按实际运行时间控制导出时长 while (Time.realtimeSinceStartup - startTime < exportDuration) { yield return new WaitForEndOfFrame(); Debug.Log($"已捕获帧:{Time.frameCount},时间:{Time.time}s"); } alembicExporter.EndRecording(); Time.captureFramerate = originalCaptureFramerate; isExporting = false; Debug.Log("Alembic导出完成"); } }
内容的提问来源于stack exchange,提问作者Rolf
相关产品推荐
相关产品推荐

