實現方式有很多,看哪種更適合你的項目:
1. UGUI實現
UI可以方便的實現血條等功能,只需要將角色的世界座標轉換爲屏幕座標,讓狀態條跟隨角色即可
問題在於,UI始終在屏幕最上層,如果有3D物體遮擋住角色,使角色不可見,UI狀態條仍然可見(暴露玩家位置)
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class UIRoleStatusBar : MonoBehaviour
{
Camera mainCamera;
Transform targetRole;
//允許超出屏幕外偏移量
int outScreenOffset = 200;
//跟隨速度(差值)
float followSpeed = 0.25f;
//相對於角色的偏移量
Vector3 rolePosOffset = new Vector3(0, 2, 0);
void Awake()
{
mainCamera = Camera.main;
}
public void Init(Transform role)
{
targetRole = role;
UpdateBarPos();
}
Vector3 tempScreenPos;
public void UpdateBarPos()
{
if (targetRole != null)
{
//世界座標轉屏幕座標
tempScreenPos = mainCamera.WorldToScreenPoint(targetRole.position + rolePosOffset);
//如果位置在屏幕範圍內,刷新位置
if (tempScreenPos.x > -outScreenOffset && tempScreenPos.x < Screen.width + outScreenOffset && tempScreenPos.y > -outScreenOffset && tempScreenPos.y < Screen.height + outScreenOffset)
{
tempScreenPos.z = 0;
//差值跟隨(防止抖動)
transform.position = Vector3.Lerp(transform.position, tempScreenPos, followSpeed);
}
}
}
}
2. 每個狀態條一個Canvas
將Canvas的渲染模式改爲世界座標,作爲角色的子物體,自動跟隨角色,實現更爲簡單
問題在於,場景內角色過多時,Canvas數量也多,還有性能問題
3. 2D Sprite實現
讓狀態條跟隨角色,同時保證Sprite始終朝向相機,即始終朝向屏幕,這樣就不會出現3D世界裏的血條因角色位移或旋轉,與屏幕形成夾角,用Sprite模擬UGUI的Slider效果,實現血條,可以更方便的加一些粒子特效
問題就是用起來沒UGUI那麼方便
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class SpriteRoleStatusBar : MonoBehaviour
{
[SerializeField] Transform healthBar;
Camera mainCamera;
Transform targetRole;
Vector3 posOffset = new Vector3(0, 2, 0);
float followSpeed = 0.25f;
//記錄初始位置
float healthBarInitPosX;
void Awake()
{
mainCamera = Camera.main;
healthBarInitPosX = healthBar.localPosition.x;
}
void Update()
{
if (targetRole != null)
UpdateBarPos();
}
public void Init(Transform role)
{
targetRole = role;
UpdateBarPos();
}
Vector3 healthBarPos = Vector3.zero;
Vector3 healthBarScale = Vector3.one;
public void OnHealthChanged(float healthPercent)
{
if (healthPercent < 0)
healthPercent = 0;
if (healthPercent > 1)
healthPercent = 1;
//修改位置和縮放,實現血條效果
healthBarPos.x = healthBarInitPosX * (1 - healthPercent);
healthBar.localPosition = healthBarPos;
healthBarScale.x = healthPercent;
healthBar.localScale = healthBarScale;
}
void UpdateBarPos()
{
//刷新朝向,始終朝向相機
transform.forward = mainCamera.transform.forward;
//刷新位置
transform.position = Vector3.Lerp(transform.position, targetRole.transform.position + posOffset, followSpeed);
}
}