Unity3D-VR人物瞬移、腳丫旋轉判定、高光、開關燈、門、電視
阿新 • • 發佈:2019-01-26
using UnityEngine;
using System.Collections;
using System;
public class Player : MonoBehaviour {
public static Player instance;//靜態公有欄位
public Transform _rightHand;//右手位置
public SteamVR_TrackedObject _rightTrackedObj;//VR指令碼元件
public LineRenderer _rightLineR;//右手線性著色器
public Transform _rightModel;//右手手柄控制器的位置
public Ray _rightRay { get { return new Ray(_rightModel.position, _rightModel.forward); } }//一條從右手手柄發出的射線,指向正前方
public RaycastHit _rightHit;//右手射線檢測體
public Transform _leftHand;//左手位置
public SteamVR_TrackedObject _leftTrackedObj;//左手VR指令碼元件
public LineRenderer _leftLineR;//左手線性著色器
public Transform _leftModel;//左手手柄位置
public Ray _leftRay { get { return new Ray(_leftModel.position,_leftModel.forward); } }//左手射線,指向正前方
public RaycastHit _leftHit;//左手射線檢測體
public Transform _footTex;//腳丫圖片位置
public SteamVR_Controller.Device rightDevice;//右手裝置控制器
public SteamVR_Controller.Device leftDevice;//左手裝置控制
public float lastAngle;//最後的角度
public float currentAngle;//當前的角度
public Quaternion initQ;//初始四元數
public Quaternion resultQ;//結果四元數
public Skybox skyBox;//天空盒
void Awake()
{
instance = this;
_rightHand = this.transform.Find("RightHand");
_rightTrackedObj = _rightHand.GetComponent<SteamVR_TrackedObject>();
_rightLineR = _rightHand.GetComponent<LineRenderer>();
_rightModel = _rightHand.Find("Model");//
_leftHand = this.transform.Find("LeftHand");
_leftTrackedObj = _leftHand.GetComponent<SteamVR_TrackedObject>();
_leftLineR = _leftHand.GetComponent<LineRenderer>();
_leftModel = _leftHand.Find("Model");
_footTex = GameObject.Find("foot").transform;
initQ = _footTex.rotation;
skyBox = this.transform.Find("Camera (head)/Camera (eye)").GetComponent<Skybox>();
InitLeft();
}
void Update()
{
PlayerInput();
}
public void PlayerInput()
{
try
{
rightDevice = SteamVR_Controller.Input((int)_rightTrackedObj.index);
leftDevice = SteamVR_Controller.Input((int)_leftTrackedObj.index);
if (rightDevice.GetPress(SteamVR_Controller.ButtonMask.Touchpad))
{
_rightLineR.SetPosition(0, _rightModel.position);
_rightLineR.SetPosition(1, _rightHit.point);
if (Physics.Raycast(_rightRay, out _rightHit))
{
Interactiable inter = _rightHit.transform.GetComponent<Interactiable>();
if (inter != null)
{
inter.HighLighting();
}
if (rightDevice.GetPressDown(SteamVR_Controller.ButtonMask.Trigger))
{
if (inter != null)
{
inter.Interactive();
}
}
}
else
{
_rightLineR.SetPosition(0, _rightModel.position);
_rightLineR.SetPosition(1, _rightModel.position);
}
}
if (rightDevice.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad))
{
_rightLineR.SetPosition(0, _rightModel.position);
_rightLineR.SetPosition(1, _rightModel.position);
}
if (leftDevice.GetPress(SteamVR_Controller.ButtonMask.Touchpad))
{
if (Physics.Raycast(_leftRay, out _leftHit, Mathf.Infinity, 1 << 8))
{
_footTex.position = _leftHit.point + new Vector3(0, 0.01f, 0);
FootTexRotate();
_leftLineR.SetPosition(0, _leftModel.position);
_leftLineR.SetPosition(1, _leftHit.point);
}
else
{
InitLeft();
}
}
if (leftDevice.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad))
{
if (_leftHit.transform != null && _leftHit.transform.tag == "floor")
{
this.transform.position = _leftHit.point;
}
InitLeft();
}
}
catch(Exception e)
{
Debug.Log(e.Message);
}
}
private void FootTexRotate()
{
//圖片旋轉
Vector3 playerForward = this.transform.forward;
Vector3 rayVector3 = _leftHit.point - new Vector3(_leftModel.position.x, playerForward.y, _leftModel.position.z);
currentAngle = Vector3.Angle(playerForward, rayVector3);
if(lastAngle != currentAngle)
{
//判斷左右
Vector3 result = Vector3.Cross(playerForward, rayVector3);
if (result.y < 0)
{
Quaternion q = Quaternion.identity;
q.eulerAngles = new Vector3(0, -currentAngle, 0);
_footTex.rotation = q * initQ;
}
else
{
Quaternion q = Quaternion.identity;
q.eulerAngles = new Vector3(0, currentAngle, 0);
_footTex.rotation = q * initQ;
}
lastAngle = currentAngle;
}
}
private void InitLeft()
{
_footTex.position = new Vector3(10000, 10000, 10000);
_leftLineR.SetPosition(0, _leftModel.position);
_leftLineR.SetPosition(1, _leftModel.position);
}
}
燈光:
using UnityEngine;
using System.Collections.Generic;
public class Light_Interactiable : Interactiable {
public List<Light> _lights = new List<Light>();
public override void Start()
{
base.Start();
for (int i = 0; i < this.transform.childCount; i++)
{
if (this.transform.GetChild(i).childCount>0)
{
Light light = this.transform.GetChild(i).GetChild(0).GetComponent<Light>();
if (light != null)
{
_lights.Add(light);
}
}
else
{
continue;
}
}
SetDefaultState();
}
protected override void Open()
{
for (int i = 0; i < _lights.Count; i++)
{
_lights[i].enabled = true;
}
}
protected override void Close()
{
for (int i = 0; i < _lights.Count; i++)
{
_lights[i].enabled = false;
}
}
}
功能父類:
using UnityEngine;
using System.Collections;
using HighlightingSystem;
public delegate void OnTrigger(Collider col);
public class Interactiable : MonoBehaviour {
public bool isOpen;
public Color highlightingColor = Color.red;
public Highlighter highlighter;
public OnTrigger triggerEnter;
public OnTrigger triggerStay;
public OnTrigger triggerExit;
public virtual void Start()
{
highlighter = this.gameObject.AddComponent<Highlighter>();
}
public virtual void OnTriggerEnter(Collider col)
{
triggerEnter(col);
}
public virtual void OnTriggerStay(Collider col)
{
triggerStay(col);
}
public virtual void OnTriggerExit(Collider col)
{
triggerExit(col);
}
public virtual void HighLighting()
{
highlighter.On(highlightingColor);
}
protected virtual void SetDefaultState()
{
if(isOpen == true)
{
Open();
}
else
{
Close();
}
}
protected virtual void Open() { }
protected virtual void Close() { }
public virtual void Interactive()
{
if (isOpen == false)
{
Open();
}
else
{
Close();
}
isOpen = !isOpen;
}
}
門開關處理:
using UnityEngine;
using System.Collections;
public enum DoorType
{
None,
Translate,
Rotate,
}
public class Door_Interactiable : Interactiable {
public Vector3 closeState;
public Vector3 openState;
public DoorType doorType;
public override void Start()
{
base.Start();
}
void Update()
{
if(isOpen)
{
if(doorType == DoorType.Translate)
{
this.transform.localPosition = Vector3.MoveTowards(this.transform.localPosition, openState, Time.deltaTime);
}
else if(doorType == DoorType.Rotate)
{
Quaternion q = Quaternion.identity;
q.eulerAngles = new Vector3(0,0, 0);
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, q, Time.deltaTime);
}
}
else
{
if (doorType == DoorType.Translate)
{
this.transform.localPosition = Vector3.Lerp(this.transform.localPosition, closeState, Time.deltaTime);
}
else if (doorType == DoorType.Rotate)
{
Quaternion q = Quaternion.identity;
q.eulerAngles = new Vector3(0, -90, 0);
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, q, Time.deltaTime);
}
}
}
}
電視電影播放:
using UnityEngine;
using System.Collections;
public class TV_Interactiable : Interactiable {
public MovieTexture _movie;
public AudioSource _audio;
public Texture movie;
private MeshRenderer _render;
public override void Start()
{
base.Start();
_render = this.GetComponent<MeshRenderer>();
_render.material.mainTexture = _movie;
_audio = this.transform.GetComponent<AudioSource>();
SetDefaultState();
}
protected override void Open()
{
_render.enabled = true;
_movie.Play();
_audio.Play();
}
protected override void Close()
{
_render.enabled = false;
_movie.Stop();
_audio.Stop();
}
}
改變材質:
using UnityEngine;
using System.Collections;
public enum ChangeMaterialType
{
None,
Skybox,
Floor,
}
public class ChangeMaterialobj_Interactiable : Interactiable
{
public ChangeMaterialType cmType;
public override void Start()
{
base.Start();
}
public override void HighLighting()
{
base.HighLighting();
}
public override void Interactive()
{
if(cmType == ChangeMaterialType.Skybox)
{
Player.instance.GetComponent<Skybox>().material = Resources.Load<Material>("SkyBox/Materials/" + this.transform.name);
}
if(cmType == ChangeMaterialType.Floor)
{
this.transform.parent.parent.GetComponent<MeshRenderer>().material = Resources.Load<Material>("Floor/Materials/" + this.transform.name);
}
}
}