unity 动态对象优化

2015年03月22日 15:05 0 点赞 0 评论 更新于 2017-04-28 11:09

在 Unity 开发中,Unity 自身会对 Draw Calls 进行一定程度的优化,但对于动态对象,Unity 并未提供专门的处理机制。这就需要开发者自行实现动态对象的优化。其实现原理是:遍历每个对象的 SkinnedMeshRenderer,将所有动态对象组合成一个大的对象,并将骨骼动画赋值给该对象,从而实现动态对象的优化。

以下是实现该优化的 C# 代码:

public static void CombineToMesh(GameObject _go)
{
// 获取所有子对象的 SkinnedMeshRenderer 组件
SkinnedMeshRenderer[] _smr = _go.GetComponentsInChildren<SkinnedMeshRenderer>();
// 用于存储要合并的网格实例
List<CombineInstance> lcom = new List<CombineInstance>();
// 用于存储材质
List<Material> lmat = new List<Material>();
// 用于存储骨骼变换
List<Transform> ltra = new List<Transform>();

// 遍历所有的 SkinnedMeshRenderer 组件
for (int i = 0; i < _smr.Length; i++)
{
// 将当前 SkinnedMeshRenderer 的材质添加到材质列表中
lmat.AddRange(_smr[i].materials);
// 将当前 SkinnedMeshRenderer 的骨骼添加到骨骼列表中
ltra.AddRange(_smr[i].bones);

// 遍历当前 SkinnedMeshRenderer 的每个子网格
for (int sub = 0; sub < _smr[i].sharedMesh.subMeshCount; sub++)
{
CombineInstance ci = new CombineInstance();
// 设置要合并的网格
ci.mesh = _smr[i].sharedMesh;
// 设置子网格索引
ci.subMeshIndex = sub;
// 将合并实例添加到列表中
lcom.Add(ci);
}

// 销毁当前的 SkinnedMeshRenderer 所在的游戏对象
Destroy(_smr[i].gameObject);
}

// 获取游戏对象的 SkinnedMeshRenderer 组件
SkinnedMeshRenderer _r = _go.GetComponent<SkinnedMeshRenderer>();
// 如果没有 SkinnedMeshRenderer 组件,则添加一个
if (_r == null)
_r = _go.AddComponent<SkinnedMeshRenderer>();

// 创建一个新的网格
_r.sharedMesh = new Mesh();
// 设置骨骼
_r.bones = ltra.ToArray();
// 设置材质
_r.materials = new Material[] { lmat[0] };
// 设置根骨骼
_r.rootBone = _go.transform;

// 合并所有的网格实例
_r.sharedMesh.CombineMeshes(lcom.ToArray(), true, false);
}

这段代码定义了一个静态方法 CombineToMesh,它接受一个 GameObject 类型的参数 _go。方法内部通过一系列操作,将 _go 及其子对象中的所有 SkinnedMeshRenderer 组件对应的网格合并成一个大的网格,并将其赋值给 _goSkinnedMeshRenderer 组件,同时处理了材质和骨骼信息。这样可以有效减少 Draw Calls,提高动态对象的渲染性能。

作者信息

feifeila

feifeila

共发布了 570 篇文章