IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity记一次时装骨骼换装的合并 -> 正文阅读

[游戏开发]Unity记一次时装骨骼换装的合并

换装入门

之前做过一次,好久没做了

国内团队都会做,做法也是各自精彩,只是分享的少;而国外的技术相对比较单一,但是模型细节度,丰富度都远不如国内,也很难和国内技术栈整合;所以网上一堆看上去还行的资料

(当然,我们拿到的国外素材很多都是几年前的,和国内团队当前素材进行比较并不公平,这里只是说下易用程度,国内素材+简单代码==容易使用)

重新做的时候被网上的资料坑了很多

搞了2个星期,终于搞完

记录一哈

(以下为残缺代码,非整个项目)

只记录重点,关键就是2个预制体或FBX融合的时候,bones要整合用第一个(很多网上的做法都是直接bones addList(),这种做法的基础必须是所有时装的bones是在同一个预制体,同一个fbx内部的,其实无需要自我限制,骨骼绑定,mesh合并,添加材质等等都是可以很“松耦合”的)

第二个重点,就是选择采用单一mesh合并(skinnedmeshrenderer相当黑盒啊),否则多个mesh,多个材质也是一种办法,相互转化,但Unity官方的东西就是。。好像能 这么用,又好像能那么用。。就是不告诉你怎么用。。。。(不公开透明的API)还真实很多坑的,

烧菜坑思路就是“怎么简单怎么来”

其他重点,就是boneposes和matrix4x4的转换了

    for (int i = 0; i < length; i++)
        {
            if(i==0) continue;//个人模型问题,这个判断可以不要,(个人第二个模型才是人体主模型)
            SkinnedMeshRenderer oneRender = combineRenders[i];
            // 记录骨骼
            //bones.AddRange(oneRender.bones);
            //(两个预制体合并,所以需要合并骨骼,不能用自己的骨骼)
            var bonesInRoot = combinedRoot.GetComponentsInChildren<Transform>();
            List<Transform> findBones = new List<Transform>();
            foreach (var b in oneRender.bones)
            {
                bool did = false;
                foreach (var t in bonesInRoot)
                {
                    if (t.name == b.name)
                    {
                        findBones.Add(t);
                        did = true;
                    }
                    
                }   
                if(did==false)
                    findBones.Add(b);
            }
            bones.AddRange(findBones);
            
            // 记录权重
            BoneWeight[] meshBoneweight = oneRender.sharedMesh.boneWeights;
            for (int j = 0; j < meshBoneweight.Length; ++j)
            {
                BoneWeight bw = meshBoneweight[j];
                BoneWeight bWeight = bw;
                bWeight.boneIndex0 += boneOffset;
                bWeight.boneIndex1 += boneOffset;
                bWeight.boneIndex2 += boneOffset;
                bWeight.boneIndex3 += boneOffset;
                boneWeights.Add(bWeight);
            }
            // offset是为了合并之后BoneWeight.boneIndex还能正确定向骨骼
            boneOffset += oneRender.bones.Length;
            // 记录网格相关信息
            CombineInstance combineInstance = new CombineInstance();
            Mesh mesh = new Mesh();
            oneRender.BakeMesh(mesh);
            mesh.uv = oneRender.sharedMesh.uv;
            combineInstance.mesh = mesh;
            //combineInstance.transform = oneRender.localToWorldMatrix;//有个天坑是 oneRender.localToWorldMatrix 和 oneRender.transform.localToWorldMatrix 是两回事
            //Matrix4x4 matrix = oneRender.transform.worldToLocalMatrix;
//            combineInstance.transform = oneRender.transform.localToWorldMatrix ;
            combineInstance.transform =
                oneRender.transform.localToWorldMatrix * Matrix4x4_Rotation( EnemyManager_Axle.X, -90);
            //combineInstance.subMeshIndex = i-1;//个人模型问题,这个判断可以不要,(个人第二个模型才是人体主模型),也不可以这么分,骨骼会错乱(个人采用了合并单一Mesh方法)
            combineInstances.Add(combineInstance);
           // oneRender.gameObject.SetActive(false);//网上抄的方法,完全不知道为什么要这么用
        }

    // 将所有的骨骼变换矩阵从自身转换到当前预制件下
        List<Matrix4x4> bindposes = new List<Matrix4x4>();
        int boneLength = bones.Count;
        for (int i = 0; i < boneLength; i++)
        {
            bindposes.Add(bones[i].worldToLocalMatrix * combineMatrix);
        }

        Mesh combinedMesh = new Mesh();
        combinedMesh.CombineMeshes(combineInstances.ToArray(), true, true);
        combinedSkinnedRenderer.sharedMesh = combinedMesh;
        combinedSkinnedRenderer.bones = bones.ToArray();
        combinedSkinnedRenderer.sharedMesh.boneWeights = boneWeights.ToArray();
        combinedSkinnedRenderer.sharedMesh.bindposes = bindposes.ToArray();
        combinedSkinnedRenderer.sharedMesh.RecalculateBounds();
        combinedSkinnedRenderer.material = combineMaterial;
  /// <summary>
    /// 一个简单的旋转,其他Matrix4x4变换可看:https://blog.csdn.net/aaa583004321/article/details/81948780
    /// </summary>
    /// <param name="transform"></param>
    /// <param name="axle"></param>
    /// <param name="angle"></param>
    public static Matrix4x4 Matrix4x4_Rotation(EnemyManager_Axle axle, float angle)
    {
        Matrix4x4 matrix = Matrix4x4.identity;

        if (axle == EnemyManager_Axle.X)
        {
            matrix.m11 = Mathf.Cos(angle * Mathf.Deg2Rad);
            matrix.m12 = -Mathf.Sin(angle * Mathf.Deg2Rad);
            matrix.m21 = Mathf.Sin(angle * Mathf.Deg2Rad);
            matrix.m22 = Mathf.Cos(angle * Mathf.Deg2Rad);

        }
        else if (axle == EnemyManager_Axle.Y)
        {
            matrix.m00 = Mathf.Cos(angle * Mathf.Deg2Rad);
            matrix.m02 = Mathf.Sin(angle * Mathf.Deg2Rad);
            matrix.m20 = -Mathf.Sin(angle * Mathf.Deg2Rad);
            matrix.m22 = Mathf.Cos(angle * Mathf.Deg2Rad);
        }
        else
        {
            matrix.m00 = Mathf.Cos(angle * Mathf.Deg2Rad);
            matrix.m01 = -Mathf.Sin(angle * Mathf.Deg2Rad);
            matrix.m10 = Mathf.Sin(angle * Mathf.Deg2Rad);
            matrix.m11 = Mathf.Cos(angle * Mathf.Deg2Rad);
        }

        return matrix;
    }

    public  enum EnemyManager_Axle
    {
        X,
        Y,
        Z
    }

参考:

技巧| Unity中Avatar换装实现 - UWA Blog (uwa4d.com)

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章           查看所有文章
加:2021-08-11 12:46:26  更:2021-08-11 12:47:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/1 8:55:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码