一坎匿、為什么要實(shí)現(xiàn)瞬移這個(gè)功能##
因?yàn)镠TC Vive活動(dòng)范圍有限制(3m * 5m)奈惑,所以我們?cè)趯?shí)際的使用中慌申,為了更好的瀏覽場(chǎng)景陌选,查看場(chǎng)景,會(huì)使用這種移動(dòng)的方式蹄溉,達(dá)到游戲中的視野移動(dòng)咨油。
一般來(lái)說(shuō)就是手柄選取一個(gè)位置,通過(guò)扳機(jī)鍵確認(rèn)移動(dòng)柒爵。
移動(dòng)的方式有兩種:一種是水平移動(dòng)即X役电,Z軸移動(dòng);另一種就是垂直移動(dòng),即Y軸移動(dòng)。
二棉胀、實(shí)現(xiàn)過(guò)程##
這瞬移過(guò)程中最重要的是拿到目標(biāo)位置的坐標(biāo)法瑟,我們可以通過(guò)射線檢測(cè)拿到位置.
在Steam VR插件給我們提供了封裝好的類與方法冀膝,我們做出相應(yīng)的改變得到我們需要的結(jié)果.
射線檢測(cè)腳本
重寫代碼展示:
using UnityEngine;
using System.Collections;
//public struct PointerEventArgs
//{
// public uint controllerIndex;
// public uint flags;
// public float distance;
// public Transform target;
//}
//public delegate void PointerEventHandler(object sender, PointerEventArgs e);
public class Test_LaserPointer : MonoBehaviour
{
public bool active = true;
public Color color;
public float thickness = 0.002f;
public GameObject holder;
public GameObject pointer;
bool isActive = false;
public bool addRigidBody = false;
public Transform reference;
public event PointerEventHandler PointerIn;
public event PointerEventHandler PointerOut;
public Vector3 HitPoint;//添加的量找到目標(biāo)位置
Transform previousContact = null;
// Use this for initialization
void Start ()
{
holder = new GameObject();
holder.transform.parent = this.transform;
holder.transform.localPosition = Vector3.zero;
holder.transform.localRotation = Quaternion.identity;
pointer = GameObject.CreatePrimitive(PrimitiveType.Cube);
pointer.transform.parent = holder.transform;
pointer.transform.localScale = new Vector3(thickness, thickness, 100f);
pointer.transform.localPosition = new Vector3(0f, 0f, 50f);
pointer.transform.localRotation = Quaternion.identity;
BoxCollider collider = pointer.GetComponent<BoxCollider>();
if (addRigidBody)
{
if (collider)
{
collider.isTrigger = true;
}
Rigidbody rigidBody = pointer.AddComponent<Rigidbody>();
rigidBody.isKinematic = true;
}
else
{
if(collider)
{
Object.Destroy(collider);
}
}
Material newMaterial = new Material(Shader.Find("Unlit/Color"));
newMaterial.SetColor("_Color", color);
pointer.GetComponent<MeshRenderer>().material = newMaterial;
}
public virtual void OnPointerIn(PointerEventArgs e)
{
if (PointerIn != null)
PointerIn(this, e);
}
public virtual void OnPointerOut(PointerEventArgs e)
{
if (PointerOut != null)
PointerOut(this, e);
}
// Update is called once per frame
void Update ()
{
if (!isActive)
{
isActive = true;
this.transform.GetChild(0).gameObject.SetActive(true);
}
float dist = 100f;
SteamVR_TrackedController controller = GetComponent<SteamVR_TrackedController>();
Ray raycast = new Ray(transform.position, transform.forward);
RaycastHit hit;
bool bHit = Physics.Raycast(raycast, out hit);
if(previousContact && previousContact != hit.transform)
{
PointerEventArgs args = new PointerEventArgs();
if (controller != null)
{
args.controllerIndex = controller.controllerIndex;
}
args.distance = 0f;
args.flags = 0;
args.target = previousContact;
OnPointerOut(args);
previousContact = null;
}
if(bHit && previousContact != hit.transform)
{
PointerEventArgs argsIn = new PointerEventArgs();
if (controller != null)
{
argsIn.controllerIndex = controller.controllerIndex;
}
argsIn.distance = hit.distance;
argsIn.flags = 0;
argsIn.target = hit.transform;
OnPointerIn(argsIn);
previousContact = hit.transform;
}
if(!bHit)
{
previousContact = null;
}
if (bHit && hit.distance < 100f)
{
dist = hit.distance;
}
if (bHit)//添加的實(shí)現(xiàn)代碼;
{
HitPoint = hit.point;
}
if (controller != null && controller.triggerPressed)
{
pointer.transform.localScale = new Vector3(thickness * 5f, thickness * 5f, dist);
}
else
{
pointer.transform.localScale = new Vector3(thickness, thickness, dist);
}
pointer.transform.localPosition = new Vector3(0f, 0f, dist/2f);
}
}
SteamVR_TrackedController腳本
下面就是自己寫代碼實(shí)現(xiàn)瞬移過(guò)程:
代碼展示及邏輯:
public class Test_Teleporter : MonoBehaviour {
// 拿到手柄對(duì)象
public GameObject LeftController;
//修改后的射線檢測(cè)腳本
private Test_LaserPointer Pointer;
// 右手柄的控制器
private SteamVR_TrackedController LeftSt;
// 事件調(diào)用函數(shù)
ClickedEventHandler ce;
// 當(dāng)前的目標(biāo)位置
Transform currentTransform;
// 碰撞事件
PointerEventArgs arg;
void Start()
{
Pointer = LeftController.GetComponent<Test_LaserPointer>();
LeftSt = LeftController.GetComponent<SteamVR_TrackedController>();
// 利用Laserpoint里面的事件函數(shù)來(lái)檢測(cè)目標(biāo)位置
Pointer.PointerIn += LeftPointIn;
// 利用Laserpoint里面的事件函數(shù)來(lái)檢測(cè)目標(biāo)位置
Pointer.PointerOut += LeftPointOut;
// 利用手柄控制器來(lái)檢測(cè)我們的扳機(jī)事件
LeftSt.TriggerClicked += TriggerClicked;
}
// 沒(méi)有檢測(cè)到碰撞信息
void LeftPointOut(object sender, PointerEventArgs e)
{ // 當(dāng)前位置沒(méi)有
currentTransform = null;
}
// 檢測(cè)到碰撞信息
void LeftPointIn(object sender, PointerEventArgs e)
{ // 設(shè)置目標(biāo)位置為檢測(cè)到的目標(biāo)
currentTransform = e.target;
}
// 扳機(jī)事件
void TriggerClicked(object sender, ClickedEventArgs e)
{
// 如果檢測(cè)到目標(biāo)位置
if (currentTransform != null)
{ // 移動(dòng)
this.gameObject.transform.position = new Vector3(Pointer.HitPoint.x - LeftController.transform.localPosition.x, Pointer.HitPoint.y, Pointer.HitPoint.z - LeftController.transform.localPosition.z);
}
}
}
三霎挟、結(jié)果實(shí)現(xiàn)##
掛載腳本窝剖,實(shí)現(xiàn)結(jié)果