3D遊戲程式設計作業9

weixin_43953962發表於2020-12-26

作業目標

  • 血條(Health Bar)的預製設計。具體要求如下:
    • 分別使用 IMGUI 和 UGUI 實現
    • 使用 UGUI,血條是遊戲物件的一個子元素,任何時候需要面對主攝像機
    • 分析兩種實現的優缺點
    • 給出預製的使用方法

實現過程

1、人物狀態

為了方便後面不同GUI設計時獲取人物血量,我先為角色設計了一個指令碼,記錄了角色的總血量、當前血量以及改變後的血量,同時設計好了受到傷害和回血的函式呼叫。

public class Health : MonoBehaviour {
    public float currentHP;
    public float nextHP;
    public float fullHP = 100;

    private void Start () {
        currentHP = fullHP;
        nextHP = fullHP;
    }

    private void Update () {
        currentHP = Mathf.Lerp (currentHP, nextHP, 0.05f);
    }

    public void Hurt () {
        nextHP = (currentHP - 10) >= 0 ? currentHP - 10f : 0;
    }

    public void Recover () {
        nextHP = (currentHP + 10) <= 100 ? currentHP + 10f : 100;
    }
}

在使用時,將Health指令碼掛載在角色上就好了。

2、IMGUI實現

IMGUI是我最常用的一種實現UI的方式(好像之前也只用了這一種),是通過OnGUI函式來設計UI介面佈局。
而要使用IMGUI來製作血條的話,我們需要用到其HorizontalScrollbar函式來設計滾動條,具體使用方法可以檢視指令碼API的介紹。

[RequireComponent (typeof (Health))]
public class IMGUI : MonoBehaviour {
    private GameObject character;
    private float currentHP;
    private float fullHP;

    private void Start () {
        character = this.gameObject;
    }

    private void OnGUI () {
        if (GUI.Button (new Rect (20, 20, 80, 40), "Hurt")) {
            character.GetComponent<Health> ().Hurt ();
        }

        if (GUI.Button (new Rect (120, 20, 80, 40), "Recover")) {
            character.GetComponent<Health> ().Recover ();
        }

        currentHP = character.GetComponent<Health> ().currentHP;
        fullHP = character.GetComponent<Health> ().fullHP;

        GUI.HorizontalScrollbar (new Rect (20, 100, 180, 20), 0, currentHP, 0, fullHP);
    }
}

在使用時,將IMGUI.cs掛載到角色上,執行後就可以看到左上角出現了Hurt、Recover兩個按鈕和代表血量的滑動條了。

3、UGUI實現

UGUI的實現在課本中已經有具體描述了,這裡稍微修改了一點內容,使得血條更符合我們的認知。

  • 選單 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

    • 選擇 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);
	}
}

而修改內容為:

  1. background重新勾上,不再禁灰
  2. 分別將background、Fill Area以及Fill Area的Fill這三個資源的Reac Transform元件(Left, Top, Right, Buttom)設定為(0, 0, 0, 0)

為了獲取人物的屬性,我又設計了UGUI.cs指令碼,在獲取人物血量的同時,借用了IMGUI的OnGUI設計了Hurt和Recover兩個按鈕,便於我們檢視血量的變化。

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

namespace HealthBar {
    public class UGUI : MonoBehaviour {
        public GameObject character;

        private void Start () {
            this.gameObject.GetComponent<Slider> ().maxValue = character.GetComponent<Health> ().fullHP;
        }

        private void Update () {
            this.gameObject.GetComponent<Slider> ().value = character.GetComponent<Health> ().currentHP;
        }

        private void OnGUI () {
            if (GUI.Button (new Rect (20, 20, 80, 40), "Hurt")) {
                character.GetComponent<Health> ().Hurt ();
            }

            if (GUI.Button (new Rect (120, 20, 80, 40), "Recover")) {
                character.GetComponent<Health> ().Recover ();
            }
        }
    }
}

4、使用方法

4.1 IMGUI

IMGUI的相關內容使用很簡單,只需要將Health指令碼和IMGUI指令碼掛載到人物上,就可以了。

4.2 UGUI

UGUI的內容稍微複雜一些,Health指令碼仍然是掛載在人物上的,但是UGUI指令碼則不是掛載在人物上,而是掛載在Slider資源上,同時需要將UGUI的Character選擇為我們的人物(Ethan)。
在這裡插入圖片描述

效果展示

我將兩個設計好的場景分別儲存命名為IMGUI和UGUI,直接開啟對應的場景便能執行對應的實現方式。

1、IMGUI

在這裡插入圖片描述

2、UGUI

在這裡插入圖片描述

兩種實現方式的優缺點

1、IMGUI

優點

  • 如果不做複雜的介面,程式碼簡單易用
  • 在修改模型,渲染模型這樣的經典遊戲迴圈程式設計模式中,在渲染階段之後,繪製 UI 介面無可挑剔
  • 避免了 UI 元素保持在螢幕最前端,又有最佳的執行效率,一切控制掌握在程式設計師手中,這對早期計算和儲存資源貧乏的遊戲裝置來說,更是彌足珍貴。

缺點

傳統程式碼驅動的 UI 開發效率低下,難以除錯。

2、UGUI

優點

  • 所見即所得(WYSIWYG)設計工具,設計師也能參與程式開發
  • 支援多模式、多攝像機渲染
  • UI 元素與遊戲場景融為一體的互動
  • 物件導向的程式設計

缺點

程式碼地址

【傳送門】

相關文章