#遊戲unity-音之國度#戰鬥系統中的血條
原創禁止轉載!
現在博主先給大家大致展示一下AR遊戲“音之國度”的大致框架和流程——
啓動遊戲—>登陸界面—>以滾動文字和圖片的方式講述故事背景—>加載界面—>進入新手引導系統並得到音符獸圖鑑—>打開攝像頭掃描卡牌以確定自己的音符獸 接下來進入主界面,遊戲正式開始
在主界面中可以選擇進入對戰或養成,其中一側出現自己音符獸的模型。
對戰系統會與其他的玩家回合制對戰,隨機得到道具和經驗值;在養成系統中可以對音符獸使用得到的道具,與其進行動作交互,可消耗一定經驗值進行升級,有二到三個等級,每個等級有不同的形態。在遊戲中始終可以通過點擊圖鑑來獲得所有音符獸的特點和基本信息。
其中,還包括存檔和讀檔的實現,UI美術資源的製作及界面搭建,道具的設計。
博主負責的是AR的對戰系統的部分,先從戰鬥系統的界面入手開始吧。
衆所周知,戰鬥系統中怎麼會沒有血條呢?我們先來介紹血條的製作及控制代碼。
血條
因爲這是AR遊戲,跟一般的3D遊戲不同,你用攝像頭掃描出的模型出現在屏幕的哪個位置,血條就會跟隨,在對戰開始前要確定下來卡牌的位置,在戰鬥中保持不變,否則模型消失,戰鬥將強行結束,下次需重新開始。
那麼我們需要一個可以跟隨物體的血條,當碰撞時,血量減少,先要做出基本的demo。
·首先新建一個UI中的物體Scrollbar,如下圖所示:
新建一個空物體,將Scrollbar作爲它的子物體,並與Scrollbar同級的新建一個Test,在其中書寫上Hp最大值;將Scrollbar的子物體Handle圖形顏色改爲紅色,將Scrollbar上的圖形顏色改爲藍色;將它們調整到合適的位置。
以上,一個基本的血條框就完成了。
·關於碰撞與血量的交互代碼
我們用WASD來簡單的控制物體的移動,當兩個模型碰撞時,血量減少一定量。
也就是說,我們需要在碰撞(交互)發生同時,實時的改變血條的長度以及血條框上的血量數值,所以應在開頭聲明如下變量——
public float MoveSpeed;
public int MAX_HP;
public int attack;
private int _hp;
private Scrollbar hpProgress;
private Text hpText;
爲了實時觀察到物體的狀態,用來監測交互的發生,聲明狀態變量——
private byte state;
private const byte STATE_STAND=1;
private const byte STATE_MOVE=2;
private const byte STATE_DIE=3;
初始在Start()方法裏就應該對組件聲明的變量進行賦值,找到對應的組件——
if(progress!=null)
{
hpText=progress.GetComponentInChildren<Text>();
hpProgress=progress.GetComponentInChildren<Scrollbar>();
}
接下來的思路就是在接收到碰撞等交互後,按照一定的比例減少紅色血條的長度。這個demo中 對每次傷害的值是固定的,而我們需要一個暴擊的隨機傷害值,這樣會增加可玩性,所以需要用到隨機數方法,很簡單的就不多說啦。
簡單的demo控制代碼如下——(後期還會根據需求進行改進和調試,這個是基本版的)
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Blood : MonoBehaviour {
public KeyCode[] controlKeyCode;
public Transform progress;
public float MoveSpeed;
public int MAX_HP;
public int attack;
private int _hp;
private Scrollbar hpProgress;
private Text hpText;
private byte state;
private const byte STATE_STAND=1;
private const byte STATE_MOVE=2;
private const byte STATE_DIE=3;
// Use this for initialization
void Start () {
if(progress!=null)
{
hpText=progress.GetComponentInChildren<Text>();
hpProgress=progress.GetComponentInChildren<Scrollbar>();
}
Hp=MAX_HP;
ChangeState(STATE_STAND);
}
private int Hp
{
get
{
return this._hp;
}
set
{
this._hp=value;
this.hpText.text="血量:"+this._hp;
hpProgress.size=this._hp/(float)MAX_HP;
}
}
void ChangeState(byte state)
{
this.state=state;
switch(state)
{
case STATE_STAND:
break;
case STATE_MOVE:
break;
}
}
// Update is called once per frame
void Update () {
for(int i=0;i<controlKeyCode.Length;i++)
{
if(Input.GetKeyDown(controlKeyCode[i]))
{
ChangeState(STATE_MOVE);
break;
}
else if(Input.GetKey(controlKeyCode[i]))
{
float hMove=Input.GetAxis("Horizontal");
float vMove=Input.GetAxis("Vertical");
this.transform.Translate(hMove*MoveSpeed*Time.fixedDeltaTime,vMove*MoveSpeed*Time.fixedDeltaTime,0);
break;
}
else if(Input.GetKeyUp(controlKeyCode[i]))
{
ChangeState(STATE_STAND);
break;
}
}
}
void FixedUpdate()
{
Vector3 vtHeroWorldPos=this.transform.position;
Vector3 vtHeroScrpos=Camera.main.WorldToScreenPoint(vtHeroWorldPos);
progress.transform.position=vtHeroScrpos;
}
void OnTriggerEnter(Collider other)
{
if(state==STATE_MOVE||state==STATE_DIE)
{
return;
}
Blood attackHero=other.gameObject.GetComponent<Blood>();
if(attackHero==null)
{
return;
}
this.Hp-=attackHero.attack;
if(this.Hp<=0)
{
this.Hp=0;
}
Debug.Log("角色:"+this.name+" 掉血:"+attackHero.attack+" 當前生命值:"+this.Hp);
if(this.Hp==0)
{
ChangeState(STATE_DIE);
Debug.Log("角色:"+this.name+" 死亡");
}
}
}