Unity裏的人物驅動/換裝備/換武器/換衣服/動畫重定位dom
剛學的過程被這個問題困擾最多。ide
首先,基本的,你們都知道驅動人物須要骨架、綁骨的Mesh和動畫(這三個要是不知道的話就得考慮看看計算機圖形學先)動畫
而後,基本上有點maya(或其餘)功底的都知道,在maya裏,骨架、mesh和動畫都是一種單獨的存在,誰混一塊兒誰鬱悶。spa
在unity裏面,狀況也是如此,不過再複雜一點展開。調試
一、骨架就是transform。不像maya和理論那樣,是一種實體的單獨的存在。在unity裏,骨架就是transform的層次關係。一個骨頭就是一個transform。這我的體的骨架(Transform)組織結構通常是abdome(spine,LeftUpLeg,RightUpLeg),abdome是根(有時用hip),向上是spine(neck,LeftUpArm,RightUpArm)。這個在哪裏都差很少。關鍵是root,就是abdome。在unity裏,引用骨架都是靠它。orm
二、Mesh。由於Unity裏的Mesh有綁骨和未綁骨兩種(在哪裏都差很少)。在導入資源的時候,unity會爲綁骨的Mesh自動生成一個SkinnedMeshRenderer,爲未綁骨的生成一個MeshFilter和一個MeshRenderer。不精細的人物,頭盔、手、武器(甚至靴子)等都不用綁骨,像騎馬與砍殺,只須要把armor綁骨就好。ip
不綁骨狀況:MeshFilter負責從文件中取出真實的Mesh(這裏用的是Script裏的類來表示,具體能夠查reference)。MeshRender負責顯示。這種想要固定在人體上,其實很簡單,把這個GameObject的tansform的parent設置爲須要綁定的骨頭的transform就好。(好比武器,transform.parent=item_l,item_l是左手一個綁定武器骨頭)因此,缺點也很明顯,一個mesh只能綁定到一個骨頭,也就是這個mesh不會變形。(這個能夠做爲綁骨和不綁骨的依據,看Mesh是否須要變形,因此頭盔,武器都不須要綁骨(僅在unity中成立))資源
綁骨狀況:SkinnedMeshRenderer有倆個重要成員,一個是Mesh,一個是Bones。固然,Mesh裏有每個頂點的綁骨數據,但這裏存的是序號。就是第幾個骨頭,並無指明是哪一個骨頭,可是若是給一個根骨頭就能推測出全部的骨頭了。這裏的Bones把全部的骨頭都列出來了,至於順序,有點扯淡,沒啥規律(調試結果)。問題出來了,那SkinnedMeshRenderer裏的骨頭這麼沒順序,Mesh裏的骨頭序號怎麼對應過來呢?好吧,仔細想一想,其實沒那麼複雜。由於SkinnedMeshRenderer裏包含Mesh和Bones兩個成員,因爲都是一塊兒生成的,那麼就一個坑埋一我的,正好就對應起來了。之因此要這麼個Bones列表,是由於要把它畫成transform樹吧。it
這樣就再回答一個問題,如何換裝備?原SkinnedMeshRender對應的骨骼已經存在,不可能銷燬它(還有其餘部分要用),因此就修改SkinnedMeshRenderer自己就好。要改的有兩個值(加上材質三個):Mesh和Bones。其實,原Bones根本不用變,只須要把Mesh變了就好(除非你的綁骨不是一幫人作的)。詳細代碼看看Unity有個官方項目。另外,我以爲吧,連SkinnedMeshRender都不用操縱,直接從新生成就好。看文章最後的代碼。io
動畫部分最有愛。其實呢,layer這個玩意,用來分組比較合適。優先級這個特色也是能夠用的,不過寄太大信心。一個layer能夠設置一樣的疊加方式(累加,混合),控制方式(只控制上半身)。通常不一樣動畫都放在不一樣層,相同功能動畫在同一層,好比向左砍人和向右砍人。另外,咱們動畫通常都是本身搞到的一個一個片斷,若是你不是動畫師,仍是不要用啥累加和混合了。用一些獨立的動畫,讓他控制身體的某些部位就好。
因此,綜合看,人物控制,在unity 裏,換裝備,換武器都是可行的。不知道咋了,網上就是搜不到如何換裝的,搞到我本身研究了很久。。。
另外,最近的新發現,升級到4後,有個mecanima模塊,用來作動畫重定位的,這個叫帥啊。個人如下代碼沒辦法處理動畫,由於動畫以前沒法重定位。可是可愛的unity的新功能來了,給每一個armor和每一個動畫都建立一個對應的avatar,而後就直接能夠用一套動畫驅動全部人了(雖然表面上咱們顯示的是一我的,可是在內部,實現這種換裝方法用的是好幾個獨立的人體骨骼,固然,這種方法要求每一個獨立的骨骼都是相同的)。
附上換裝代碼。
#pragma strictpublic var O_body_r:GameObject;public var O_hand_L_r:GameObject;public var O_hand_R_r:GameObject;public var O_helmet_r:GameObject;public var O_calf_L_r:GameObject;public var O_calf_R_r:GameObject;public var O_weapon_R_r:GameObject;public var body1_r:GameObject;private var mBody:GameObject;private var mHand_L:GameObject;private var mHand_L_P:Transform;private var mHand_R:GameObject;private var mHand_R_P:Transform;private var mHelmet:GameObject;private var mHelmet_P:Transform;private var mCalf_L:GameObject;private var mCalf_L_P:Transform;private var mCalf_R:GameObject;private var mCalf_R_P:Transform;private var mWeapon_R:GameObject;private var mWeapon_R_P:Transform;function Start () {}private var ifIs:boolean=true;function Update () { if(Input.GetButtonDown("Fire1")){Generate(ifIs);ifIs=!ifIs;}}function Generate(num:boolean){if(mBody){Destroy(mBody);}if(num==true){mBody=Instantiate(O_body_r,transform.position,Quaternion.identity);}else{mBody=Instantiate(body1_r,transform.position,Quaternion.identity);}mHand_L_P=mBody.transform.Find("abdomen/spine/thorax/shoulder.L/upperarm.L/forearm.L/hand.L");mHand_L=Instantiate(O_hand_L_r,mHand_L_P.position,Quaternion.identity);mHand_L.transform.parent=mHand_L_P;mHand_L.transform.localRotation=Quaternion.Euler(0,270,90);mHand_R_P=mBody.transform.Find("abdomen/spine/thorax/shoulder.R/upperarm.R/forearm.R/hand.R");mHand_R=Instantiate(O_hand_R_r,mHand_R_P.position,Quaternion.identity);mHand_R.transform.parent=mHand_R_P;mHand_R.transform.localRotation=Quaternion.Euler(0,270,90);mWeapon_R_P=mBody.transform.Find("abdomen/spine/thorax/shoulder.R/upperarm.R/forearm.R/hand.R/item.R");mWeapon_R=Instantiate(O_weapon_R_r,mWeapon_R_P.position,Quaternion.identity);mWeapon_R.transform.parent=mWeapon_R_P;mWeapon_R.transform.localRotation=Quaternion.Euler(0,270,90);mCalf_L_P=mBody.transform.Find("abdomen/thigh.L/calf.L");mCalf_L=Instantiate(O_calf_L_r,mCalf_L_P.position,Quaternion.identity);mCalf_L.transform.parent=mCalf_L_P;mCalf_L.transform.localRotation=Quaternion.Euler(0,270,90);mCalf_R_P=mBody.transform.Find("abdomen/thigh.R/calf.R");mCalf_R=Instantiate(O_calf_R_r,mCalf_R_P.position,Quaternion.identity);mCalf_R.transform.parent=mCalf_R_P;mCalf_R.transform.localRotation=Quaternion.Euler(0,270,90);mHelmet_P=mBody.transform.Find("abdomen/spine/thorax/head");mHelmet=Instantiate(O_helmet_r,mHelmet_P.position,Quaternion.identity);mHelmet.transform.parent=mHelmet_P;mHelmet.transform.localRotation=Quaternion.Euler(0,270,90);}