我們常在遊戲中的環境看到角色會有血條,這讓我很好奇Canvas,或一些UI是如何顯示在World上。所以我今天將研究在一個環境中顯示當前的血量,並且透過Slider來作為我們血量的控制與顯示,並且根據生命值數值來變更Slider的顏色,同時分享一下如何將我們的Canvas 持續的面向鏡頭。接下來就透過簡單的實作來說明。未來也可以基於該方法使用在Oculus中。就讓我們開始吧!
首先新增一個空物件 Empty gameObject,名稱為 Player。接著也新增一個地板 Plane。
並且新增一個腳本 HealthBar 到內部中。
接下來新增一個 image上去,本身系統會新增Canvas 與 EventSystem。接下來 reset 原本的位置。
接著去調整該Image 的長寬。 width and height
接下來在 Canvas 內部新增一個 Empty Object。改名成 HealthBar,並將其 Width 與 height 調整成對的大小。
把剛剛的 Image (Border) 放進去成為子物件。這邊有更改原本Border 的顏色。
在 HealthBar 下方在新增一個新的 Image ,並且改名成 Fill。
後續對調與Border,上下關係代表著在環境中UI顯示的前後關係
調整 Fill 中右方 Rect Transform 中的 stretch,我們壓著鍵盤ALT,點選最右下角的方向
接下來就會變成這樣:
取消勾選 Interactable ,將 Transition, Navigation 將其設定成 None
最後將我們的 Fill 放進到我們上面的 Fill Rect
目的是為了可以調整其 Value 實現類似該Health Bar 的結果,這邊注意到若點選 Slider的 Whole Numbers 點選後變成以整數進行增加減少。
這樣設定的目的就是為了要讓該物件可以隨著HealthBar 的大小變動
如果我們點選 Whole Number 則每次顯示的結果就會是以整數增加或減少。這邊不要勾選
接下來在 healthbar 中去新增腳本 HealthBar scripts。
撰寫初步程式碼,主要是設定該 healthBar 的數值。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HealthBar : MonoBehaviour
{
public Slider healthSlider;
public void setHealth(int _health)
{
healthSlider.value = _health;
}
}
回到 Unity 中去將我們的Slider 拉到環境中。
新增該程式碼 void SetMaxValue( ) ,接下來就可以將其放置在任何的物件上了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HealthBar : MonoBehaviour
{
public Slider healthSlider;
public void setHealth(int _health)
{
healthSlider.value = _health;
}
public void setMaxHealth(int _health)
{
healthSlider.value = _health;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public Transform ground;
public float rotateSpeed = 20f;
public int currentHealth;
public int MaxHealth = 100;
public HealthBar healthBar;
void Start()
{
healthBar.setHealth(MaxHealth);
currentHealth = MaxHealth;
}
void Update()
{
// rotate the ground
ground.RotateAround(Vector3.zero, Vector3.up, rotateSpeed * Time.deltaTime);
// get damage
if(Input.GetKeyDown(KeyCode.Space))
{
takeDamage(20);
}
}
void takeDamage(int _damage)
{
currentHealth -= _damage;
healthBar.setHealth(currentHealth);
}
}
回到 Unity 將我們的 HealthBar 拉近到我們 Player 的文本中。並且將該 HealthBar 的 MaxValue 設定為 100。
實際測試會發現到該HealthBar 隨我觸發 Space 後遞減。
public Gradient gradient;
Mode 要設定成 Fixed
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HealthBar : MonoBehaviour
{
public Slider healthSlider;
public Gradient gradient;
public Image fill;
public void setHealth(int _health)
{
healthSlider.value = _health;
fill.color = gradient.Evaluate(healthSlider.normalizedValue);
// because gradient is 0~1
}
public void setMaxHealth(int _health)
{
healthSlider.maxValue = _health;
healthSlider.value = _health;
fill.color = gradient.Evaluate(1f);
}
}
最後把 fill image 拉到該 HealthBar 當中。
接下來就可以執行看看。
首先建立一個環境。
接下來改變該 bar 在環境中顯示的位置,也就是在 Canvas 中的位置。
首先將該Canvas 中的 Render Mdoe 設定成 World Space
後續調整該 Canvas 的Scale大小。與將其位置設回到原點。我們就會看到該Health Bar 會出現在物件上面。
接著將其 Canvas 向下移動,在 HealthBar 中按下 ALT並點選中間在 Canvas 的相對位置。
接下來將其放置到 Player 的身上去。 就可以難看到 Canvas 隨著該Player 的方向更改其方向
我們在 Canvas 上面去新增一個 Scripts 叫做 Billboard.cs。
接下來撰寫該程式碼,也就是希望該 Camera 持續面向該 Health Bar 。使用 LookAt 來達成。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BillBoard : MonoBehaviour
{
public Transform cam;
void LateUpdate() {
transform.LookAt(transform.position + cam.forward);
}
}
回到 Unity 將我們的 camera 拉近到我們設定的 camera 中。
執行後就會發現該結果會一直面向我們的鏡頭。 最後就完成了 HealthBar。透過將我們的Cube 移動看看 Bar持續面對 User 的效果!
gradient.Evaluate(healthSlider.normalizedValue)