4.9 生命条 敌人在受到攻击的时候,我们并不知道它受到了多少伤害,为了能够提示它的剩余生命值,我们需要为它制作一个生命条。 在Project窗口的Rawdata/Lifebar目录下可以找到一个LifeBar.fbx文件,这是一个普通的平面模型,并附有一张贴图,如图4-25所示,贴图由简单的黄色和红色组成,我们将使用改变平面模型UV的方式,使黄色表示剩余生命值,红色表示失去的生命。 图4-25 生命条模型 创建脚本LifeBar.cs: using UnityEngine; using System.Collections; public class LifeBar : MonoBehaviour { // 当前生命 public float m_currentLife = 1.0f; // 最大生命 public float m_maxLife = 1.0f; internal Transform m_transform; // 横向缩放生命条 float m_hscale = 1.0f; // 纵向缩放生命条 float m_vscale = 1.0f; // 多边形模型组件 Mesh m_mesh; // 摄像机 Transform m_cameraTransform; //一个二维数组,用于保存UV Vector2[] m_Uvs; // 初始化 public void Ini(float currentlife, float maxlife ,float hscale ,float vscale) { m_transform = this.transform; m_cameraTransform = Camera.main.transform; m_hscale = hscale; m_vscale = vscale; m_transform.localScale = new Vector3(hscale, vscale, 1.0f); // 获得模型组件 m_mesh = (Mesh)this.GetComponent<MeshFilter>().mesh; // 获得模型的顶点 Vector3[] vertices = m_mesh.vertices; // 获得所有的UV m_Uvs = new Vector2[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { m_Uvs[i] = m_mesh.uv[i]; } // 更新生命条状态 UpdateLife(currentlife, maxlife); } // 移动生命条模型的UV void Pad( float value ) { float left = (1.0f - value)/2+0.01f; float right = 0.5f + (1.0f - value)/2-0.01f; // 0==左下角, 1==右下角, 2==右上角, 3==左上角 m_Uvs[0] = new Vector2(left, 0.0f); m_Uvs[3] = new Vector2(left, 1.0f); m_Uvs[1] = new Vector2(right, 0.0f); m_Uvs[2] = new Vector2(right, 1.0f); m_mesh.uv = m_Uvs; } // 根据生命值状况更新生命条模型的UV位置 public void UpdateLife(float currentlife, float maxlife) { if (m_maxLife == 0) return; m_currentLife = currentlife; m_maxLife = maxlife; this.Pad(currentlife / maxlife); m_transform.localScale = new Vector3(m_hscale, m_vscale, 1.0f); } // 设置生命条的位置和方向,它将始终面向摄像机 public void SetPosition( Vector3 position, float yoffset ) { //获得敌人的位置 Vector3 vec = position; // 向上偏移 vec.y += yoffset; m_transform.position = vec; // 使生命条面向Camera Vector3 rot = new Vector3(); rot.y = m_cameraTransform.eulerAngles.y; rot.x = m_cameraTransform.eulerAngles.x; m_transform.eulerAngles = rot; } } 在这个脚本中,Ini函数负责初始化,主要是获取生命条模型的UV。在UpdateLife函数中,我们根据当前生命值和最大生命值计算出一个比例,然后调用Pad函数左右移动UV的位置,当生命值越低,黄色显示的越少,红色显示的越多。 SetPosition函数负责设置生命条的位置,因为生命条始终要伴随相应敌人的移动,并出现在它的上方,所以这个函数设置了一个yoffset参数,使生命条的位置向上偏移一定距离。 将LifeBar.cs脚本指定给LifeBar.fbx作为脚本组件,并将它制作为prefab文件。 打开敌人的脚本Enemy.cs,为它添加生命条属性,并在Inspector窗口将生命条的prefab与其关联。 public Transform m_lifeBarObject; protected LifeBar m_bar; 在脚本Enemy.cs的Start和OnDisable函数中初始化和销毁生命条: void Start () { m_spawn.m_liveEnemy++; GameManager.Instance.m_EnemyList.Add(this); // 创建生命条 Transform obj=(Transform)Instantiate(m_lifeBarObject, this.transform.position, Quaternion.identity); m_bar = obj.GetComponent<LifeBar>(); m_bar.Ini(m_life, m_maxlife, 2, 0.2f); } void OnDisable() { m_spawn.m_liveEnemy--; GameManager.Instance.m_EnemyList.Remove(this); // 销毁生命条 if ( m_bar ) Destroy(m_bar.gameObject); } 在脚本Enemy.cs的MoveTo函数最后添加设置生命条位置的函数,使其一直伴随敌人移动: m_bar.SetPosition(this.transform.position, 4.0f); 在脚本Enemy.cs的SetDamage函数中更新生命条的状态: public void SetDamage(int damage) { m_life -= damage; if (m_life <= 0) { Destroy(this.gameObject); } else m_bar.UpdateLife(m_life, m_maxlife); } 运行游戏,在敌人的上方会出现一个生命条,当敌人受到攻击生命值下降时,黄色会减少,并露出红色,如图4-26所示。 图4-26 生命条