3D遊戲程式設計與設計 作業九
阿新 • • 發佈:2020-12-28
血條(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除外)