基于共享骨骼简单高效的换装方案

原文地址 blog.csdn.net

游戏的换装, 一般分为 3 种. 换材质, 骨骼挂接, 共享骨骼. 用的比较多的是骨骼挂接和共享骨骼.

1. 骨骼挂接

没有动作的骨骼挂接, 适合武器.

有动作的骨骼挂接, 适合坐骑.

2. 共享骨骼

共享骨骼, 适合身体部件. 主模型 (身体) 包含整个骨骼, 部件模型只包含自己部分的骨骼, 应用的时候, 部件模型的骨骼共享主模型的骨骼. 这样的话, 只需要播放主模型的动画, 部件会跟着动.

Unity 的换装呢, 你要百度一下, 能搜出一堆文章, 方法也是多种多样. 有参考价值的却不多.

比如主流推荐的官方 demo 提供的换装方式. 合并 mesh, 多此一举又麻烦.

比如 avatar 的方式 ... 不适合 Legacy 动画

其实用以前端游的方式, 共享骨骼就行了, Ogre 引擎直接提供函数 OGRE::shareSkeletonInstanceWith() 来实现. 而 Unity 引擎没有这个函数, 怎么办呢, 自己写一个呗. 命名我也取一样的, 表示对 Unity 自己不封装这个函数的鄙视.

// 共享骨骼
        public static void ShareSkeletonInstanceWith(SkinnedMeshRenderer selfSkin, GameObject target)
        {
            Transform[] newBones = new Transform[selfSkin.bones.Length];
            for (int i = 0; i < selfSkin.bones.GetLength(0); ++i)
            {
                GameObject bone = selfSkin.bones[i].gameObject;
                // 目标的SkinnedMeshRenderer.bones保存的只是目标mesh相关的骨骼,要获得目标全部骨骼,可以通过查找的方式.
                newBones[i] = FindChildRecursion(target.transform, bone.name);
            }
            selfSkin.bones = newBones;   
        }
 
        // 递归查找
        public static Transform FindChildRecursion(Transform t, string name)
        {
            foreach (Transform child in t)
            {
                if (child.name == name)
                {
                    return child;
                }
                else
                {
                    Transform ret = FindChildRecursion(child, name);
                    if (ret != null)
                        return ret;
                }
            }
            return null;
        }

代码很简单, 原理我再结合 Unity 仔细分析下.

第一步 :

假设整个模型分两部分, 身体和翅膀, 身体作为主模型, 翅膀作为部件模型, 身体 30 根骨骼, 翅膀 6 根骨骼, 总数量 36 根骨骼.

  1. 导出身体模型的时候, 选中身体和整个骨骼 (注意是整个骨骼), 这样身体也包含了翅膀的骨骼.

  2. 导出翅膀模型的时候, 选中翅膀和翅膀骨骼 (翅膀不用导整个骨骼).

第二步:

模型有哪些骨骼, 可以放入 Unity 查看 root 下面的节点 , 这里有个注意的地方, 通过 SkinnedMeshRenderer.bones 查看的骨骼数量总是比通过 root 节点查看的数个数量少, 因为 SkinnedMeshRenderer.bones 保存的模型真正用到的骨骼, 而不是整个骨骼, 比如身体模型的 SkinnedMeshRenderer.bones 只有 30, 而不是 36.

第三步:

平级挂接 2 个模型到同一个父节点下测试, 播放身体模型的动画, 身体会动, 翅膀不会, 很正常, 因为动的是身体模型的骨骼, 翅膀模型的骨骼根本就没动. 接下来把翅膀模型的 6 个骨骼设置成身体模型对应的那 6 个骨骼的 transform, 再播放, 就发现翅膀也跟着动了, 所谓共享, 就是对应的把自己的骨骼设置成目标的骨骼.

函数调用很简单 ShareSkeletonInstanceWith(翅膀, 身体)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 最近都比较忙,没时间写,今晚利用空余时间分享一下游戏开发中常用的“换装”给大家,如果大家有什么好的插件或想法,记得...
    光明程辉阅读 10,799评论 1 7
  • 前言   学了Unity后,总是感觉缺少资源,包括人物、物品模型、动作数据、贴图、特效,各种插件,还被骗去学了几天...
    crossous阅读 17,797评论 1 11
  • 换装的核心思想:更换对象SkinnerMeshRenderer组件中骨骼(Bones),网格(sharedMesh...
    逍遥仔阅读 7,659评论 0 3
  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    余生动听阅读 13,608评论 0 11
  • 彩排完,天已黑
    刘凯书法阅读 9,807评论 1 3

友情链接更多精彩内容