您的位置:首页 > 移动开发 > Unity3D

【Unity3D】3D角色换装++ Advance

2015-03-12 22:07 260 查看
  1、如果角色只是单纯的更换装备
也就是说 角色的整个身体是一个完整的网格 而所需要更换的各个部件只是装备 而不是身体的某一部分 比如NGUI中Character的例子 穿装备之前 角色只有默认的身体 穿了装备以后 身体不变 只是在特

  

  定的位置显示装备 如下图

  

  穿装备以前穿装备以后

  



  



  这样做的好处是实现起来很简单
就是在特定的骨骼下显示一个不含有蒙皮信息的装备模型

  更换的时候去通知特定功能的代码去删掉或隐藏之前的
再显示新的即可

  不好的地方是
1 实现不了身体部件的更换 当然这不一定是不足 要视游戏的设计本身而论

  

  

  2 穿上装备 实际上就是多增加了一份模型 那么所需要渲染的面数会增加 drawcall也会增加

  如果游戏中模型的面数以及drawcall控制的很好
并且不存在除角色以外的其他玩家换装的话 并且游戏本身设计时也不需要身体部件更换的话

  

  那这样做应该会是个值得考虑的方案

  2、大部分网络游戏都会选择将身体的各个部件拆开
各个部件由身体部分和装备部分共同组成一个完整的模型 因此更换部件其实也就是更换装备

  unity实现就如同上文中所讲
代码可参考官方CharacterCustomization例子

  在游戏中
关心的不仅是装备有没有更换 更关心更换的好不好 会不会留有隐患

  官方的这个例子只是演示了换装的原理
但是打开profile的memory一栏 会看到在更换装备的时候 内存占用在不断的增加

  这样无厘头的内存占用会带来严重的后果
尤其是网络游戏这种换装频率高的游戏方式 尤其对于移动平台的网络游戏 尤其对于移动平台的3d网络游戏

  优化问题牵扯到内存优化
资源优化 渲染优化 代码优化等多方面 待后文中再逐一讨论

  官方换装中的内存问题
是因为装备被替换掉以后 没有从内存中清除 不断的更换就会在内存中不断的累加

  相关问题在unity圣殿中有文章详细解释

  

  装备中除武器以外
其他的部分都可以用同一种方式去更换 当然武器也可以 同样要视游戏本身而论

  如果游戏中在安全区需要武器背在背上
而在非安全区拿在手上 同时有角色的"亮出武器"这样的过度动作配合 那么一个角色身上装备两把武器绝对是不二之选一把在手上 一把在背上 控制其中之一显示即可那么在更换武器的时候则需要将这两把武器全部更新

  如果只是一把武器
在不同的状态挂在不同的位置的话 那么unity实现中一个很好的办法就是单纯的把武器模型放到相应的骨骼下 成为该骨骼的sub node

  身体各部件都需要能够支持动态的更换
按照官方的例子 实际上更换每一个部件 就等同于重新合并了一遍网格 只是这次合并是用新装备的模型和其他部件的模型

  当然如果选择不合并网格
那么也就是说 每个装备的部件都有一个SkinnedMeshRenderer组件来与骨骼进行关联 等同于计算量会翻倍

  合并网格的换装代码参考官方实例
不合并网格的换装核心代码如下 即从当前角色的骨骼中取到该模型所关联的骨骼 然后建立关联即可

  

  1 public void Generate(GameObject root, int elemId)

  2 {

  3 if (root == null)

  4 return;

  5

  6 // Return if current map doesnt contain this element

  7 if (!elementDict.ContainsKey(elemId) || elementDict[elemId]

  == null) return;

  8

  9 // Get element's SkinnedMeshRenderer component

  10 SkinnedMeshRenderer elemSmr = elementDict[elemId].GetSkinnedMeshRenderer();

  11 // To be sub-object

  12 elemSmr.gameObject.transform.parent = root.transform;

  13 // All bones in this root

  14 Transform[]

  bones = root.GetComponentsInChildrenTransform();

  15 // All bones needed by element

  16 ListTransform elemBones = new ListTransform();

  17 // All bone name in this element

  18 string[]

  elemBoneNames = elementDict[elemId].GetBoneNames();

  19

  20 // Find matched bones in root

  21 for (int i = 0; i elemBoneNames.Length; ++i)

  22 {

  23 for (int j = 0; j bones.Length; ++j)

  24 {

  25 if (string.Compare(bones[j].name, strBone) == 0)

  26 {

  27 elemBones.Add(bones[j]);

  28 break;

  29 }

  30 }

  31 }

  32 elemSmr.bones = elemBones.ToArray();

  33 elemSmr.updateWhenOffscreen = false;

  

  

  

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: