|
unity的新動畫系統(tǒng)叫Mecanim,使用Animator來取代舊系統(tǒng)Animation,按Unity文檔的慣例:知識點主要分2部分:unity manual和unity script,讀者可以邊看文章邊查閱文檔,最好能動手測試。 文章的開始之前,先講幾個基本的知識的: 1.創(chuàng)建動畫的一個基本步驟是設(shè)置一個unity3d可理解的簡化后的骨骼到骨架中實際骨骼的映射;在Mecanim的術(shù)語中,這個映射稱為Avatar,即avatar是骨骼到骨架的映射。 Avatar主要用于類人骨骼模型,可以實現(xiàn)角色之間的Retargeting。非類人模型可以認(rèn)為骨架就是骨骼。 2.構(gòu)建模型的基本步驟: modelling->rigging->skinning(建模->構(gòu)建骨架->蒙皮) 1.modelling 建模: 1.Observe a sensible topology(遵循合理的拓撲結(jié)構(gòu)),一個合理的標(biāo)準(zhǔn)是動畫帶動的網(wǎng)格變形是漂亮的; 2.注意網(wǎng)格的縮放比例。最好做一下各個建模軟件模型的導(dǎo)入測試,來設(shè)置好正確的縮放比例(不同建模軟件導(dǎo)入比例不一樣) 3.安放角色使得角色的腳站在坐標(biāo)原點或者模型的“錨點”。角色通常是豎直地走在地面上,如果角色的錨點(也就是他的變換中心)在地面上會更容易控制。 4.如果是類人模型,則盡量使用T字姿態(tài)建模(Unity為類人模型提供了許多功能和優(yōu)化) 5.整理你的模型,去掉垃圾。只要可能的話,覆蓋孔洞,焊接頂點并且移除隱藏的面,這會對蒙皮有幫助,特別是自動蒙皮過程。 2.Rigging 搭骨架:創(chuàng)建骨架上的關(guān)節(jié)來控制你的模型進行運動。 非類人模型的話,可以認(rèn)為沒有骨架,只有骨骼,骨骼直接控制動畫,類人模型是骨架控制動畫。步驟1中的模型已經(jīng)有腳,手,頭,武器等骨骼,還有受擊骨骼等,這些可以用來控制模型或者懸掛額外物件。 3.Skinning 蒙皮:給骨架附加網(wǎng)格。 1.把網(wǎng)格中的頂點綁定到骨骼,包括硬綁定(一個頂點指定一個骨骼,不是一一對應(yīng),可能多個頂點指定的是一個骨骼)和軟綁定(一個頂點指定多個骨骼,每個骨骼有一定權(quán)重) 3.動畫文件導(dǎo)入unity后,我們對它的處理和設(shè)置,這些在Inspector面板:Animation Importing settings 分3個頁簽: Model:這里的參數(shù)基本由美術(shù)來定,其他的使用默認(rèn)就好了,這里只提4個參數(shù): 1.scale factor 模型縮放比例,不同建模軟件導(dǎo)入比例不一樣,unity的物理單位是1m,這個根據(jù)不同建模軟件設(shè)置 2.readable/writeable和UITexture一樣,如果開了unity就必須拷一份到內(nèi)存,盡量不開。 Rig:這里Animation Type包括(Generic/Humanoid/Legacy/None) Generic 用于非類人模型;Humanoid用于類人模型 Avatar Definition:可以使用現(xiàn)有的avatar,也可以create from this model,一般地,模型網(wǎng)格文件選create,這個時候,Avatar子資產(chǎn)被增加到模型資產(chǎn)的下面,即Avatar是unity根據(jù)網(wǎng)格文件生成的,對Humanoid類型,還會自動匹配骨骼到骨架,不符合會報錯;而動畫文件使用copy,使用已有資源。 Animations:對一個Animation Clip動畫片段進行設(shè)置 前面部分的設(shè)置這里就不講了,下面的clip片段我們看到Start和End參數(shù),這表示從一個fbx動畫中截取一段給clip使用,多個clip共用一個動畫資源,所以,可以一個模型的所有動作都搞到一個動畫文件中,各個動作去里面取一段即可;也可以一個模型每個動作都有一個動畫文件,分開管理。 中間的參數(shù)比較煩躁,略過,先提一下Animations頁簽最下面的幾個有意思的參數(shù):curves,events,mask,這2個簡單的參數(shù)可以帶來許多有趣的功能,在后面會講到。 講完上面幾個基本知識點后,下面我們來分點看幾個有趣的應(yīng)用: 1.AnimationEvent Unity manual部分: 這個在animations頁簽的下面,可以給clip加幀事件,即播到某幀時觸發(fā)某個事件: 1.給clip的某些幀上加event,這個Function就是事件的名字,其他的是這個函數(shù)的參數(shù) 2.定義一個腳本來接受這個事件,比如這個圖需要定義一個腳本,并且腳本里定義了void ani(xxx){}函數(shù) 3.參數(shù)的處理:根據(jù)腳本的函數(shù)定義格式傳參數(shù),比如void ani(int a),則傳Int那個參數(shù),ani(Object a)則傳Object那個參數(shù),ani(float a, string b)則傳Float和String這2個參數(shù),而,ani(AnimationnEvent a)則傳整個event進去(包括所有參數(shù)和當(dāng)前event對應(yīng)的clip的信息) ps:添加了event的clip的animator物體必須掛上定義了該事件名Function的函數(shù)的腳本,否則會報錯 Unity Script部分:可查看class AnimationEvent,主要是獲得該event所在clip的一些信息:與此event相關(guān)的stateinfo,clipinfo,和該event本身的信息:event調(diào)用的函數(shù)名functionName、函數(shù)調(diào)用的參數(shù):float/int/string/Object(采用哪個看函數(shù)定義式)、time(事件的觸發(fā)時間) 實際應(yīng)用:這個event機制可以在播到某些幀執(zhí)行一些事件。那么我們可以,在某個點播某個特效,在某個點播某個聲音,在某個點進行一些畫面特效,在某個點進行對敵人“擊退”“擊飛”“擊浮空”,非常有利于實現(xiàn)各種節(jié)奏效果!還可以加入技能打斷機制:當(dāng)播到某2個幀之間可以被打斷:比如我遠撲某個玩家,結(jié)果我在空中被打斷,我就被彈回來。這種效果一定很爽吧。讀者可以在一個專門的腳本中定義各種接受事件的函數(shù),并進行相應(yīng)處理來進行使用此event機制。 2.AnimationCurve: Unity manual部分: 添加curve,這個curve和event有點像但又不同,event是幾幀,curves 則是每幀,curves可以配合OnAnimatorMove使用,比如每幀不同速度前進: void OnAnimatorMove() { Animator animator = GetComponent<Animator>(); Vector3 newPosition = transform.position; newPosition.z += animator.GetFloat("Runspeed") * Time.deltaTime; //RunSpeed是Curves的曲線變量,控制移動, transform.position = newPosition; //由此類似方法可以讓角色一個動畫各種移動。 } 官方文檔給出一個例子是: 比如人在冰冷環(huán)境呼吸時,呼氣的水霧由粒子系統(tǒng)控制,那么就可以在播呼吸動畫或者站立動畫時,通過Animator.Get參數(shù)(一個Curve的name)獲得當(dāng)前數(shù)值,控制水霧大小。 Unity Script部分: 屬性:keys(關(guān)鍵幀key集合),length(the num of keys),postWrapMode(最后一幀循環(huán)類型),preWrapMode(第一幀循環(huán)類型),this[int]獲取關(guān)鍵幀 接口:Evaluate(time):計算某個time時曲線的value 總結(jié):curves感覺就是:邊播動畫邊干點其他事情,event則像播到一些幀就干點事情。2者配合使用能讓你的動畫系統(tǒng)變得豐富起來,好好使用這兩個小小的利器吧。 3.Animation Layers和遮罩 實現(xiàn):邊走邊吃蘋果 1.給吃蘋果動畫加遮罩:在animation tab中的Mask中加遮罩,只勾選吃蘋果的那部分骨骼,3種情況添加: A.加現(xiàn)有的遮罩文件,可以通過Assets->Create->Avatar Mast創(chuàng)建一個遮罩 2.創(chuàng)建新Layer:EatApple Layer, 把第1步的遮罩拖到這里的Mask參數(shù)中,設(shè)置該layer設(shè)置比走路動畫Layer高,并設(shè)置該Layer的Blending為override,這樣,播走路動畫和播吃蘋果動畫就可以同時進行并且播蘋果動畫override了走路動畫的上半身動畫。 4.Animator Override Controller: 顧名思義,它就是Override “Animator Controller”的,先簡單說一下Animations Controller: Animation Controller可以認(rèn)為它就是動畫狀態(tài)機, Animator動畫系統(tǒng)是通過Animator Controller來控制動畫播放的,里面存著指向各個動畫片段Animation Clip的引用,和播放動畫的邏輯,比如狀態(tài)轉(zhuǎn)移等. 而Animator Override Controller則用于拓展一個已存在的Animtor Controller,它只是在后者基礎(chǔ)上在某些狀態(tài)播新的動畫Clip而已,保持后者的狀態(tài)機邏輯,結(jié)構(gòu)等等:retaining the original’s structure, parameters and logic. 所以在應(yīng)用方面,Animator Override Controller能做到一個狀態(tài)機(Animator Controller)實現(xiàn)多套動作,非常利于維護。按官方說法就是: 如果一類模型可以共用動畫狀態(tài)機,則可以弄一個基礎(chǔ)Animtor Controller,里面是基本的動畫狀態(tài)邏輯,然后給某個模型使用就弄一個Animtor Override Controller,然后把其中不同的動畫Clip換成自己的,這樣就只需維護一份動畫狀態(tài)機了,省心省力。比如NPC系統(tǒng)的各個NPC。許多怪物也可以共用,主角更不用說。 5.1種換裝系統(tǒng) ?。◤?fù)習(xí)一個知識點:Skinning 蒙皮:給骨架附加網(wǎng)格,把網(wǎng)格中的頂點綁定到骨骼) 先加載2個模型出來,第1個模型是基礎(chǔ)模型,skinmesh/動畫/Animator等都有,第2個模型則是一個帶skinmesh的幾乎空的模型,第一個是源模型,第二個是目標(biāo)模型,我們現(xiàn)在要做的就是用第2個模型的skinmesh替換掉第1個模型的skinmesh,做法如下: a.獲得第一個模型的skinmesh old_meshrender,獲得第2個模型的skinmesh dst_meshrender,獲得第一個模型的所有骨骼 Transform[] bones. b.目的是獲得dst_meshrender中各個頂點映射到bones的各個骨骼列表,即為dst_meshrender網(wǎng)格中各個頂點找到第1個模型中對應(yīng)的骨骼,即為“新皮”重新指定骨骼,然后把old_meshrender的網(wǎng)格sharemesh換成dst_meshrender的sharemesh,把old_meshrender的骨骼bones換成新的骨骼列表(當(dāng)然還是第1個模型的),簡而言之,就是:為第1個模型重新指定網(wǎng)格(第二個模型的),因為網(wǎng)格是新的,所以需要重新映射網(wǎng)格頂點到骨骼,看代碼可能更容易理解: SkinnedMeshRender dst_meshR = newModel.GetComponent<SkinnedMeshRender>(); SkinnedMeshRender old_meshR = oldModel.GetComponent<SkinnedMeshRender>(); Transform[] bones = old_meshR.bones; Transform[] newBones = new Transform[dst_meshR.bones.Length]; for (int i = 0; i < dst_meshR.bones.Length;++i) { for (int j = 0; j < old_meshR.bones.Length; ++j) { if (old_meshR.bones[j].name == dst_meshR.bones[i].name) { newBones[i] = old_meshR.bones[j]; break; } } } old_meshR.sharedMesh = dst_meshR.sharedMesh; old_meshR.bones = newBones; old_meshR.sharedMaterials = dst_meshR.sharedMaterials; 這種換皮技術(shù)原理清晰、簡單,也方便使用,并且只換皮(網(wǎng)格)不換模型骨架,所以對動畫系統(tǒng)等非常方便,只需把那些東西綁定到原始模型即可。 但需要注意的是,各個換裝模型的骨骼要規(guī)范,盡量骨架同原始模型一致,至少需要做到骨骼“可以多不可以少”。 6.混合樹 狀態(tài)轉(zhuǎn)移和混合樹,雖然兩者都是用來制作平滑動畫,但區(qū)別是大大的(讀者可只看前3點即可): 8.之前一直不知道怎么移動瀏覽Animator 窗口的各自狀態(tài):Alt+鼠標(biāo)左鍵! 9.animator的TargetMatching技術(shù) 假如你有一個跳躍的動畫,要實現(xiàn)跳躍到某個物體上的效果,可以考慮用animator的TargetMatching技術(shù): get到模型的Animator ani,然后 animator.MatchTarget(jumpTarget.position, jumpTarget.rotation, AvatarTarget.LeftFoot, new MatchTargetWeightMask(Vector3.one, 1f), 0.141f, 0.78f); 10.IK控制骨骼 步驟: 11.根運動 根運動是動畫本身自帶的,比如行走動畫,如果不apply root motion則“原地踏步”(in-place),如果應(yīng)用則向前行走。 實際項目中一般,不apply root motion,而通過代碼來設(shè)置transform postion,總結(jié)而言: 1.不apply root motion并且該animator組件所在obj上的控制腳本不實現(xiàn)OnAnimatorMove,且所有腳本也不控制該模型position,=>模型原地踏步; PS1:上述只提了位置,根運動也包括rotation,且控制邏輯也是同樣的。 官方說明:Root motion is the effect where an object‘s entire mesh moves away from its starting point but that motion is created by the animation itself rather than by changing the Transform position. Note that applyRootMotion has no effect when the script implements a MonoBehaviour.OnAnimatorMove function.Changing the value of applyRootMotion at runtime will re-initialize the animator. 11.一些優(yōu)化建議 1.The Animator doesn’t spend time processing when a Controller is not set to it 12.Animator Component Unity Manual:參考這篇:http://www.cnblogs.com/Tearix/p/6941156.html Unity Script:屬性和接口太多了,看官方文檔吧,有個翻譯可以參考一下,但那個只是作者自己的理解,不保證準(zhǔn)確: http://www.cnblogs.com/hont/p/5100472.html?utm_source=tuicool&utm_medium=referral 13.一個坑 Play(A);Play(B);則最終Play了A;以前好像遇到過有概率不播某個動畫的情況,沒查明是否是因此造成的。解決方法是: Play(A);Update(x);Play(B);則最終Play了B,用Update更新一下就可以覆蓋了。如果是CrossFade,情況又復(fù)雜一些了,這個問題我專門和一位網(wǎng)友討論過,這里不提。 標(biāo)簽:amp 錨點 end skin ble 動作 actor bre 函數(shù)定義 原文地址:http://www.cnblogs.com/Tearix/p/6939948.html |
|
|
來自: 勤奮不止 > 《游戲引擎unity》