Unity3D遊戲開發之換裝系統的實現
不知從什麼時候開始,國產RPG單機遊戲開始出現換裝,仙劍系列中第一部實現了換裝的遊戲是仙劍奇俠傳四,後來原上海軟星團隊,目前的燭龍科技更是在/《古劍奇譚》中將換裝發揮到了極致。我們來看幾組圖片吧:
換裝從某種意義上來說就是改變角色的外觀,雖然沒有什麼特別實用的功能,但從視覺上可以打破以往PRG遊戲一套行頭走天下的尷尬局面,所以換裝還是很不錯的。那麼從技術上來講,換裝主要分為兩類:
一、增加式換裝
所謂增加式換裝,就是指角色模型的身體是一個完整的網格,需要更換的部分只是一個可拆卸的部件,因而換裝實際上就是在特定的部位增加或者移除一個模型。這類換裝通常用在角色的武器更換中,仙劍、古劍的武俠更換都是這種型別,如圖所示的魚骨頭只是在手這個位置更換模型:
二、更新式換裝
更新式換裝是指角色擁有一個公共的骨骼網路和針對該模型的若干組貼圖。那麼,此時的換裝實際上就是將貼圖貼到對應的位置實現角色外觀的改變,仙劍四嚴格來講應該不算是換裝,它實際上是做了兩套模型(瓊華裝/野人裝)。古劍奇譚的換裝實際上就是這種型別的換裝,這裡我們以下面的一個例子,來一起學習如何實現這種型別的換裝。首先我們建立一個Unity專案:
首先我們去下載官方提供的換裝的例子,我們這裡只需要裡面的模型,因為這個模型提供了多組貼圖可以供我們使用。我們將模型拖拽到場景中,我們展開模型可以發現模型是有若干個部分組成的,每一個模型都有一個SkinnedMeshRenderer元件,改變該元件的材質,我們就可以實現對特定部位的換裝。由此,我們寫出了下面的程式碼:
- using UnityEngine;
- using System.Collections;
- public class ChangeSkin : MonoBehaviour {
- //眼睛貼圖
- public Texture2D[] TextureEyes;
- //面部貼圖-前
- public Texture2D[] TextureFace1;
- //面部貼圖-後
- public Texture2D[] TextureFace2;
- //頭髮貼圖-前
- public Texture2D[] TextureHair1;
- //頭髮貼圖-後
- public Texture2D[] TextureHair2;
- //下衣貼圖-前
- public Texture2D[] TexturePants1;
- //下衣貼圖-後
- public Texture2D[] TexturePants2;
- //上衣貼圖-前
- public Texture2D[] TextureTop1;
- //上衣貼圖-後
- public Texture2D[] TextureTop2;
- //鞋子貼圖-前
- public Texture2D[] TextureShoes1;
- //鞋子貼圖-後
- public Texture2D[] TextureShoes2;
- //與貼圖對應的SkinnedMeshRenderer
- SkinnedMeshRenderer MeshEyes;
- SkinnedMeshRenderer MeshFace1;
- SkinnedMeshRenderer MeshFace2;
- SkinnedMeshRenderer MeshHair1;
- SkinnedMeshRenderer MeshHair2;
- SkinnedMeshRenderer MeshPants1;
- SkinnedMeshRenderer MeshPants2;
- SkinnedMeshRenderer MeshTop1;
- SkinnedMeshRenderer MeshTop2;
- SkinnedMeshRenderer MeshShoes1;
- SkinnedMeshRenderer MeshShoes2;
- void Start ()
- {
- //獲取SkinnedMeshRenderer
- MeshEyes=transform.Find("eyes").GetComponent<SkinnedMeshRenderer>();
- MeshFace1=transform.Find("face-1").GetComponent<SkinnedMeshRenderer>();
- MeshFace2=transform.Find("face-2").GetComponent<SkinnedMeshRenderer>();
- MeshHair1=transform.Find("hair-1").GetComponent<SkinnedMeshRenderer>();
- MeshHair2=transform.Find("hair-2").GetComponent<SkinnedMeshRenderer>();
- MeshPants1=transform.Find("pants-1").GetComponent<SkinnedMeshRenderer>();
- MeshPants2=transform.Find("pants-2").GetComponent<SkinnedMeshRenderer>();
- MeshTop1=transform.Find("top-1").GetComponent<SkinnedMeshRenderer>();
- MeshTop2=transform.Find("top-2").GetComponent<SkinnedMeshRenderer>();
- MeshShoes1=transform.Find("shoes-1").GetComponent<SkinnedMeshRenderer>();
- MeshShoes2=transform.Find("shoes-2").GetComponent<SkinnedMeshRenderer>();
- }
- void OnGUI()
- {
- if(GUILayout.Button("顯示外裝1",GUILayout.Height(30)))
- {
- SetSkin(MeshEyes,TextureEyes[0]);
- SetSkin(MeshFace1,TextureFace1[0]);
- SetSkin(MeshFace2,TextureFace2[0]);
- SetSkin(MeshHair1,TextureHair1[0]);
- SetSkin(MeshHair2,TextureHair2[0]);
- SetSkin(MeshPants1,TexturePants1[0]);
- SetSkin(MeshPants2,TexturePants1[0]);
- SetSkin(MeshTop1,TextureTop1[0]);
- SetSkin(MeshTop2,TextureTop2[0]);
- SetSkin(MeshShoes1,TextureShoes1[0]);
- SetSkin(MeshShoes2,TextureShoes2[0]);
- }
- if(GUILayout.Button("顯示外裝2",GUILayout.Height(30)))
- {
- SetSkin(MeshEyes,TextureEyes[1]);
- SetSkin(MeshFace1,TextureFace1[1]);
- SetSkin(MeshFace2,TextureFace2[1]);
- SetSkin(MeshHair1,TextureHair1[1]);
- SetSkin(MeshHair2,TextureHair2[1]);
- SetSkin(MeshPants1,TexturePants1[1]);
- SetSkin(MeshPants2,TexturePants1[1]);
- SetSkin(MeshTop1,TextureTop1[1]);
- SetSkin(MeshTop2,TextureTop2[1]);
- SetSkin(MeshShoes1,TextureShoes1[1]);
- SetSkin(MeshShoes2,TextureShoes2[1]);
- }
- }
- private void SetSkin(SkinnedMeshRenderer mRenderer,Texture2D mTexture)
- {
- mRenderer.material.mainTexture=mTexture;
- }
- }
using UnityEngine;
using System.Collections;
public class ChangeSkin : MonoBehaviour {
//眼睛貼圖
public Texture2D[] TextureEyes;
//面部貼圖-前
public Texture2D[] TextureFace1;
//面部貼圖-後
public Texture2D[] TextureFace2;
//頭髮貼圖-前
public Texture2D[] TextureHair1;
//頭髮貼圖-後
public Texture2D[] TextureHair2;
//下衣貼圖-前
public Texture2D[] TexturePants1;
//下衣貼圖-後
public Texture2D[] TexturePants2;
//上衣貼圖-前
public Texture2D[] TextureTop1;
//上衣貼圖-後
public Texture2D[] TextureTop2;
//鞋子貼圖-前
public Texture2D[] TextureShoes1;
//鞋子貼圖-後
public Texture2D[] TextureShoes2;
//與貼圖對應的SkinnedMeshRenderer
SkinnedMeshRenderer MeshEyes;
SkinnedMeshRenderer MeshFace1;
SkinnedMeshRenderer MeshFace2;
SkinnedMeshRenderer MeshHair1;
SkinnedMeshRenderer MeshHair2;
SkinnedMeshRenderer MeshPants1;
SkinnedMeshRenderer MeshPants2;
SkinnedMeshRenderer MeshTop1;
SkinnedMeshRenderer MeshTop2;
SkinnedMeshRenderer MeshShoes1;
SkinnedMeshRenderer MeshShoes2;
void Start ()
{
//獲取SkinnedMeshRenderer
MeshEyes=transform.Find("eyes").GetComponent<SkinnedMeshRenderer>();
MeshFace1=transform.Find("face-1").GetComponent<SkinnedMeshRenderer>();
MeshFace2=transform.Find("face-2").GetComponent<SkinnedMeshRenderer>();
MeshHair1=transform.Find("hair-1").GetComponent<SkinnedMeshRenderer>();
MeshHair2=transform.Find("hair-2").GetComponent<SkinnedMeshRenderer>();
MeshPants1=transform.Find("pants-1").GetComponent<SkinnedMeshRenderer>();
MeshPants2=transform.Find("pants-2").GetComponent<SkinnedMeshRenderer>();
MeshTop1=transform.Find("top-1").GetComponent<SkinnedMeshRenderer>();
MeshTop2=transform.Find("top-2").GetComponent<SkinnedMeshRenderer>();
MeshShoes1=transform.Find("shoes-1").GetComponent<SkinnedMeshRenderer>();
MeshShoes2=transform.Find("shoes-2").GetComponent<SkinnedMeshRenderer>();
}
void OnGUI()
{
if(GUILayout.Button("顯示外裝1",GUILayout.Height(30)))
{
SetSkin(MeshEyes,TextureEyes[0]);
SetSkin(MeshFace1,TextureFace1[0]);
SetSkin(MeshFace2,TextureFace2[0]);
SetSkin(MeshHair1,TextureHair1[0]);
SetSkin(MeshHair2,TextureHair2[0]);
SetSkin(MeshPants1,TexturePants1[0]);
SetSkin(MeshPants2,TexturePants1[0]);
SetSkin(MeshTop1,TextureTop1[0]);
SetSkin(MeshTop2,TextureTop2[0]);
SetSkin(MeshShoes1,TextureShoes1[0]);
SetSkin(MeshShoes2,TextureShoes2[0]);
}
if(GUILayout.Button("顯示外裝2",GUILayout.Height(30)))
{
SetSkin(MeshEyes,TextureEyes[1]);
SetSkin(MeshFace1,TextureFace1[1]);
SetSkin(MeshFace2,TextureFace2[1]);
SetSkin(MeshHair1,TextureHair1[1]);
SetSkin(MeshHair2,TextureHair2[1]);
SetSkin(MeshPants1,TexturePants1[1]);
SetSkin(MeshPants2,TexturePants1[1]);
SetSkin(MeshTop1,TextureTop1[1]);
SetSkin(MeshTop2,TextureTop2[1]);
SetSkin(MeshShoes1,TextureShoes1[1]);
SetSkin(MeshShoes2,TextureShoes2[1]);
}
}
private void SetSkin(SkinnedMeshRenderer mRenderer,Texture2D mTexture)
{
mRenderer.material.mainTexture=mTexture;
}
}
這裡我們提供兩套外裝。我們把指令碼拖放到模型上,然後編輯貼圖陣列:
編輯好貼圖後,我們就可以執行程式了,注意貼圖要和模型網格匹配。執行效果:
這種方法需要設計者完全的瞭解角色身體的內部構造,所以需要和美工有良好的合作才可以實現,感覺效果還是不錯的啊,哈哈
好了,這就是今天的部落格了,希望對大家有用、希望大家喜歡!