1. 程式人生 > >Unity3D-VR人物瞬移、腳丫旋轉判定、高光、開關燈、門、電視

Unity3D-VR人物瞬移、腳丫旋轉判定、高光、開關燈、門、電視

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);
        }
    }
}