校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁(yè) > 知識(shí)庫(kù) > 游戲開(kāi)發(fā)進(jìn)階Unity網(wǎng)格(Mesh\動(dòng)態(tài)合批\骨骼動(dòng)畫(huà)\蒙皮)

游戲開(kāi)發(fā)進(jìn)階Unity網(wǎng)格(Mesh\動(dòng)態(tài)合批\骨骼動(dòng)畫(huà)\蒙皮)

熱門(mén)標(biāo)簽:400電話(huà)辦理費(fèi)用低 蘇州呼叫中心外呼系統(tǒng)哪家強(qiáng) 鶴壁高頻外呼系統(tǒng)多少錢(qián)一個(gè)月 400電話(huà)申請(qǐng)到底哪家好 外呼系統(tǒng)怎么群發(fā)短信 聯(lián)通外呼系統(tǒng)電腦app軟件 地圖標(biāo)注項(xiàng)目幾個(gè)月 谷歌地圖標(biāo)注日期 宿遷怎么辦理400電話(huà)

一、前言

嗨,大家好,我是新發(fā)。
有同學(xué)私信我讓我寫(xiě)一篇Unity網(wǎng)格相關(guān)的教程,

那我就帶大家來(lái)一次Unity的網(wǎng)格探險(xiǎn)之旅吧~

二、Hello Mesh

我背著旅行背包走在Unity的場(chǎng)景中,突然眼前出現(xiàn)了一棵樹(shù),

我走近一看,這棵樹(shù)身上掛著MeshFilterMeshRenderer組件,根據(jù)Unity探險(xiǎn)手冊(cè)記載,這個(gè)MeshFilter是網(wǎng)格過(guò)濾器,它會(huì)引用一個(gè)網(wǎng)格資源,我順騰摸瓜,找到了對(duì)應(yīng)的網(wǎng)格,

實(shí)在太美了,我久久佇立,這就是網(wǎng)格啊!
正當(dāng)我欣賞著網(wǎng)格三角形時(shí),突然世界暗了下來(lái),眼前出現(xiàn)了一團(tuán)火,

我又拿出了Unity探險(xiǎn)手冊(cè),啊,這一定就是粒子系統(tǒng)了!它可以動(dòng)態(tài)生成網(wǎng)格。

天外傳來(lái)一陣打字聲,場(chǎng)景中出現(xiàn)了一行看起來(lái)像文字的網(wǎng)格,作為一個(gè)具有多年Hello World經(jīng)驗(yàn)的程序員,我看出了第一個(gè)單詞應(yīng)該是Hello,第二個(gè)單詞…我知道了,

Hello Mesh

(此處為震撼人心的入場(chǎng)音樂(lè))

三、萌新初識(shí)Mesh

1、引擎內(nèi)置的Mesh

網(wǎng)格的英文名是MeshUnity萌新最先接觸的網(wǎng)格應(yīng)該就是引擎內(nèi)置的Cube(正方體)、Capsule(膠囊體)、Cylinder(圓柱體)、Plane(平面)、Sphere(球體)、Quad(四邊形),如下

事實(shí)上,我們?cè)?code>Unity場(chǎng)景中,所有能被渲染出來(lái)的物體都會(huì)帶有網(wǎng)格,比如3D模型、粒子特效、UI、文字等等。

2、Mesh是什么

從概念上講,網(wǎng)格是圖形硬件用來(lái)繪制復(fù)雜內(nèi)容的構(gòu)造。它至少包含一組定義3D空間中點(diǎn)的頂點(diǎn),以及一組連接這些點(diǎn)的三角形,實(shí)際上還包含法線、頂點(diǎn)顏色紋理坐標(biāo)等信息,這些三角形構(gòu)成了網(wǎng)格所代表的任何表面。

我們可以看下UnityMesh類(lèi),Mesh的屬性和方法很多,我這里列舉幾個(gè)比較常用的,如下

// 頂點(diǎn)坐標(biāo)數(shù)組
public Vector3[] vertices { get; set; }
// 法線向量數(shù)組
public Vector3[] normals { get; set; }
// 頂點(diǎn)顏色數(shù)組
public Color[] colors { get; set; }
// 三角形序列數(shù)組,每三個(gè)數(shù)字為一組
public int[] triangles { get; set; }
// uv坐標(biāo)數(shù)組
public Vector2[] uv { get; set; }
// 重新計(jì)算法線,在修改完頂點(diǎn)后,通常會(huì)更新法線來(lái)反映新的變化,注意,法線是根據(jù)共享的頂點(diǎn)計(jì)算出來(lái)的。
public void RecalculateNormals();
// 從法線和紋理坐標(biāo)重新計(jì)算網(wǎng)格的切線。修改網(wǎng)格的頂點(diǎn)和法線之后,如果網(wǎng)格使用引用法線貼圖的著色器進(jìn)行渲染,則切線需要更新。 
public void RecalculateTangents();
// 重新計(jì)算從網(wǎng)格包圍體的頂點(diǎn), 在修改頂點(diǎn)后需要這個(gè)函數(shù)以確保包圍體是正確的,賦值三角形將自動(dòng)重新計(jì)算這個(gè)包圍體。
public void RecalculateBounds();

畫(huà)個(gè)圖,方便大家有個(gè)直觀印象,

三、Mesh的創(chuàng)建方式

1、第三方建模軟件

建模本質(zhì)上就是建網(wǎng)格,我們可以事先通過(guò)第三方建模軟件來(lái)創(chuàng)建模型網(wǎng)格,

常見(jiàn)的建模軟件比如

3DS MAX官網(wǎng):https://www.autodesk.com/products/3ds-max/overview

MAYA官網(wǎng):https://www.autodesk.com/products/maya/overview

blender官網(wǎng):https://www.blender.org/

2、Unity建模插件:ProBuilder

Unity官方提供了一個(gè)可以用來(lái)創(chuàng)建和自定義幾何體的工具ProBuilder,我們可以在UnityPackage Manager中下載到這個(gè)插件,

使用ProBuilder我們可以直接在Unity中創(chuàng)建或編輯簡(jiǎn)單的幾何體,不用通過(guò)第三方建模軟件,提升了效率,方便快速搭建場(chǎng)景原型,

3、程序動(dòng)態(tài)生成網(wǎng)格

網(wǎng)格也可以是程序動(dòng)態(tài)生成的,比如粒子系統(tǒng)的網(wǎng)格就是動(dòng)態(tài)生成的,

又比如文字,也是程序動(dòng)態(tài)生成網(wǎng)格,

文章后面我還會(huì)手把手教你如何使用純代碼來(lái)構(gòu)建網(wǎng)格,這里先不急著寫(xiě)代碼,我們繼續(xù)探尋網(wǎng)格的秘密先~

四、Unity中如何顯示網(wǎng)格

Unity中,我們要顯示一個(gè)網(wǎng)格,需要用到兩個(gè)組件:MeshFilterMeshRenderer

注:你也可以直接使用SkinnedMeshRenderer組件,與MeshFilterMeshRenderer的區(qū)別我下文會(huì)講。

1、MeshFilter:網(wǎng)格過(guò)濾器

MeshFilter是網(wǎng)格過(guò)濾器,我們需要通過(guò)它設(shè)置引用的網(wǎng)格資源,比如這里引用的是一個(gè)Cube(正方體)網(wǎng)格。

我們可以看下MeshFilter.cs的源碼,

[RequireComponent(typeof(Transform))]
[NativeHeader("Runtime/Graphics/Mesh/MeshFilter.h")]
public sealed partial class MeshFilter : Component
{
    [RequiredByNativeCode]  // MeshFilter is used in the VR Splash screen.
    private void DontStripMeshFilter() {}

    extern public Mesh sharedMesh { get; set; }
    extern public Mesh mesh {[NativeName("GetInstantiatedMeshFromScript")] get; [NativeName("SetInstantiatedMesh")] set; }
}

MeshFilter只有兩個(gè)屬性:meshsharedMesh
我們查看Unity的官方手冊(cè),看看meshsharedMesh的區(qū)別:https://docs.unity3d.com/ScriptReference/MeshFilter.html

我來(lái)解讀一下,mesh訪問(wèn)的是一個(gè)Mesh資源的實(shí)例(副本),這意味著我們修改這個(gè)mesh并不會(huì)修改到原始資源本身,改的只是Mesh的實(shí)例(副本)。
sharedMesh是原始資源的引用,如果修改了sharedMesh,比如修改頂點(diǎn)坐標(biāo),那么原始資源也會(huì)被修改。
畫(huà)成圖大概是這樣子:

這里我順手寫(xiě)個(gè)隨機(jī)修改Mesh頂點(diǎn)坐標(biāo)的腳本,如下,將下面這個(gè)RandoMeshmVertices腳本掛到MeshFilter組件所在的物體上即可,

// RandoMeshmVertices.cs
// 隨機(jī)修改Mesh頂點(diǎn)坐標(biāo)
using UnityEngine;
public class RandoMeshmVertices: MonoBehaviour
{
    // Mesh的實(shí)例
    MeshFilter meshFilter;
    // 頂點(diǎn)的原始坐標(biāo)
    Vector3[] originalVertices;
    void Start()
    {
        meshFilter = GetComponentMeshFilter>();
        originalVertices = meshFilter.mesh.vertices;
    }
    void Update()
    {
        // 隨機(jī)修改頂點(diǎn)坐標(biāo)
        Vector3[] vertices = meshFilter.mesh.vertices;
        for (int i = 0, len = originalVertices.Length; i  len; ++i)
        {
            var v = originalVertices[i];
            vertices[i] = v + Random.Range(-0.1F, 0.1F) * Vector3.one;
        }
        meshFilter.mesh.vertices = vertices;
        meshFilter.mesh.RecalculateNormals();
    }
}

運(yùn)行效果如下,網(wǎng)格頂點(diǎn)坐標(biāo)發(fā)生了隨機(jī)偏移,

關(guān)于mesh屬性的訪問(wèn)需要特別注意一下,我們先看看Unity官方手冊(cè)的說(shuō)明,https://docs.unity3d.com/ScriptReference/MeshFilter-mesh.html

翻譯一下就是,如果一個(gè)Mesh資源已經(jīng)被分配給MeshFiltermesh屬性,那么當(dāng)我們?cè)诖a中第一次訪問(wèn)mesh屬性時(shí)才正真創(chuàng)建了Mesh的實(shí)例;再次訪問(wèn)mesh屬性時(shí)則直接返回這個(gè)實(shí)例,并且一旦mesh屬性被訪問(wèn),則與原始共享網(wǎng)格的鏈接會(huì)丟失,此時(shí)sharedMesh變成mesh的別名,如果我們想避免這種自動(dòng)生成Mesh實(shí)例,可以使用sharedMesh代替。
寫(xiě)成偽代碼的話(huà)大致是這樣子:

public class MeshFilter ...
{
	...
	private Mesh _mesh;
	public Mesh mesh
	{
		get
		{
			if (_mesh == null) 
			{
				_mesh = new Mesh();
				Copy(sharedMeh, _mesh);
			}
			return _mesh;
		}
	}
	...
}

還有,如果我們?cè)L問(wèn)了mesh屬性而導(dǎo)致自動(dòng)創(chuàng)建了Mesh實(shí)例,則需要在代碼中主動(dòng)調(diào)用Resources.UnloadUnusedAssets來(lái)銷(xiāo)毀沒(méi)有引用的Mesh實(shí)例,建議是在場(chǎng)景切換時(shí)調(diào)用Resources.UnloadUnusedAssets

2、MeshRenderer:網(wǎng)格渲染器

MeshRenderer,顧名思義,網(wǎng)格渲染器。我們依舊先來(lái)看看官方手冊(cè)的介紹:

https://docs.unity3d.com/Manual/class-MeshRenderer.html

翻譯過(guò)來(lái)就是MeshRenderer會(huì)從MeshFilter那里拿到網(wǎng)格數(shù)據(jù)并在所在物體的位置處將其渲染出來(lái)。
如果沒(méi)有MeshRenderer,我們就看不見(jiàn)網(wǎng)格了,如下

另外,我們還需要在MeshRendererMaterials中指定一個(gè)材質(zhì)球,這樣才能正常顯示,否則模型表面就是紫色的。

3、SkinnedMeshRenderer:蒙皮網(wǎng)格渲染器

SkinnedMeshRenderer是蒙皮網(wǎng)格渲染器,可能有小伙伴就會(huì)問(wèn)了,上面使用MeshFilterMeshRenderer已經(jīng)可以顯示模型網(wǎng)格了,為什么又弄了一個(gè)SkinnedMeshRenderer呢?
看下Unity官方手冊(cè)的介紹:https://docs.unity3d.com/Manual/class-SkinnedMeshRenderer.html

可以看到SkinnedMeshRenderer其實(shí)是針對(duì)帶 骨骼動(dòng)畫(huà) 的模型的渲染的。

3.1 骨骼動(dòng)畫(huà)

為什么需要做骨骼動(dòng)畫(huà)呢?

就好比我們?nèi)艘粯樱覀兊墓趋罆?huì)隨著我們肌肉的伸縮而動(dòng),骨骼又可以帶動(dòng)它管轄的身體部位發(fā)生形變和移動(dòng),骨骼還會(huì)影響它所連接的其他骨骼一起發(fā)生聯(lián)動(dòng)。對(duì)應(yīng)到模型動(dòng)作上,想想一個(gè)簡(jiǎn)單的舉手動(dòng)作要牽涉到多少網(wǎng)格頂點(diǎn)的移動(dòng),如果沒(méi)有骨骼,那動(dòng)畫(huà)師要每幀挨個(gè)網(wǎng)格頂點(diǎn)進(jìn)行調(diào)整,即使動(dòng)畫(huà)做出來(lái)了,這個(gè)動(dòng)畫(huà)也不能復(fù)用到其他模型上,因?yàn)椴煌P偷捻旤c(diǎn)信息都不一樣,這么低效的動(dòng)畫(huà)制作肯定是不行的,于是,就有了骨骼動(dòng)畫(huà)。

骨骼動(dòng)畫(huà)的原理

就是將模型分為骨骼(Bone)和蒙皮(Mesh)兩個(gè)部分,骨骼可分為多層父子骨骼,每個(gè)骨骼都附加到周?chē)W(wǎng)格的一些頂點(diǎn)上,在動(dòng)畫(huà)關(guān)鍵幀數(shù)據(jù)的驅(qū)動(dòng)下,計(jì)算出各個(gè)父子骨骼的位置,基于骨骼的控制通過(guò)頂點(diǎn)混合動(dòng)態(tài)計(jì)算出蒙皮網(wǎng)格的頂點(diǎn)。

動(dòng)畫(huà)師可以在MAYA軟件上給模型綁定骨骼,綁定骨骼不是本文的重點(diǎn),這里就不展講開(kāi)具體操作了,感興趣的同學(xué)可以自行百科學(xué)習(xí)。

制作好導(dǎo)出為fbx格式,

fbx文件導(dǎo)入到Unity中,選中它,

Inspector視圖中點(diǎn)擊Rig按鈕,

我們可以看到動(dòng)畫(huà)類(lèi)型Animation TypeNoneLegacyGenericHumanoid四個(gè),

具體選項(xiàng)可以參見(jiàn)Unity官方手冊(cè):https://docs.unity3d.com/Manual/FBXImporter-Rig.html

我這里演示一下人形骨骼動(dòng)畫(huà),選擇Humanoid類(lèi)型,Avatar Definition選擇Create From This Model,然后點(diǎn)擊Configure

Inspector視圖中我們就可以看到對(duì)應(yīng)的骨骼綁定信息了,

如下,綠色的線段就是一根根骨骼,

我們調(diào)整一根骨骼,對(duì)應(yīng)的網(wǎng)格也會(huì)跟著一起動(dòng),如下

這樣做出來(lái)的人形動(dòng)畫(huà)是可以進(jìn)行復(fù)用了,有請(qǐng)妹子上場(chǎng),

骨骼動(dòng)畫(huà)資源的話(huà),我在之前的文章中也介紹過(guò)一個(gè)寶藏網(wǎng)站Mixamo:https://www.mixamo.com/,上面有很多做好的人形骨骼動(dòng)畫(huà),

看,是不是挺好玩的,

我們可以把它的動(dòng)作直接復(fù)用到我們自己的人形模型上,效果如下:



3.2 SkinnedMeshRenderer組件

骨骼動(dòng)畫(huà)可以正常播放,要?dú)w功于SkinnedMeshRenderer組件,制作好骨骼動(dòng)畫(huà)的fbx文件導(dǎo)入Unity中,Unity會(huì)自動(dòng)幫我們掛上SkinnedMeshRenderer組件,


其中幾個(gè)重要的屬性我講一下,
Bounds:骨骼數(shù)據(jù);
Mesh:要渲染的網(wǎng)格;
Root Bone:根骨骼,其他骨骼都是相對(duì)根骨骼移動(dòng)的;
BlendShapes:一般用于制作表情融合,我之前寫(xiě)過(guò)一篇文章講過(guò)BlendShapes

Unity通過(guò)BlendShape實(shí)現(xiàn)面部表情過(guò)渡切換Animation教程

我們?cè)賮?lái)看看SkinnedMeshRenderer腳本的屬性和方法:

需要講的應(yīng)該就是這個(gè)BakeMesh方法了,下面我就單獨(dú)拎出來(lái)講下BakeMesh

3.2 使用BakeMesh進(jìn)行優(yōu)化

假設(shè)現(xiàn)在場(chǎng)景中有100只皮卡丘,每只皮卡丘的網(wǎng)格、貼圖、動(dòng)作相同,

如果每只皮卡丘身上都掛SkinnedMeshRenderer,那就是100個(gè)SkinnedMeshRenderer在計(jì)算蒙皮,

由于SkinnedMeshRenderer是根據(jù)骨骼動(dòng)畫(huà)動(dòng)態(tài)計(jì)算網(wǎng)格頂點(diǎn)坐標(biāo),這個(gè)運(yùn)算開(kāi)銷(xiāo)還是不小的,有沒(méi)有辦法優(yōu)化呢?

SkinnedMeshRenderer提供了一個(gè)BakeMesh方法,可以將一個(gè)蒙皮動(dòng)畫(huà)的某個(gè)時(shí)間點(diǎn)上的動(dòng)作,Bake成一個(gè)不帶蒙皮的Mesh,我們統(tǒng)一使用這個(gè)Mesh來(lái)顯示其余的皮卡丘,這樣就可以大大減少了SkinnedMeshRenderer的計(jì)算了,
畫(huà)成圖大概是這樣子:

不過(guò),上面這種方案的局限性是每只皮卡丘的動(dòng)畫(huà)是相同的,如果突然某一只皮卡丘要播放與其他皮卡丘不同的動(dòng)畫(huà),那就不行了。

另一種Bake方案可以是這樣:
對(duì)皮卡丘的每個(gè)動(dòng)畫(huà)進(jìn)行遍歷采樣,把采樣到的Mesh存到數(shù)組中,因?yàn)檫@里要Bake很多網(wǎng)格,比較耗時(shí),建議在加載場(chǎng)景時(shí)時(shí)就完成采樣過(guò)程;后面要播放某個(gè)動(dòng)畫(huà)時(shí)直接從這個(gè)Mesh數(shù)組中獲取Mesh來(lái)顯示,此時(shí)直接使用MeshFilterMeshRenderer的方式來(lái)顯示網(wǎng)格就好了。
貼個(gè)BakeMesh的示例腳本:

using UnityEngine;
using System.Collections.Generic;
/// summary>
/// Bake Mesh 示例
/// /summary>
public class BakeMeshTest : MonoBehaviour
{
    [SerializeField]
    Animation m_animation;
    [SerializeField]
    SkinnedMeshRenderer m_skinnedMeshRenderer; 
    [SerializeField]
    string m_clipToBake = "Idle";
    ListMesh> m_bakedMeshList = new ListMesh>();
    /// summary>
    /// 采樣幀數(shù)
    /// /summary>
    [SerializeField]
    int m_numFramesToBake = 30;
    void Start()
    {
        // 獲取要Bake的動(dòng)畫(huà)片段
        AnimationState clipState = m_animation[m_clipToBake];
        if (clipState == null)
        {
            Debug.LogError(string.Format("Unable to get clip '{0}'", m_clipToBake), this);
            return;
        }
        // 開(kāi)始播放動(dòng)畫(huà)
        m_animation.Play(m_clipToBake, PlayMode.StopAll);
        // 設(shè)置動(dòng)畫(huà)初始時(shí)間戳
        clipState.time = 0.0f;
        // 采樣幀間隔
        float deltaTime = clipState.length / (float)(m_numFramesToBake - 1);
        for (int frameIndex = 0; frameIndex  m_numFramesToBake; ++frameIndex)
        {
            string frameName = string.Format("BakedFrame{0}", frameIndex);
            // 創(chuàng)建Mesh
            Mesh frameMesh = new Mesh();
            frameMesh.name = frameName;
            // 動(dòng)畫(huà)采樣
            m_animation.Sample();
            // 執(zhí)行BakeMesh
            m_skinnedMeshRenderer.BakeMesh(frameMesh);
            m_bakedMeshList.Add(frameMesh);
            // 設(shè)置動(dòng)畫(huà)時(shí)間戳
            clipState.time += deltaTime;
        }
        // 停止播放動(dòng)畫(huà)
        m_animation.Stop();
    }

}

需要提醒的是,這個(gè)方案是利用空間換時(shí)間,如果模型頂點(diǎn)數(shù)據(jù)特別多或動(dòng)畫(huà)時(shí)長(zhǎng)特別長(zhǎng)的時(shí)候,這時(shí)就會(huì)遇到內(nèi)存瓶頸。

五、純代碼動(dòng)態(tài)創(chuàng)建網(wǎng)格

一般情況下,網(wǎng)格是事先制作好的資源,但也有一些特殊的需求需要在代碼中動(dòng)態(tài)創(chuàng)建網(wǎng)格。
比如我之前寫(xiě)的一篇牙齒碎了的文章:

游戲開(kāi)發(fā)Unity2D圖片任意形狀破碎裂片效果展示

現(xiàn)在我來(lái)教大家如何使用代碼從零創(chuàng)建網(wǎng)格并將網(wǎng)格渲染出來(lái),下文我以創(chuàng)建一個(gè)正方形網(wǎng)格為例進(jìn)行講解。

1、創(chuàng)建Mesh對(duì)象

第一步最簡(jiǎn)單,就是直接new一個(gè)Mesh

var mesh = new Mesh();

2、頂點(diǎn)坐標(biāo)

首先分析一下,一個(gè)四邊形有四個(gè)頂點(diǎn),假設(shè)正方形邊長(zhǎng)為1,四個(gè)點(diǎn)的坐標(biāo)如下,

寫(xiě)成代碼就是這樣:

// 構(gòu)建頂點(diǎn)坐標(biāo)
var vertices = new ListVector3>();
vertices.Add(new Vector3(-0.5f, -0.5f, 0));
vertices.Add(new Vector3(-0.5f, 0.5f, 0));
vertices.Add(new Vector3(0.5f, 0.5f, 0));
vertices.Add(new Vector3(0.5f, -0.5f, 0));
// 將頂點(diǎn)坐標(biāo)設(shè)置給Mesh
mesh.SetVertices(vertices);

3、UV坐標(biāo)

UV坐標(biāo)就是紋理貼圖坐標(biāo),它將紋理上每一個(gè)點(diǎn)精確對(duì)應(yīng)到模型物體的表面上,注意UV的取值范圍是0~1
UV坐標(biāo)系原點(diǎn)在左下角,U軸是水平軸,V軸是豎直軸,如下:

對(duì)應(yīng)到我們的上面那個(gè)正方向網(wǎng)格的話(huà),四個(gè)點(diǎn)的UV坐標(biāo)如下:

寫(xiě)成代碼就是這樣:

// 構(gòu)建UV坐標(biāo)
var uvs = new ListVector2>();
uvs.Add(new Vector2(0, 0));
uvs.Add(new Vector2(0, 1));
uvs.Add(new Vector2(1, 1));
uvs.Add(new Vector2(1, 0));
// 將UV坐標(biāo)設(shè)置給Mesh
mesh.SetUVs(0, uvs);

4、三角形序列

網(wǎng)格需要切分成三角形,我們可以這樣切分,

當(dāng)然也可以這樣切分,

兩種切分方法對(duì)應(yīng)不同的三角形序列,假設(shè) 法線方向 是垂直于屏幕從內(nèi)指向屏幕外的話(huà),第一種切分方式的三角形序列如下:

注:法線的方向就決定了表面正面,如果你的材質(zhì)是單面渲染的話(huà),那么只有從正面看才能看到網(wǎng)格被渲染。

即三角形序列為:{ 0, 1, 2, 0, 2, 3 },注意序號(hào)是從0開(kāi)始的。
為什么是這樣的順序呢?我教大家一個(gè)技巧,伸出你的左手,豎起大拇指,像這樣子,

大拇指指向法線的方向,那么此時(shí)你的其余四根手指頭環(huán)繞的方向就是三角形的序號(hào)的順序,三個(gè)序號(hào)為一組按順序塞入數(shù)組中即可,即得到的數(shù)組就是:{ 0, 1, 2, 0, 2,3}當(dāng)然,以下數(shù)組最終的效果都是等價(jià)的,只要順序一致即可:

{ 0, 1, 2, 0, 2, 3 },
{ 1, 2, 0, 0, 2, 3 },
{ 0, 2, 3, 1, 2, 0 },

我們現(xiàn)在寫(xiě)成代碼,

// 重新計(jì)算法線,注意,法線是根據(jù)共享的頂點(diǎn)計(jì)算出來(lái)的。
mesh.RecalculateNormals();

// 重新計(jì)算包圍體,在修改頂點(diǎn)后需要這個(gè)函數(shù)以確保包圍體是正確的
mesh.RecalculateBounds();

// 從法線和紋理坐標(biāo)重新計(jì)算網(wǎng)格的切線(如果網(wǎng)格使用引用法線貼圖的著色器進(jìn)行渲染,則切線需要更新)
// 因?yàn)槲覀冞@里不使用法線貼圖,所以就不調(diào)用它了
// mesh.RecalculateTangents();

5、重新計(jì)算法線和包圍體

當(dāng)我們?cè)O(shè)置或修改了頂點(diǎn)數(shù)據(jù)后,需要調(diào)用MeshRecalculate方法來(lái)重新計(jì)算一些必要的信息,比如重新計(jì)算法線、包圍體,代碼如下

// 重新計(jì)算法線,注意,法線是根據(jù)共享的頂點(diǎn)計(jì)算出來(lái)的。
mesh.RecalculateNormals();

// 重新計(jì)算包圍體,在修改頂點(diǎn)后需要這個(gè)函數(shù)以確保包圍體是正確的
mesh.RecalculateBounds();

// 從法線和紋理坐標(biāo)重新計(jì)算網(wǎng)格的切線(如果網(wǎng)格使用引用法線貼圖的著色器進(jìn)行渲染,則切線需要更新)
// 因?yàn)槲覀冞@里不使用法線貼圖,所以就不調(diào)用它了
// mesh.RecalculateTangents();

6、完整版代碼

以上代碼封裝成GenQuadMesh.cs腳本,完整代碼如下:

// 使用代碼生成四邊形網(wǎng)格
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class GenQuadMesh : MonoBehaviour
{
    public MeshFilter mf;
    private void Start()
    {
        mf.mesh = Build();
    }
   public static Mesh Build()
    {
        var mesh = new Mesh();
        // 構(gòu)建頂點(diǎn)坐標(biāo)
        var vertices = new ListVector3>();
        vertices.Add(new Vector3(-0.5f, -0.5f, 0));
        vertices.Add(new Vector3(-0.5f, 0.5f, 0));
        vertices.Add(new Vector3(0.5f, 0.5f, 0));
        vertices.Add(new Vector3(0.5f, -0.5f, 0));
        // 將頂點(diǎn)坐標(biāo)設(shè)置給Mesh
        mesh.SetVertices(vertices);
        // 構(gòu)建UV坐標(biāo)
        var uvs = new ListVector2>();
        uvs.Add(new Vector2(0, 0));
        uvs.Add(new Vector2(0, 1));
        uvs.Add(new Vector2(1, 1));
        uvs.Add(new Vector2(1, 0));
        // 將UV坐標(biāo)設(shè)置給Mesh
        mesh.SetUVs(0, uvs);
        // 設(shè)置三角形序列
        var triangles = new int[] { 0, 1, 2, 0, 2, 3 };
        mesh.SetTriangles(triangles, 0);
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
        return mesh;
    }
}

7、測(cè)試

創(chuàng)建一個(gè)空物體,掛上MeshFilterMeshRenderer組件。

再掛上我們上面寫(xiě)的GenQuadMesh腳本,賦值mf變量為MeshFilter對(duì)象,如下

運(yùn)行Unity,看到一個(gè)紫色快,

Scene視圖的模式設(shè)置為Wireframe,如下

現(xiàn)在我們可以看到我們動(dòng)態(tài)創(chuàng)建的網(wǎng)格啦,

上面之所以顯示紫色塊,是因?yàn)槲覀儧](méi)有給MeshFilter設(shè)置材質(zhì)球,順手做一個(gè)炮姐的材質(zhì)球吧,

MeshRenderer設(shè)置材質(zhì)球?qū)ο螅?/p>

重新運(yùn)行Unity,效果如下,

8、項(xiàng)目源碼

要用代碼動(dòng)態(tài)創(chuàng)建一個(gè)Mesh,就是new一個(gè)Mesh,給它塞入頂點(diǎn)坐標(biāo)、UV坐標(biāo)和三角形序列即可。再?gòu)?fù)雜的網(wǎng)格也可以通過(guò)這些步驟創(chuàng)建出來(lái)~
下面這些就是使用純代碼創(chuàng)建出來(lái)的幾何體網(wǎng)格,感興趣的同學(xué)可以下載項(xiàng)目源碼下來(lái)學(xué)習(xí)。
項(xiàng)目源碼:https://codechina.csdn.net/linxinfa/unity-mesh-builder

六、網(wǎng)格相關(guān)的開(kāi)源項(xiàng)目

我再推薦一些網(wǎng)格相關(guān)的開(kāi)源項(xiàng)目給大家~

1、2D網(wǎng)格涂鴉

項(xiàng)目地址:https://github.com/mattatz/unity-triangulation2D

2、3D網(wǎng)格涂鴉

項(xiàng)目地址:https://github.com/mattatz/unity-teddy

3、網(wǎng)格體素化

項(xiàng)目地址:https://github.com/Scrawk/Mesh-Voxelization

 

4、網(wǎng)格平滑算法

項(xiàng)目地址:https://github.com/mattatz/unity-mesh-smoothing

5、網(wǎng)格切割

項(xiàng)目地址:https://github.com/hugoscurti/mesh-cutter

 

6、網(wǎng)格合并

項(xiàng)目地址:https://github.com/sanukin39/UniMeshCombiner

七、未完的探險(xiǎn)

好了,這次探險(xiǎn)之旅就暫時(shí)到這里吧,還有很多內(nèi)容需要探索,先保持體力,我們下次再見(jiàn),更多關(guān)于Unity網(wǎng)格(Mesh\動(dòng)態(tài)合批\骨骼動(dòng)畫(huà)\蒙皮)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • Unity3D動(dòng)態(tài)生成平面網(wǎng)格
  • 一篇文章教會(huì)你用Unity制作網(wǎng)格地圖生成組件
  • Unity3D網(wǎng)格功能生成球體網(wǎng)格模型
  • Unity3D實(shí)現(xiàn)自動(dòng)尋路

標(biāo)簽:丹東 莆田 雙鴨山 錫林郭勒盟 襄陽(yáng) 哈爾濱 鄂爾多斯 遵義

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《游戲開(kāi)發(fā)進(jìn)階Unity網(wǎng)格(Mesh\動(dòng)態(tài)合批\骨骼動(dòng)畫(huà)\蒙皮)》,本文關(guān)鍵詞  游戲,開(kāi)發(fā),進(jìn)階,Unity,網(wǎng)格,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《游戲開(kāi)發(fā)進(jìn)階Unity網(wǎng)格(Mesh\動(dòng)態(tài)合批\骨骼動(dòng)畫(huà)\蒙皮)》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于游戲開(kāi)發(fā)進(jìn)階Unity網(wǎng)格(Mesh\動(dòng)態(tài)合批\骨骼動(dòng)畫(huà)\蒙皮)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    久久国产麻豆精品| 国产美女在线观看一区| 国产精品视频第一区| 欧美少妇xxx| 成人a区在线观看| 亚洲国产精品嫩草影院| 国产亚洲精品7777| 欧美日韩在线一区二区| 福利视频网站一区二区三区| 日韩福利视频导航| 一区二区三区鲁丝不卡| 国产日产欧美一区二区视频| 91精品欧美福利在线观看| 色女孩综合影院| 91色porny蝌蚪| 91麻豆国产香蕉久久精品| 国产高清久久久| 国产成人一区二区精品非洲| 黑人巨大精品欧美一区| 美女看a上一区| 秋霞国产午夜精品免费视频| 日韩电影免费在线| 日韩av电影一区| 久久精品国产在热久久| 裸体在线国模精品偷拍| 美腿丝袜在线亚洲一区| 久久国产福利国产秒拍| 久久精品72免费观看| 激情综合色综合久久| 韩国中文字幕2020精品| 国产高清久久久久| av爱爱亚洲一区| 欧美在线短视频| 在线不卡中文字幕| 26uuu亚洲综合色欧美| 国产三级欧美三级| 亚洲男女一区二区三区| 亚洲图片一区二区| 老司机午夜精品99久久| 国产精品一区二区黑丝| 风间由美一区二区av101| 精品一区二区免费视频| 精品亚洲国产成人av制服丝袜| 日韩中文字幕区一区有砖一区 | 蜜臀av一级做a爰片久久| 日韩成人dvd| 成人小视频免费观看| 日本久久精品电影| 日韩欧美一区中文| 国产精品国产自产拍高清av| 午夜精品国产更新| 丰满白嫩尤物一区二区| 欧美午夜理伦三级在线观看| 欧美mv和日韩mv的网站| 最新国产の精品合集bt伙计| 免费人成精品欧美精品| 色噜噜狠狠一区二区三区果冻| 日韩精品一区在线观看| 亚洲视频一区在线观看| 蜜臀av亚洲一区中文字幕| 91色.com| 国产女人水真多18毛片18精品视频 | 日本高清不卡视频| 精品99一区二区三区| 亚洲一区二区三区四区五区黄| 国产美女精品人人做人人爽| 欧美日韩精品欧美日韩精品一综合| 久久网站最新地址| 日韩成人av影视| 欧美三级午夜理伦三级中视频| 欧美精品一区二区三区视频| 亚洲图片欧美综合| 色综合久久66| 日韩美女精品在线| 国产成人在线色| 久久五月婷婷丁香社区| 青青草97国产精品免费观看无弹窗版| 99re这里都是精品| 国产欧美日韩亚州综合| 狠狠色综合色综合网络| 日韩精品中文字幕一区二区三区| 亚洲电影视频在线| 欧美日韩一区久久| 亚洲自拍偷拍图区| 欧美性受xxxx黑人xyx性爽| 亚洲色图欧洲色图| 色香色香欲天天天影视综合网| 中文字幕一区在线观看| gogo大胆日本视频一区| 国产精品国产三级国产| k8久久久一区二区三区| 亚洲婷婷综合色高清在线| av中文字幕在线不卡| 亚洲另类一区二区| 91成人看片片| 午夜a成v人精品| 91精品免费观看| 九九九精品视频| 国产精品丝袜在线| 色狠狠色狠狠综合| 天堂蜜桃一区二区三区| 精品国产电影一区二区| 国产成人精品一区二区三区四区| 国产日韩欧美一区二区三区乱码 | 国产成a人无v码亚洲福利| wwwwww.欧美系列| 国产精品99久久不卡二区| 国产精品全国免费观看高清| 97久久精品人人做人人爽| 亚洲综合另类小说| 91麻豆精品国产91久久久更新时间| 蜜臀av性久久久久蜜臀aⅴ流畅| 2023国产精华国产精品| aaa欧美日韩| 日韩成人一区二区| 国产精品视频观看| 欧美性欧美巨大黑白大战| 久久99精品一区二区三区三区| 久久久www免费人成精品| 色欲综合视频天天天| 日韩精品午夜视频| 国产精品久久久久婷婷| 欧美电影影音先锋| heyzo一本久久综合| 麻豆一区二区三区| 亚洲精品一卡二卡| 欧美精品一区二区三区四区| 色噜噜狠狠成人网p站| 国产综合色精品一区二区三区| 亚洲色图.com| 国产亚洲欧美在线| 日韩丝袜情趣美女图片| av电影在线观看不卡| 国产精品一区二区果冻传媒| 久久99精品久久久久久久久久久久| 亚洲激情综合网| 国产精品乱码久久久久久| 精品少妇一区二区三区视频免付费| 盗摄精品av一区二区三区| 久久国产欧美日韩精品| 午夜精品成人在线| 亚洲一区二区不卡免费| 1024成人网色www| 久久久国产精华| 国产日韩精品一区二区三区| 777亚洲妇女| 欧美一级国产精品| 欧美一区二区三区视频在线| 91色.com| 欧美日韩国产影片| 欧美日本视频在线| 欧美一二三四区在线| 制服视频三区第一页精品| 欧美精品国产精品| 制服丝袜成人动漫| 精品99一区二区| 国产色综合一区| 亚洲美女区一区| 午夜久久久影院| 麻豆传媒一区二区三区| 奇米影视一区二区三区| 久久精品久久精品| 成人一级片网址| 欧洲激情一区二区| 欧美一级一区二区| 国产喂奶挤奶一区二区三区| 日韩一区有码在线| 亚洲综合精品自拍| 日本特黄久久久高潮| 国产精品资源在线观看| 国产成人在线免费| 日本高清无吗v一区| 欧美日韩亚洲高清一区二区| 欧美一区二区久久| 国产三级一区二区| 夜夜操天天操亚洲| 免费成人av在线| jlzzjlzz欧美大全| 91精品欧美一区二区三区综合在| 欧美日本高清视频在线观看| 久久综合久久综合亚洲| 亚洲色图20p| 激情国产一区二区| 91电影在线观看| 精品国产一区二区三区忘忧草| 国产精品久久777777| 美女高潮久久久| 99re热视频这里只精品| 欧美一区二区人人喊爽| 亚洲素人一区二区| 国产成人精品免费网站| 欧美精品久久久久久久久老牛影院| 26uuu国产一区二区三区| 亚洲国产综合视频在线观看| 久久99久久久久| 在线视频你懂得一区| 国产日韩成人精品| 欧美96一区二区免费视频| 91论坛在线播放| 国产欧美日韩久久|