?GPU 3D骨骼動(dòng)畫和 GPU 2D?Spine動(dòng)畫插件均包含在【萬人同屏整合方案】中,老板們可在某寶搜:[游戲開發(fā)資源商店] 以獲取全套方案的所有源碼插件。
?
萬人同屏渲染避障鎖敵方案實(shí)現(xiàn)對抗戰(zhàn)斗demo 展示GPU動(dòng)畫高級功能 動(dòng)畫事件 動(dòng)畫平滑過渡 融合
?
插件功能:
1. 支持3D動(dòng)畫轉(zhuǎn)GPU動(dòng)畫?
2. 支持2D Spine動(dòng)畫轉(zhuǎn)GPU動(dòng)畫
3. 支持掛點(diǎn)、支持掛載物、動(dòng)態(tài)切換掛載物、實(shí)時(shí)獲取掛點(diǎn)Transform信息
4. 支持實(shí)時(shí)獲取gpu動(dòng)畫信息,如動(dòng)畫幀數(shù)、動(dòng)畫時(shí)長、動(dòng)畫是否循環(huán)
5. 支持動(dòng)畫事件
GPU骨骼動(dòng)畫視頻介紹:
GPU頂點(diǎn)動(dòng)畫和GPU骨骼動(dòng)畫實(shí)現(xiàn)原理及優(yōu)缺點(diǎn)對比 性能優(yōu)化
2d spine動(dòng)畫幀數(shù)提升數(shù)十倍?spine轉(zhuǎn)gpu動(dòng)畫 2d spine動(dòng)畫 10w單位
GPU動(dòng)畫是實(shí)現(xiàn)萬人同屏的前置條件,在之前的文章中已介紹過GPU頂點(diǎn)動(dòng)畫的實(shí)現(xiàn)方法:【Unity】渲染性能開掛GPU Animation, 動(dòng)畫渲染合批GPU Instance_skinmeshrender合批-CSDN博客
GPU頂點(diǎn)動(dòng)畫的優(yōu)缺點(diǎn):
GPU頂點(diǎn)動(dòng)畫是將每一幀動(dòng)畫的Mesh頂點(diǎn)/法線存入貼圖,在Shader中直接讀取頂點(diǎn)/法線使用。
優(yōu)點(diǎn):由于沒有過多的計(jì)算,因此性能較高;
缺點(diǎn):如果一個(gè)模型有多個(gè)SkinnedMeshRenderer需要先合并Mesh; 生成的動(dòng)畫/法線貼圖較大;不支持切換掛載武器;
GPU骨骼動(dòng)畫的優(yōu)缺點(diǎn):
GPU骨骼動(dòng)畫是將每一幀動(dòng)畫的所有骨骼的矩陣信息存入貼圖,每一個(gè)頂點(diǎn)至多受4根骨骼影響,在Shader中用這4根骨骼的矩陣和4根骨骼對應(yīng)的蒙皮權(quán)重對頂點(diǎn)位置和法線進(jìn)行變換,得到受骨骼影響后的頂點(diǎn)/法線值。
優(yōu)點(diǎn):動(dòng)畫貼圖很??;無需合并Mesh;支持掛載武器切換;可以實(shí)時(shí)獲取到某個(gè)掛點(diǎn)位置
缺點(diǎn):需要一定計(jì)算量,因此性能比頂點(diǎn)動(dòng)畫略低;
GPU骨骼動(dòng)畫實(shí)現(xiàn):
一,讀取骨骼數(shù)據(jù),生成動(dòng)畫貼圖,Mesh
?1. 獲取蒙皮動(dòng)畫的骨骼信息:
可通過SkinnedMeshRenderer的rootBone查找到根骨骼,或者直接使用bones字段,該字段為SkinnedMeshRenderer關(guān)聯(lián)的所有骨骼的Transform數(shù)組;
2. 從動(dòng)畫曲線獲取每個(gè)動(dòng)畫幀記錄的骨骼Transform數(shù)值:
以獲取動(dòng)畫每幀的骨骼位置為例:
private Vector3 GetBonePositionAtTime(string bonePath, AnimationClip clip, float animTime)
{
var localPosXCurve = EditorCurveBinding.FloatCurve(bonePath, typeof(Transform), "m_LocalPosition.x");
var localPosYCurve = EditorCurveBinding.FloatCurve(bonePath, typeof(Transform), "m_LocalPosition.y");
var localPosZCurve = EditorCurveBinding.FloatCurve(bonePath, typeof(Transform), "m_LocalPosition.z");
Vector3 pos = Vector3.zero;
pos.x = AnimationUtility.GetEditorCurve(clip, localPosXCurve).Evaluate(animTime);
pos.y = AnimationUtility.GetEditorCurve(clip, localPosYCurve).Evaluate(animTime);
pos.z = AnimationUtility.GetEditorCurve(clip, localPosZCurve).Evaluate(animTime);
return pos;
}
3. 將骨骼矩陣寫入動(dòng)畫貼圖:
把矩陣的前3行數(shù)值,以骨骼個(gè)數(shù)為偏移量分別寫入動(dòng)畫貼圖:
for (int boneIdx = 0; boneIdx < bones.Length; boneIdx++)
{
var bone = bones[boneIdx];
bool noBone = bone.GetComponent<MeshRenderer>() != null;
if (!noBone && bone.TryGetComponent<SkinnedMeshRenderer>(out var sMeshRender) && sMeshRender.rootBone == null)
{
noBone = true;
}
var boneMatrix = bone.localToWorldMatrix;
if (!noBone)
{
boneMatrix *= bonesW2LMatrices[boneIdx];
}
animBoneTex.SetPixel(boneIdx, curFrameIndex, boneMatrix.GetRow(0));
animBoneTex.SetPixel(bonesCount + boneIdx, curFrameIndex, boneMatrix.GetRow(1));
animBoneTex.SetPixel(bonesCount * 2 + boneIdx, curFrameIndex, boneMatrix.GetRow(2));
}
4. 將每個(gè)動(dòng)畫的開始幀/結(jié)束幀、動(dòng)畫時(shí)常、動(dòng)畫是否循環(huán)播放的信息寫入動(dòng)畫貼圖的最后一列像素?

?5. 生成Mesh網(wǎng)格:
有了骨骼信息的動(dòng)畫貼圖,還需要知道每個(gè)頂點(diǎn)受哪些骨骼影響,才能在Shader中取到對應(yīng)的骨骼信息對頂點(diǎn)和法線進(jìn)行變換;
為了節(jié)省資源和讀取方便,我們可以直接把頂點(diǎn)關(guān)聯(lián)的4根骨骼以及每根骨骼的權(quán)重分別塞到Mesh的UV2和UV3兩個(gè)通道。
?二、GPU骨骼動(dòng)畫Shader實(shí)現(xiàn):
?1. 從動(dòng)畫貼圖中解析當(dāng)前動(dòng)畫的起始/結(jié)束幀,根據(jù)是否Loop來計(jì)算出當(dāng)前動(dòng)畫幀:
?2. 以當(dāng)前幀為動(dòng)畫貼圖采樣的V坐標(biāo),采樣獲取所有骨骼矩陣每行數(shù)值,構(gòu)建骨骼矩陣并計(jì)算頂點(diǎn)/法線:
3.? 通過自定義函數(shù)得到轉(zhuǎn)換后的頂點(diǎn)坐標(biāo)和法線并應(yīng)用到GPU骨骼動(dòng)畫shader:
?這樣就完成了GPU骨骼動(dòng)畫功能,切換動(dòng)畫時(shí)傳入動(dòng)畫Index和當(dāng)前時(shí)間Time.time,動(dòng)畫片段將自動(dòng)從起始幀開始播放,并且完美支持動(dòng)畫是否循環(huán)。對于在骨骼上掛載的武器,無論是MeshRenderer還是SkinnedMeshRenderer都完美支持,因?yàn)閽燧d武器的節(jié)點(diǎn)Transform本身也作為骨骼寫入到了動(dòng)畫貼圖,Shader中會(huì)自動(dòng)通過骨骼的Local2WorldMatrix對頂點(diǎn)進(jìn)行變換,自然而然武器就會(huì)跟著骨骼動(dòng)。
三,獲取掛點(diǎn)位置?
例如GPU動(dòng)畫人物手里拿著一把槍,發(fā)射子彈時(shí)就需要在槍口的位置創(chuàng)建并發(fā)射子彈,由于GPU動(dòng)畫已經(jīng)沒有了骨骼Transform,槍口的位置怎么獲取呢?
GPU動(dòng)畫因?yàn)槭羌僑hader實(shí)現(xiàn),所以切換動(dòng)畫只需要修改材質(zhì)的ClipId屬性即可,其中x作為動(dòng)畫索引,y作為動(dòng)畫播放的開始時(shí)間,即Time.time。
有了動(dòng)畫索引和播放的開始時(shí)間,我們就可以得到當(dāng)前動(dòng)畫已經(jīng)播放了多久,根據(jù)已經(jīng)播放時(shí)長就可以算出動(dòng)畫播到了第幾幀,通過第幾幀就可以從動(dòng)畫貼圖讀出任意骨骼的矩陣,這樣就實(shí)現(xiàn)了隨用隨取的高性能獲取掛載點(diǎn)位置、旋轉(zhuǎn)、縮放。
四,GPU動(dòng)畫幀事件:?
GPU動(dòng)畫轉(zhuǎn)換工具會(huì)自動(dòng)把Animation Clip中包含的事件數(shù)據(jù)保存到文件里,無需手動(dòng)處理。并且支持隨意增刪事件。
GPU動(dòng)畫事件同時(shí)支持 Mesh Renderer渲染和BRG渲染。
兩種渲染模式觸發(fā)邏輯不同:
1. 使用MeshRenderer渲染只需掛載一個(gè)事件腳本,然后就像為Button添加/移除監(jiān)聽事件一樣簡單。
2. 使用BRG渲染, BRG提供了獲取觸發(fā)事件的接口,接口使用Jobs檢測當(dāng)前幀觸發(fā)的事件,并將事件列表返回,由用戶在主線程自行調(diào)用觸發(fā)。大大提升了海量GPU動(dòng)畫單位事件觸發(fā)性能。
同時(shí)GPU動(dòng)畫事件處理時(shí)會(huì)進(jìn)行插幀計(jì)算,不會(huì)因?yàn)榭D問題導(dǎo)致跳過動(dòng)畫事件的觸發(fā)。
例如:一個(gè)弓箭手射箭動(dòng)畫,動(dòng)畫前大部分是搭箭、拉弓,動(dòng)畫最后一幀才松手,為了顯示效果同步,就需要在最后一幀弓箭手松手時(shí)讓箭發(fā)射出去,而不是在搭箭/拉弓的時(shí)候就發(fā)射箭。通過使用幀事件就能完美卡點(diǎn)解決這個(gè)問題。
五,GPU動(dòng)畫過渡/融合:?
?目前市面上的GPU動(dòng)畫插件要么是沒有動(dòng)畫融合,要么就是使用腳本計(jì)算融合,會(huì)導(dǎo)致性能大打折扣。為了保證性能優(yōu)先、兼容性高,最佳方案還是純shader處理。
如何用最小的代價(jià)實(shí)現(xiàn)GPU動(dòng)畫平滑過渡呢?GPU動(dòng)畫切換動(dòng)畫時(shí)需要修改material上的shader參數(shù)clipId(Vector4),其中x為動(dòng)畫clip的索引,y為動(dòng)畫切換時(shí)間,zw是預(yù)留屬性,暫未用到。
已知clip索引和切換動(dòng)畫的時(shí)間就可以輕易計(jì)算出動(dòng)畫已經(jīng)播了多久,進(jìn)而計(jì)算出播到第幾幀,然后通過幀數(shù)就可以從動(dòng)畫貼圖中讀取到當(dāng)前幀所有骨骼的Transform信息,然后所有骨骼從當(dāng)前的Transform數(shù)值平滑過渡到下一動(dòng)畫clip索引的第一幀骨骼Transform不就能實(shí)現(xiàn)骨骼平滑過渡了嗎?我們還需要指導(dǎo)上一個(gè)動(dòng)畫索引和上一個(gè)動(dòng)畫開始播放的時(shí)間,正好存入預(yù)留的zw中。
GPU 2d Spine動(dòng)畫實(shí)現(xiàn):
有多個(gè)網(wǎng)友反饋有2D GPU動(dòng)畫的需求,不過我們通常會(huì)認(rèn)為2D很難存在渲染瓶頸,然而并非如此。經(jīng)過實(shí)際測試同屏顯示相同的動(dòng)畫人物,1W個(gè)Spine動(dòng)畫 vs 1W個(gè)Animator動(dòng)畫。測試結(jié)果令人大跌眼鏡!Spine動(dòng)畫和Animator動(dòng)畫性能接近,1W單位下都只有8幀左右。要知道,我們之前測試的五百多頂點(diǎn)的3D人物,同數(shù)量級下能達(dá)到近9幀左右。Spine動(dòng)畫性能竟然如此之差!
看來對于數(shù)量級超過百、千單位的項(xiàng)目,非常有必要使用GPU Spine動(dòng)畫。
2d spine動(dòng)畫幀數(shù)提升30倍 spine轉(zhuǎn)gpu動(dòng)畫 2d spine動(dòng)畫 10w單位
?實(shí)現(xiàn)原理其實(shí)就是把Spine動(dòng)畫轉(zhuǎn)換為Animator動(dòng)畫,由于2D動(dòng)畫都是有面片Mesh組成,z軸全為0. 因此必須解決渲染層級的問題,這一轉(zhuǎn)換過程需對Mesh進(jìn)行修改以使得渲染層級正確。轉(zhuǎn)換為Animator動(dòng)畫后就可以使用我們的GPU動(dòng)畫轉(zhuǎn)換工具直接進(jìn)行轉(zhuǎn)換,同樣支持頂點(diǎn)動(dòng)畫/骨骼動(dòng)畫兩種模式。文章來源:http://www.zghlxwxcb.cn/news/detail-836597.html
同屏1W個(gè)單位測試環(huán)境下,Spine動(dòng)畫轉(zhuǎn)換為GPU 2D動(dòng)畫后幀數(shù)直接提升10倍以上,使用萬人同屏方案合批渲染功能后,相比Spine動(dòng)畫提升接近恐怖的40倍,對于2D割草游戲絕對是最佳方案。文章來源地址http://www.zghlxwxcb.cn/news/detail-836597.html
到了這里,關(guān)于【Unity】GPU骨骼 GPU Spine動(dòng)畫 2D/3D渲染性能開掛 合批渲染 支持武器掛載 動(dòng)畫事件 動(dòng)畫融合 實(shí)時(shí)獲取骨骼位置的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!