一、簡介
1、所需知識點
(1)射線檢測
(2)Mecanim動畫系統
(3)Navigation尋路系統
(4)OGUI
(5)歐拉角與四元數、向量
(6)持久化數據
2、遊戲需求
(1)開始界面(人物換裝),到遊戲場景角色誕生,誕生的角色穿着換裝界面存儲的服裝。
(2)隨機在3個誕生點,一共產生3波怪(每波怪2-3個即可)。
(3)怪物頭頂有血條,隨着波數的累加怪物越來越難打(血量多)。
(4)角色與怪之間動畫互動(Mecanim動畫系統),如:角色射線打到怪物,角色播放攻擊動畫,怪播放受到攻擊的動畫。
(5)敵人,角色血條效果。
(6)打敵人,隨機產生掉裝備,吃到掉的裝備可實現例如加血的效果。
(7)打死3波怪後勝利畫面,自己血條值爲0時GameOver畫面 。
二、開始界面
先上圖,看看最終完成是什麼樣的!
在點擊不同的按鈕有不同的事件響應,按鈕功能就不進行說明了。
按鈕功能實現邏輯: 以上按鈕可以分爲四種按鈕,分別是角色選擇、服裝選擇、武器選擇、動作預覽。
那麼我們就可以按這四種分類將功能進行實現,創建一個空物體,將一個種類的按鈕作爲此空物體的孩子,編寫的腳本就給予空物體,那麼給按鈕添加事件就需要遍歷所有的子物體,然後添加按鈕點擊事件。而點擊按鈕需要實現功能,我就拿角色選擇按鈕來舉例,另外三種按鈕的腳本可以仿照此邏輯進行編寫;
角色選擇按鈕功能實現: 在點擊按鈕後,我需要進行角色物體的創建,那麼按鈕和預製件之間就需要有響應,那麼如何根據我們點擊的按鈕來創建指定的角色呢?我們可以通過按鈕名字與預製件名字來進行聯繫,將按鈕名字設置成爲預製件的名字 (按鈕名字也可以不和預製件名字相同,但是必須包含預製件名字),那麼功能的實現就比較簡單了,可以創建字典,key值爲按鈕名字,value值爲gameobject類型,存儲角色預製件,那麼我們在點擊按鈕的時候就可以根據按鈕名字直接獲取預製件進行創建角色物體了。另三種按鈕功能請自行類推了~
溫馨提示:代碼編寫當中的細節問題在代碼註釋中有說明
1、開始界面按鈕功能代碼
- 角色選擇功能
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class GenerateRole : MonoBehaviour
{
public GameObject[] gameRole;
public Transform vec;
private Dictionary<string,GameObject> dic;
public static GameObject Role { get; set; }
public GenerateRole() { }
private void Start()
{
//初始化字典
dic = new Dictionary<string, GameObject>();
//遍歷所有的孩子,給按鈕添加點擊事件
AddEevent();
}
//因按鈕和預製件的名字不一樣
//所以需要對name進行切割
private void GetButtonName()
{
var button = EventSystem.current.currentSelectedGameObject;
CreateRole(button.name.Substring(4));
}
//遍歷所有孩子添加,給按鈕添加點擊時間
private void AddEevent()
{
string name;
for (int i=0;i<transform.childCount;i++)
{
name = transform.GetChild(i).name.Substring(4);
//將遊戲物體添加至字典當中
//每次點擊按鈕,就將按鈕的名字和遊戲物體存入字典
//避免重複點擊按鈕時,需要重複遍歷
for (int x=0;x<gameRole.Length;x++)
{
if (gameRole[x].name == name)
{
dic.Add(name,gameRole[x]);
}
}
transform.GetChild(i).GetComponent<Button>().onClick
.AddListener(new UnityAction(GetButtonName));
}
}
//創建遊戲物體
private void CreateRole(string name)
{
//如果vec有孩子,則銷燬後再創建,如果沒有則直接創建
GameObject deleteClone;
int childCount = vec.childCount;
if (childCount==1)
{
//若是創建的遊戲物體就是這個孩子,則不進行任何代碼執行
//因名字包含Clone,所以還需要對名字進行改變再判斷
//Debug.Log(vec.GetChild(0).name);
if (vec.GetChild(0).name==(name+"(Clone)"))
{
return;
}
deleteClone = vec.GetChild(0).gameObject;
Destroy(deleteClone);
SetParent(name);
}
else if (childCount == 0)
{
SetParent(name);
}
}
private void SetParent(string name)
{
GameObject clone = Instantiate(dic[name], vec.position, Quaternion.identity);
Role = clone;
//將創建的遊戲物體設置爲vic的子類
clone.transform.SetParent(vec);
}
}
- 武器選擇功能
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class WeaponChose : MonoBehaviour
{
//創建武器位置
private Transform weaponLocal;
public GameObject[] weapons;
private Dictionary<string, GameObject> dic;
private void Start()
{
//字典進行初始化
dic = new Dictionary<string, GameObject>();
AddEvent();
DicAddWeapon();
}
//遍歷所有孩子,添加按鈕點擊事件
/// <summary>
/// 添加點擊事件
/// </summary>
private void AddEvent()
{
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i).GetComponent<Button>().onClick
.AddListener(new UnityAction(CreateWeapon));
}
}
//將所有武器類型添加進入字典當中
private void DicAddWeapon()
{
string name;
for (int i = 0; i < transform.childCount; i++)
{
name = transform.GetChild(i).name.Substring(4);
for (int index = 0; index < transform.childCount; index++)
{
if (name == weapons[index].name)
{
dic.Add(name, weapons[index]);
}
}
}
}
//點擊事件
//根據按鈕的名字來創建武器
/// <summary>
/// 創建武器
/// </summary>
private GameObject clone;
private void CreateWeapon()
{
//按鈕名字
string buttonName = EventSystem.current.currentSelectedGameObject.name.Substring(4);
//給武器尋找位置
weaponLocal = GameObject.Find("wphand").transform;
if (weaponLocal != null)
{
//如果wphand不存在孩子,則直接創建,否則進行二次判斷
if (weaponLocal.childCount == 1)
{
//如果孩子的名字就是所點擊按鈕的名字,那麼就直接結束程序
if (weaponLocal.GetChild(0).name == (buttonName + "(Clone)"))
{
return;
}
//否則進行武器的創建,並銷燬原來的物體
Destroy(clone);
SetParent(buttonName);
}
else
//進行名字切割並創建武器
SetParent(buttonName);
}
else Debug.Log("請先創建遊戲角色");
}
private void SetParent(string buttonName)
{
clone = Instantiate(dic[buttonName], weaponLocal.position, Quaternion.Euler(180, -105, 0));
clone.transform.SetParent(weaponLocal);
}
}
- 服裝選擇功能
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ChoseCloth : MonoBehaviour
{
/*
* 需要先知道目前所選擇的角色是誰,才能夠進行衣服的選擇
*1、去HereCreate中獲取創建的角色是誰
*2、在人物創建時,給一個人物返回值Role即可
*可用二維字典進行存儲,第一個參數爲角色,第二個參數爲衣服號碼
*/
//獲取的名字是帶有Clone的,需要進行處理
private GameObject role;
public Texture[] cloths;
private Dictionary<string, Dictionary<string, Texture>> dic;
// private Renderer rend;
//數據初始化
private void Start()
{
dic = new Dictionary<string, Dictionary<string, Texture>>();
DicAddCloth();
AddButtonEvent();
}
private void DicAddCloth()
{
int index = 0;
//存儲的種類名字,四種衣服
string[] clothname=new string[4];
string[] name;
string newName = null;
//遍歷cloths數組,將其添加至二維數組
foreach (Texture cloth in cloths)
{
//衣服名字格式爲mon_goblinWizard_c2_df
//將名字切割,取第二個goblinWizard,再加上(Clone),再爲其添加衣服
name = cloth.name.Split('_');
if (Array.IndexOf(clothname, name[1])==-1)
{
clothname[index++] = name[1];
dic.Add(name[1], new Dictionary<string, Texture>());
//Debug.Log("clothname:"+name[1]);
}
dic[name[1]].Add((dic[name[1]].Count+1)+"", cloth);
// Debug.Log(newName[1]);
}
}
private void AddButtonEvent()
{
for (int i=0;i<transform.childCount;i++)
{
transform.GetChild(i).GetComponent<Button>().onClick.AddListener
(new UnityAction(ButtonEvent));
}
}
/// <summary>
/// 觸發事件,更換衣服
/// </summary>
private void ButtonEvent()
{
//獲取角色
role = GenerateRole.Role;
//根據按鈕名字來更換衣服
string buttonName = EventSystem.current.currentSelectedGameObject.name;
//按鈕名字格式爲btn_col_02
//獲取最後一個數字即可
string clothName = buttonName.Substring(buttonName.Length-1);
if (role != null)
{
//將role.name的名字進行切割
string[] RoleName = role.name.Split('(');
string[] RoleName01 = RoleName[0].Split('_');
//Debug.Log("衣服名字"+clothName);
//Debug.Log("角色名字" + role.name);
//Debug.Log("種類名字:"+ RoleName01[1]);
role.GetComponentInChildren<SkinnedMeshRenderer>().material.mainTexture
= dic[RoleName01[1]][clothName];
}
else { Debug.Log("請先創建遊戲角色"); }
}
}
- 動作預覽功能
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ActionPlay : MonoBehaviour
{
/*
* 動作按鈕的播放設置
*/
//獲取遊戲對象
private GameObject role;
private Animation ani;
private void Start()
{
AddEvent();
}
//給每個按鈕添加點擊事件
private void AddEvent()
{
for (int i=0;i<transform.childCount;i++)
{
transform.GetChild(i).GetComponent<Button>().onClick.
AddListener(new UnityAction(PlayAction));
}
}
/// <summary>
/// 播放動畫
/// </summary>
private void PlayAction()
{
role = GenerateRole.Role;
string buttonName = EventSystem.current.currentSelectedGameObject.name;
string[] newName = null;
if (role!=null)
{
ani = role.GetComponent<Animation>();
newName = buttonName.Split('_');
ani.Play(newName[newName.Length-1]);//字符串爲按鈕名字切割後的字符串
ani.CrossFadeQueued("Idle");
}
}
}
人物模型連接(含UI貼圖)------MonsterBaseTeam.rar
其他功能的實現請見 Unity3D-----簡易遊戲項目開發02