1. 程式人生 > 其它 >3D遊戲程式設計與設計 作業九

3D遊戲程式設計與設計 作業九

血條(Health Bar)的預製設計

專案要求

血條(Health Bar)的預製設計。具體要求如下

  • 分別使用 IMGUI 和 UGUI 實現
  • 使用 UGUI,血條是遊戲物件的一個子元素,任何時候需要面對主攝像機
  • 分析兩種實現的優缺點
  • 給出預製的使用方法

IMGUI實現

IMGUI比較簡單,使用GUI.HorizontalScrollbar來實現,其他要做的只是計算出HorizontalScrollbar的位置和大小

    //初步計算血條位置
    Vector3 worldPos = new Vector3(transform.position.x, transform.position.y -
0.2f, transform.position.z); Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);

因為IMGUI不會隨著物體移動,HorizontalScrollbar大小自然也不會隨著遠近變化,我簡單計算人物與攝像機的距離,隨著距離增大減少
這裡只是簡單模擬,所以設計的公式是 1 1 + d i s t a n c e \frac{1}{1+distance} 1+distance1

    //計算血條大小比例
    float distance = (transform.position.z - Camera.
main.transform.position.z - 10); float newScale = (distance < 0 ? 1 : 1 / (1 + distance)) * 0.5f;

最後用計算的位置和大小比例生成HorizontalScrollbar即可

    GUI.HorizontalScrollbar(new Rect(new Rect(screenPos.x - 100*newScale, screenPos.y, 200*newScale, 20*newScale)), 0.0f, health, 0.0f, 1.0f);

完整程式碼:

public class HealthBar
: MonoBehaviour { public float health = 0.5f; void OnGUI() { //初步計算血條位置 Vector3 worldPos = new Vector3(transform.position.x, transform.position.y -0.2f, transform.position.z); Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos); //計算血條大小比例 float distance = (transform.position.z - Camera.main.transform.position.z - 10); float newScale = (distance < 0 ? 1 : 1 / (1 + distance)) * 0.5f; //生產HorizontalScrollbar GUI.HorizontalScrollbar(new Rect(new Rect(screenPos.x - 100*newScale, screenPos.y, 200*newScale, 20*newScale)), 0.0f, health, 0.0f, 1.0f); } }

UGUI World Place實現

使用UGUI World Place實現血條的過程與課程部落格提供的一致

  • 選單 Assets -> Import Package -> Characters 匯入資源
  • 在層次檢視,Context 選單 -> 3D Object -> Plane 新增 Plane 物件
  • 資源檢視展開 Standard Assets :: Charactors :: ThirdPersonCharater :: Prefab
  • 將 ThirdPersonController 預製拖放放入場景,改名為 Ethan
  • 檢查以下屬性
    • Plane 的 Transform 的 Position = (0,0,0)
    • Ethan 的 Transform 的 Position = (0,0,0)
    • Main Camera 的 Transform 的 Position = (0,1,-10)
  • 執行檢查效果
  • 選擇 Ethan 用上下文選單 -> UI -> Canvas, 新增畫布子物件
  • 選擇 Ethan 的 Canvas,用上下文選單 -> UI -> Slider 新增滑條作為血條子物件
  • 執行檢查效果
  • 選擇 Ethan 的 Canvas,在 Inspector 檢視
    • 設定 Canvas 元件 Render Mode 為 World Space
    • 設定 Rect Transform 元件 (PosX,PosY,Width, Height) 為 (0,2,160,20)
    • 設定 Rect Transform 元件 Scale (x,y) 為 (0.01,0.01)
  • 執行檢查效果,應該是頭頂 Slider 的 Ethan,用鍵盤移動 Ethan,觀察
  • 展開 Slider
    • 選擇 Handle Slider Area,禁灰(disable)該元素
    • 選擇 Background,禁灰(disable)該元素
    • 選擇 Fill Area 的 Fill,修改 Image 元件的 Color 為 紅色
  • 選擇 Slider 的 Slider 元件
    • 設定 MaxValue 為 100
    • 設定 Value 為 75

給 Canvas 新增以下指令碼 LookAtCamera.cs

using UnityEngine;

public class LookAtCamera : MonoBehaviour {

	void Update () {
		this.transform.LookAt (Camera.main.transform.position);
	}
}

UGUI Srceen Space - Overlay實現

如果只用UGUI World Place實現我感覺這次作業不像是我做的,而是直接跟著做,所以就試著做了一個UGUI Srceen Space - Overlay版本,其實這個版本和IMGUI很像,也算是將它當作IMGUI來做,但是現在血條是一個物件
預製體制作與UGUI World Place一致
首先計算血條位置

    //計算healthBar位置
    Vector3 worldPos = new Vector3(transform.position.x, transform.position.y + 1.8f, transform.position.z);
    Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
    healthBar.transform.position = new Vector3(screenPos.x, screenPos.y, screenPos.z);

然後計算血條比例,任然使用 1 1 + d i s t a n c e \frac{1}{1+distance} 1+distance1

    //計算scale比例  
    float distance = (transform.position.z - Camera.main.transform.position.z - 10);
    float newScale = (distance<0?1: 1/(1+distance)) *0.5f;
    healthBar.transform.localScale = new Vector3(newScale, newScale, 1);

完整程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class OverlayHealthBar : MonoBehaviour
{
    private Slider healthBar;
    void Start()
    {
        healthBar = GetComponentInChildren<Slider>();
    }

    void Update()
    {
        //計算healthBar位置
        Vector3 worldPos = new Vector3(transform.position.x, transform.position.y + 1.8f, transform.position.z);
        Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
        healthBar.transform.position = new Vector3(screenPos.x, screenPos.y, screenPos.z);
        //計算scale比例  
        float distance = (transform.position.z - Camera.main.transform.position.z - 10);
        float newScale = (distance<0?1: 1/(1+distance)) *0.5f;
        healthBar.transform.localScale = new Vector3(newScale, newScale, 1);
    }
}

效果

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

優缺點分析

  • IMGUI
    優點:

    • 使用方便,上手容易
    • 沒有狀態,維護方便

    缺點:

    • 效率低下,每次都需要重新生成所有元件
    • 沒有狀態,配置不夠靈活,實現運動、動畫等比較麻煩
  • UGUI
    優點:

    • 擁有UI狀態,可以比較方便的修改其屬性或進行其他操作(運動等)
    • 錨點的存在可以實現位置自適應
    • 每次生命週期不需要重複遍歷一次UI元件,效率較高
      缺點:
    • 使用比較繁瑣、對不同的功能需要提供不同的canvas,並單獨配置

預製使用方法

使用比較簡單,直接將指令碼拖入Ethan中即可(lookAtCamera除外)