【Unity3d學習】UI系統——簡單的血條製作

寫在前面

  • 本次項目較爲簡單,代碼上傳到GitHub上:Github傳送門
  • 課程實驗資料在老師的課程網站上:傳送門
  • 實驗的視頻鏈接(本次實驗演示較簡短):傳送門

實驗內容

實現簡單血條預製:

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

步驟分析:
首先IMGUI在之前的實驗中也有用到,主要是用來設置開始遊戲和結束遊戲的界面。實現方法是在onGUI函數中添加相應的控件(Label、Button等),也就是說每次都調用onGUI都會刷新一次所有控件。
而UGUI是課上新接觸的UI設計工具。主要設計可以通過鼠標拖拽、設置屬性等方式,在二維平面上完成UI設計,即時能夠看到效果。換句話說可以不通過代碼就能實現一定的UI效果。

分析完兩者的一些區別之後就開始動手實現了。

IMGUI製作簡單血條

由於IMGUI主要是通過代碼來實現UI,所以也沒有說需要建立模型什麼的,調整位置也是靠代碼控制xy座標來實現。所以直接上代碼:

public class IMGUIhealth : MonoBehaviour
{
    public float value;
    private float tmp;
    
    // Start is called before the first frame update
    private void OnGUI()
    {
    	// 加號按鈕,點擊時增加血量,每次增加十分之一
        if (GUI.Button(new Rect(450, 50, 40, 40), "+"))
        {
            tmp += 10;
            if (tmp > 100)
                tmp = 100;
        }
		// 減號按鈕,點擊時減少血量,每次減少十分之一
        if (GUI.Button(new Rect(100, 50, 40, 40), "-"))
        {
            tmp -= 10;
            if (tmp < 0)
                tmp = 0;
        }
		// 線性插值,使得變化更平滑
        value = Mathf.Lerp(value, tmp, 0.05f);
	
		// 使用HorizontalScrollbar作爲血條主體,利用value來控制血量多少
        GUI.color = Color.red;
        GUI.HorizontalScrollbar(new Rect(200, 50, 200, 20), 0, value, 0, 100);
        
    }
}

代碼主要添加了三個控件:兩個Button負責加減血量,一個水平滾動條負責顯示血量。
Button的用處就不講了,之前實踐過很多次了,對於HorizontalScrollbar來說,是第一次接觸,所以看下官方文檔:
在這裏插入圖片描述
大概理解一下各個參數的意思:

Parameter 意義
position 整個滾動條的位置和大小
value 滾動條的那一個滑塊的位置
size 滑塊大小(長度)
leftValue 最小值
rightValue 最大值
style 滾動條的樣式

翻譯了一遍,但是對於某些部分還是有點不理解,就拿現成的例子說明以下:
在這裏插入圖片描述
箭頭所指爲滑塊,可以知道我們滾動移動的時候改變的是滑塊的位置。對於不同的網頁,滑塊的長度會不一樣:
在這裏插入圖片描述
基於這個想法,我們可以利用滑塊的長度作爲血條現有血量的多少,將滑塊的位置固定在0端,也就是最左端(最小值處),改變滑塊的長度(0~100)來顯示血量的變化。
所以有了以下的這一句代碼:

GUI.HorizontalScrollbar(new Rect(200, 50, 200, 20), 0, value, 0, 100);

其中Rect後的第一個數字0,表示滑塊的當前位置,0就是最左邊。value就是當前血量,也就是對應着滑塊長度。
最後將腳本掛載到攝像機上!

顯示效果(靜態):
在這裏插入圖片描述
(注:其實有一個控件是HorizontalSlider水平滑動條,但是由於沒有滑塊的大小,所以顯示不出血量的變化,相比之下HorizontalScrollbar更加適合血條的樣式)

UGUI設計血條預製

UGUI是爲了讓設計師能夠直接參與UI設計而產生的,所以UGUI有一個設計界面,有所見即所得的方便之處。所以不同於代碼編程,用UGUI設計出來會得到一個模型,也就是我們的遊戲對象,所以可以將其變爲預製,使用的時候直接拖入場景中進行實例化使用。
參考老師課程網站上的教程進行UGUI血條預製:

  1. 首先創建一個Canvas對象作爲UGUI控件的一個載體,並且取名爲Health.然後在這個載體裏面添加一個Slider.對象結構如下:
    在這裏插入圖片描述
    Slider下的子對象是自動生成的不需要手動添加。

  2. 設置 Canvas 組件 Render Mode 爲 World Space
    設置 Rect Transform 組件 (PosX,PosY,Width, Height) 爲 (0,2,160,20)
    設置 Rect Transform 組件 Scale (x,y) 爲 (0.01,0.01):
    在這裏插入圖片描述

  3. 由於我們不需要拖動Slider,所以把Handle Slide Area禁用掉,至於Background可以禁可以不禁,不禁的話就可以當空血槽,效果也不錯,看個人喜歡。然後更改fill的屬性值,在Image的部件中找到color一項,改變它的顏色:
    在這裏插入圖片描述
    然後在Scene界面點擊2D的按鈕,可以直觀看到效果:
    在這裏插入圖片描述
    一個綠色的長條就製作完成了。

  4. 改變Slider的屬性:
    設置 MaxValue 爲 100
    設置 Value 爲 75 :
    在這裏插入圖片描述
    可以看到缺了一部分。如果加上background,會看的更明顯:
    在這裏插入圖片描述

  5. 下面給他添加一個腳本。
    由於它會隨着物體轉動而轉動,所以需要讓其時時刻刻都保持面向攝像頭,然後自己給他添加了一點顏色改變的邏輯,當血量少到一定程度就會變黃再變紅。還做了一個讓血條自己變化的一個函數(因爲血條量可以通過Slider的Inspetor的slider部件改變,所以這裏就沒有做一個加減血量的按鈕)。

public class HealthBar : MonoBehaviour {

    public Slider slider;
    float factor = 0.1f;
    public bool active = true;
    private int turn = 1;
    private void Start()
    {
    }
	
    void change() {
        if (turn == 1)
            slider.value -= 1f;
        else 
            slider.value += 1f;
        if (slider.value <= 0) {
            slider.value = 0;
            turn = 2;
        }
        if (slider.value >= 100) {
            slider.value = 100;
            turn = 1;
        }
    }
    void Update () {
		this.transform.LookAt (Camera.main.transform.position);
        if (active)
            change();
        Color current = slider.fillRect.transform.GetComponent<Image>().color;
        if (slider.value <= 20) {
            slider.fillRect.transform.GetComponent<Image>().color = Color.Lerp(current, Color.red, factor);
        }
        else if (slider.value <= 70) {
            slider.fillRect.transform.GetComponent<Image>().color = Color.Lerp(current, Color.yellow, factor);
        }
        else {
            slider.fillRect.transform.GetComponent<Image>().color = Color.Lerp(current, Color.green, factor);
        }
	}
}

最後將腳本拖到Heath的畫布上面去,將Slider拖入腳本的slider變量中去,完成腳本與Slider的綁定。Active是選擇是否讓其自動變化。
在這裏插入圖片描述
將其拖到一個物體Cube上,觀察效果:
(看到效果,我們可能會發現,血條的左右是反的?就是會從右邊開始增加減少,這時候只需要稍微設置一下slider的方向即可,因爲實際上我們創建Slider的時候,他的Z軸是朝向正方向的,也就是說他的正方向恰好的背對着攝像頭,這時候我們看到的效果纔是正常的,但是如果設置了LookatCamera,那麼就會出現了相反的效果,這時候我們可以通過設置他的方向來調整,這個可能實現方法不同效果不太一樣,根據實際情況進行調整)
在這裏插入圖片描述
在這裏插入圖片描述
拖動Slider的slider部件中的value選項:
在這裏插入圖片描述
就可以看到血條在變化。

動態效果展示

IMGUI:
在這裏插入圖片描述
UGUI:
在這裏插入圖片描述

兩種製作的優缺點

IMGUI優缺點分析

優點:

  • 編程實現,符合遊戲編程的傳統。
  • 避免了 UI 元素保持在屏幕最前端,又有最佳的執行效率,一切控制掌握在程序員手中。對於簡單UI的製作十分有好處。
  • 對新手友好,入門容易,同時幫助理解遊戲引擎渲染的調用函數
    缺點:
  • 編程實現既是優點,也是缺點,無法直觀看到UI佈局情況,需要使用代碼一點一點更改位置
  • 渲染在屏幕最前端,所以簡單的實現只能夠用於初始界面、結束界面等的設計,如果想要映射到遊戲場景中去,還需要實現更加複雜的大小、位置映射關係,非常麻煩。(IMGUI系統通常不打算用於玩家可能使用並與之交互的普通遊戲內用戶界面IMGUI系統通常不打算用於玩家可能使用並與之交互的普通遊戲內用戶界面)

UGUI優缺點分析

優點:

  • 能夠讓設計師也參與到遊戲製作中去,直接利用界面設計UI,所見即所得。
  • UI 元素與遊戲場景融爲一體的交互,支持複雜的佈局,功能更加強大!
  • 面向對象的編程,每個控件都是一個對象,通過對其加減Component或者改變屬性可以實現不同的效果。

缺點:

  • 功能強大的同時也意味着它的操作性要更強,許多設計技巧和方法都需要查閱大量資料去學習。
  • 同時性能是個十分值得考慮的問題!

預製使用方法

  1. 新建一個物體(方塊什麼的,能看到形狀的),然後從預製文件夾中找到對應的預製Health,將其拖到一個物體上,使其成爲該物體的子對象。(當然也可以直接將預製拖到場景中,單獨查看血條的效果)
    在這裏插入圖片描述
  2. 將Slider拖入腳本的slider變量中去,完成腳本與Slider的綁定(如果還沒有賦值的話)。Active是使血量自動循環變化,不喜歡可以關掉。
    在這裏插入圖片描述
  3. 開始運行遊戲!即可看到效果,可以手動改變value的值來顯示變化。
    在這裏插入圖片描述

本次實驗到此完成!

更新

提出一點方案建議,沒來得及研究實現。
根據參考資料:Faking World Space for monster health bars in Unity

如果你在生產中使用上述血條,足以證明你是入門級別程序員。爲了顯示血條,每個圖片從 pixel 單位映射到 world space,再投影到攝像機空間,在變成屏幕空間(pixel 單位)這需要多少算力?
因此,能用 Srceen Space 解決的問題絕不用 World Space, 能用 Overlay 解決問題絕不用 Camera!

由於使用World Space會降低性能,這個例子中是用到Canvas 組件 Render Mode 爲Screen Space - Overlay來實現的。所以會需要一個從worldSpace到屏幕的映射關係,主要有z軸(攝像機朝向)對應深度信息,xy對應xy
在這裏插入圖片描述
在這裏插入圖片描述
完成一個從三維控件到屏幕平面座標的映射。

解決血條暴露行蹤問題

在該例子中也給出了明確的方案:
在這裏插入圖片描述
可以根據這個例子來學習UGUI更多知識!再放一遍鏈接:
Faking World Space for monster health bars in Unity

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章