1. 程式人生 > >Htc Vive入門之凝視效果(眼神殺,遇神殺神,遇佛殺佛)

Htc Vive入門之凝視效果(眼神殺,遇神殺神,遇佛殺佛)

瞅我幹嘛?瞅你咋的?誰惹我,我盯誰,盯誰殺誰。神擋殺神,佛擋殺佛。--------眼神殺,htc vive的凝視效果

1、刪除場景中的maincamera,建立一個Plane並設定屬性


2、建立一個cube並設定相關屬性



3、建立一個Canvase並設定相關屬性


4、建立一個Button,作為Canvase的子物體,並設定相關屬性



5、將SteamVR Plugins匯入到unity,然後將CameraGig拖動到Hierarchy檢視並設定相關屬性


6、建立一個Canvas,作為Camera(eye)的子物體並設定相關屬性


7、建立一個Image,作為Canvase的子物體,用來存放準星,並設定相關屬性


8、再建立一個Image,作為上一步的image的子物體,用來存放準星的半透明的背景,並設定相關屬性


9、建立兩個指令碼,GazeController掛載到Camera(eye)上,VRGazeItem分別掛載到cube和button上

碰撞到物體,將準星移動到視線接觸到的位置,準星與物體垂直,並且進度條根據計時更改進度



②如果是視線第一次看見這個物體,並且物體身上有凝視元件,進行凝視操作


cube凝視進入時變成藍色,button凝視時執行虛擬滑鼠進入的方法,button設定了在滑鼠進入時的藍色背景,所以凝視時顯示變成藍色



如果眼神接觸另一個物體前,上一個物體上有凝視元件,則進行移出操作,視線從button上離開時,button執行滑鼠移出的方法,變成正常色,視線從cube上離開時,cube也變成正常的白色



10、當視線在物體上停留時,進行凝視操作。button消失,cube作用一個力,進行移動

凝視前cube的位置


凝視時cube的右邊那個角被擡高了


凝視前button的位置


凝視後button消失


11、VRGazeItem.cs的程式碼

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class VRGazeItem : MonoBehaviour {

    //高亮材質
    public Material highlightMat;
    //正常材質
    public Material normalMat;

	
	void Start () {
		
	}
	
	
	void Update () {
		
	}

    //視線移入處理函式
    public void GazeIn()
    {
        if(gameObject.tag == "GazeUI")
        {
            //滑鼠移入的效果
            ExecuteEvents.Execute(gameObject,new PointerEventData(EventSystem.current),ExecuteEvents.pointerEnterHandler);
        }else if(gameObject.tag == "GazeObj")
        {
            //給cube新增高亮時變成藍色
            gameObject.GetComponent<Renderer>().material = highlightMat;
        }

    }

    //視線移出處理函式
    public void GazeOut()
    {
        if (gameObject.tag == "GazeUI")
        {
            //滑鼠移入的效果
            ExecuteEvents.Execute(gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerExitHandler);
        }
        else if (gameObject.tag == "GazeObj")
        {
            //cube變成正常的顏色
            gameObject.GetComponent<Renderer>().material = normalMat;
        }
    }

    //視線啟用處理函式
    public void GazeFire(RaycastHit hit)
    {
        if (gameObject.tag == "GazeUI")
        {
            //隱藏物體
            gameObject.SetActive(false);
        }
        else if (gameObject.tag == "GazeObj")
        {
            //給物體cube作用一個力
            gameObject.GetComponent<Rigidbody>().AddForceAtPosition(hit.point.normalized*100,hit.point);
        }

    }
}
12、GazeController.cs的程式碼
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GazeController : MonoBehaviour {

    //準星容器
    public Canvas reticleCanvas;
    //準星
    public Image reticleImage;
    //擊中的當前目標
    public GameObject target;
    //初始位置
    private Vector3 originPos;
    //初始縮放
    private Vector3 originScale;
    //倒計時時間
    private float countDownTime = 3;
    //當前時間
    private float currentTime = 0;

	// Use this for initialization
	void Start () {
        reticleImage.fillAmount = 0;
        //記錄初始位置
        originPos = reticleCanvas.transform.localPosition;
        //記錄初始縮放
        originScale = reticleCanvas.transform.localScale;
	}
	
	// Update is called once per frame
	void Update () {
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hit;
        //如果碰撞到了物體
        if (Physics.Raycast(ray, out hit, 50))
        {
            //將碰撞的位置賦給準星
            reticleCanvas.transform.position = hit.point;
            //根據距離進行縮放,補償在3d世界中近大遠小的情況
            reticleCanvas.transform.localScale = originScale * hit.distance;

            //讓準星與碰撞的物體垂直通過讓準星與擊中點法線方向一致
            reticleCanvas.transform.forward = hit.normal;
            //視線初次進入
            if (hit.transform.gameObject != target)
            {
                //如果上次的目標物體不為空,進行移出的操作
                if (target != null)
                {
                    VRGazeItem oldItem = target.GetComponent<VRGazeItem>();
                    if (oldItem)
                    {
                        oldItem.GazeOut();
                    }
                }

                //將擊中的目標賦給當前的目標物體
                target = hit.transform.gameObject;
                //獲取物體上的凝視元件
                VRGazeItem newItem = target.GetComponent<VRGazeItem>();
                //如果有凝視元件
                if (newItem)
                {
                    //凝視
                    newItem.GazeIn();
                }
            }
            else//視線在此停留
            {
                currentTime += Time.deltaTime;
                //設定時間未結束
                if (countDownTime - currentTime > 0)
                {
                    //設定進度條
                    reticleImage.fillAmount = currentTime / countDownTime;
                }
                else//達到設定條件
                {
                    currentTime = 0;
                    //如果
                    VRGazeItem gazeFireItem = target.GetComponent<VRGazeItem>();
                    if (gazeFireItem)
                    {
                        gazeFireItem.GazeFire(hit);
                    }
                }
            }
        }
        //沒有碰撞到物體
        else
        {
            reticleCanvas.transform.position = originPos;
            //縮放復位
            reticleCanvas.transform.localScale = originScale;
            //準星方向復位
            reticleCanvas.transform.forward = Camera.main.transform.forward;
            reticleImage.fillAmount = 0;
        }
    }
}


注:1、參考資料:http://edu.manew.com/course/344/learn#lesson/5606

2、遇到的問題:當準星與物體接觸時,不停閃動

原因:unity本身的問題,當兩個物體接觸時,會發生閃動的問題

解決辦法:給物體新增一個shader

①建立一個Matirial,Create-->Material-->重新命名“UIMaterial”


②將“UIOverlay”拖動進unity


③選擇材質UIMaterial,在Shader下拉框選項中選擇UI-->Overlay


④分別為兩個image新增material