这次主要给大家讲解一下unity 伤害值显示的问题,因为项目里面也做过这方面的内容,所以今天就拿出来给大家分享一下,仅供大家学习参考。

Unity3D游戏开发之伤害数值显示。如图所示,是博主十分喜欢的一部游戏《血雨前传:蜃楼》。这部游戏虽然脱离了前两部作品回合制的模式,以爽快的ACT横版过关模式再次进入玩家的视野中,但是相信只有真正玩过这个游戏的人才知道这是一部地地道道的RPG游戏,诡异、独特的画面风格,古龙式武侠叙事风格都为这部作评带来了无限的生命力。而《雨血》系列更是近年来少有的走出国门、享誉国外的游戏。这部游戏一招一式都很华丽,而且爽快的打击感让人欲罢不能。作为一部PRG游戏,在战斗中最重要的当属敌我双方生命值的对比,所以在战斗中实时显示玩家对敌人造成的伤害值十分重要。《仙剑奇侠传五前传》更是在战斗中加入了伤害统计,方便玩家对于战场局势的把握。好了,讲了这么多,我们来继续我们的Unity3D学习之旅,在下面的文章中,我们将使用Unity3D中的OnGUI()方法来实现伤害数值的 显示。

既然是基于OnGUI()方法的, 相信大家一定很熟悉了,所以我们直接给出代码:

  1. using UnityEngine;
  2. using System.Collections;

  3. public class DamagePopup : MonoBehaviour {

  4.   //目标位置
  5.   private Vector3 mTarget;
  6.   //屏幕坐标
  7.   private Vector3 mScreen;
  8.   //伤害数值
  9.   public int Value;

  10.   //文本宽度
  11.   public float ContentWidth=100;
  12.   //文本高度
  13.   public float ContentHeight=50;

  14.   //GUI坐标
  15.   private Vector2 mPoint;

  16.   //销毁时间
  17.   public float FreeTime=1.5F;

  18.   void Start () 
  19.   {
  20.     //获取目标位置
  21.     mTarget=transform.position;
  22.     //获取屏幕坐标
  23.     mScreen= Camera.main.WorldToScreenPoint(mTarget);
  24.     //将屏幕坐标转化为GUI坐标
  25.     mPoint=new Vector2(mScreen.x,Screen.height-mScreen.y);
  26.     //开启自动销毁线程
  27.     StartCoroutine("Free");
  28.   }

  29.   void Update()
  30.   {
  31.     //使文本在垂直方向山产生一个偏移
  32.     transform.Translate(Vector3.up * 0.5F * Time.deltaTime);
  33.     //重新计算坐标
  34.     mTarget=transform.position;
  35.     //获取屏幕坐标
  36.     mScreen= Camera.main.WorldToScreenPoint(mTarget);
  37.     //将屏幕坐标转化为GUI坐标
  38.     mPoint=new Vector2(mScreen.x,Screen.height-mScreen.y);
  39.   }

  40.   void OnGUI()
  41.   {
  42.     //保证目标在摄像机前方
  43.     if(mScreen.z>0)
  44.     {
  45.        //内部使用GUI坐标进行绘制
  46.        GUI.Label(new Rect(mPoint.x,mPoint.y,ContentWidth,ContentHeight),Value.ToString());
  47.     }
  48.   }

  49.   IEnumerator Free()
  50.   {
  51.     yield return new WaitForSeconds(FreeTime);
  52.     Destroy(this.gameObject);
  53.   }
  54. }
       在上面的代码中我们需要把握下面几点:
       1、根据Transform组件获取位置坐标,将此坐标转化为屏幕坐标及GUI坐标。

       2、Unity3D中常见的四种坐标系:

             a、世界坐标:场景中物体的坐标,使用 transform.position获得。

             b、屏幕坐标:以像素来定义的,以屏幕的左下角为(0,0)点,右上角为(Screen.width,Screen.height),Z的位置是以相机的世界单位来衡量的。如Input.mousePosition即为屏幕坐标。

             c、视口坐标:视口坐标是标准的和相对于相机的。相机的左下角为(0,0)点,右上角为(1,1)点,Z的位置是以相机的世界单位来衡量的。

             d、GUI坐标:该坐标系以屏幕的左上角为(0,0)点,右下角为(Screen.width,Screen.height)。

      3、在代码中我们将世界坐标先转化为屏幕坐标,再转化为GUI坐标

      好了,下面我们将这个脚本绑定在一个空的游戏体上,并制作成预设,在下面的示例中,我们将使用这个预设。

 如图,我们希望实现当角色攻击红色的胶囊体时,在游戏场景中显示玩家对胶囊体造成的伤害值。具体怎么做呢?我们可以先给模型和胶囊体加上碰撞器,并勾选IsTrigger使其成为一个触发器。我们分别将他们的tag设为Player和Enemy。接下来,为Enemy编写一个脚本:

  1. using UnityEngine;
  2. using System.Collections;

  3. public class Enemy : MonoBehaviour {

  4.   public GameObject PopupDamage;

  5.   void OnTriggerEnter(Collider mCollider)
  6.   {
  7.     if(mCollider.gameObject.tag=="Player")
  8.     {
  9.       //克隆伤害弹出组件
  10.       GameObject mObject=(GameObject)Instantiate(PopupDamage,transform.position,Quaternion.identity);
  11.       mObject.GetComponent<DamagePopup>().Value=Random.Range(20,40);
  12.     }
  13.   }
  14. }

      这里我们设定玩家对敌人造成的伤害值为20到40,运行程序,我们会得到下面的结果:

由于这里博主使用的是非精确碰撞,所以导致程序一开始角色就和胶囊体发生了碰撞,而OnTrigger()方法由于只能在碰撞开始的时候捕捉碰撞,所以这里只显示了一次伤害值。理论上只有当玩家攻击胶囊体,才会触发伤害值的显示,不过这个问题再这里我们可以先不追究,因为我们关注的是伤害数值的显示。到目前为止,这个问题已经圆满的解决了。

        有朋友可能会问:为什么人家的游戏里显示的伤害效果看起来那么眩目,而你的程序却只能显示普普通通的文字呢?对于这个问题,我们这里给出两种思路,留给大家自己去探究啊。第一种方法是在项目中创建一个GUISkin,然后在DamagePopup脚本中添加一个GUIStyle类型的成员变量mStyle,通过该变量我们可以引用到在项目中创建的GUISkin。这样,我们就可以定义整体的GUI样式。此时,我们将OnGUI中的方法修改为:

GUI.Label(new Rect(mPoint.x,mPoint.y,ContentWidth,ContentHeight),Value.ToString(),mStyle);
这样我们就可以实现自定义的文字效果了。第二种方法是使用贴图,即首先准备0-9的数字图片,然后我们将Value各个数位上的数字分别截取出来,根据截取的结果来绘制贴图,这样同样可以实现自定义的效果。好了,今天的内容就是这样了。感谢大家关注我的博客,希望大家能够喜欢今天的内容。

    每日箴言: 活得优雅些,别人压不垮你,内心的强大才是真正的强大。