iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0

最近幫學長做實驗發現學長製作的環境中都會有一個圓圈形成的進度條,方便我知道要維持某一個姿勢或是動作多久才算完成。這邊我請教學長後也試著實作一下,或許未來在實驗中也可能會使用到。那這邊我會以假裝頭戴HMD,看到某一個Target 物件就開始累積進度條的數值,並且透過兩個同樣是Circle Image 的方式顯示目前進度,我個人覺得很有趣XD。

今天也會使用到 Debug.DrawRay 結合 RaycastHit 來確認當前是否有觸發到物件,並改變該Ray 的樣貌。讓我們開始吧。

建置環境

  1. 首先創建一個 Sphere 並且改名為 User,接著去設計一下外觀。如下類似一個人帶著 HMD。

  2. 接下來我們新增一個文本,LookAtCheck.cs。新增到該User 的Inspector中。

  3. 接著設定幾個 Target Object 在User 的前方。

開始撰寫文本

  1. 首先我會希望知道User 當前的視角,所以我會透過 RaycastHit 來了解。將撰寫從User會產生一個Demo 的射線,若射線接觸到物件顯示為黃色並指向該物件上,沒有觸碰到任何物件就顯示成白色的。
void gazeHit()
    {
        RaycastHit hit;
        if(Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity))
        {
            Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);
            Debug.Log("Hit something!");
        }else{
            Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 1000, Color.white);
            Debug.Log("Hit nothing!");
        }
    }
  1. 回到 Unity 後記得要注意到開啟Scene 右上角的 Gizmos,若沒開啟就無法出現我們需要的射線樣式。

  2. 接下來你就可以在執行的過程中看到 Scene 出現一條很細的線。

若接觸到任何物件就會顯示成黃色的。

  1. 開始製作進度條。首先我們在Scene 中新增一個Canvas,並且在其內新增一個空白物件 SelectionCircle,最後設計兩個同樣是 Circle 但是不同顏色的 Image。 nonSelecCircle 是尚未選取的時候,selectCircle 就是我要設計當選取後進度條顯示的樣子。

讓 Image 成為進度條的樣式

  1. 首先到 Unity 選擇我們的 selectCircle,看到 Inspector 的地方調整成入下的樣子。最重要的地方就是請將Image Type 設定成 Filled。

  2. 接下來新增一個文本 FilledCircle.cs 到我們 SelectionCircle 空白物件中。

  3. 開始撰寫該 FilledCircle 文本,這邊宣告一個 public 計數的函數,如果說當Ray 射線觸發到某個物件的時候就會每秒進行累積,我這邊設定 5f就是進度條累積到全滿會需要 5 秒的時間。

public  void filledCircle(){
        if(filledT < 5f)
        {
            filledT += Time.deltaTime;
        }
    }
  1. 累積該 Red Circle 的方式就需要使用Image內建的 fillAmount,被 filledT 給指定顯示累積。
redCircleFilled.GetComponent<Image>().fillAmount = filledT;
  1. FilledCircle.cs 整體的程式碼
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class FilledCircle : MonoBehaviour
{
    public float filledT = 0f;
    public GameObject redCircleFilled;

    void Update() 
    {
        redCircleFilled.GetComponent<Image>().fillAmount = filledT;
        
    }


    public  void filledCircle(){
        if(filledT < 5f)
        {
            filledT += Time.deltaTime;
        }else{
            Debug.Log("Success to select!");
        }
    }
}
  1. 回到 Look.AtCheck.cs 去更改一些部分。當Ray 指向,也就是當User 看到某個Target 的時候會開始累積 RedCircle 的 Image。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class LookAtCheck : MonoBehaviour
{
    RaycastHit hit;
    public float circleFilled = 0f;
    public FilledCircle redcircle;
    


    void Update()
    {
        
        gazeHit();

    }

    void gazeHit()
    {
        RaycastHit hit;
        if(Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity))
        {
            Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);
            redcircle.filledCircle();
            //Debug.Log("Hit something!");
        }else{
            Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 1000, Color.white);
            redcircle.filledT = 0f;
            //Debug.Log("Hit nothing!");
        }
    }
}
  1. 執行結果如下,
  • 沒有看到任何物件或離開Target 目標時不會累積。

  • 看到物件時中央的Red Circle 開始累積

結論

  1. 通常我們使用進度條基本是使用 Slider 作為我們進度條的樣式,但在這邊也可以透過兩個不同顏色的 Image 來顯示該進度條的樣式。
  2. 若要使用Image 進度條就需要想到更改 Image 中本身 Image Type 要變成 Filled 填滿的型態。
  3. 今天也使用到 Scene 的 Gizmo,若沒有開啟 Gizmo 則無法看到任何該 DebugRay 的使用。
  4. 這個實作其實也很好應用於在當人戴上HMD觀看視角的特性,幫助我們知道該User 轉動的方向與角度,最後並應用在其他互動上。

上一篇
Day9: Teleport in VR
下一篇
Day11: Understand Collision and Trigger
系列文
Unity 基本功能實作與日常紀錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言