#游戏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+" 死亡");
}
}
}