【Unity】3D場景角色血條/狀態條

實現方式有很多,看哪種更適合你的項目:

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);
    }

}

 

發佈了98 篇原創文章 · 獲贊 66 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章