/// by JCxYIS / Modded from Pico VR demo script /// 20220410 using UnityEngine; using System.Collections; using System.Collections.Generic; using Pvr_UnitySDKAPI; using UnityEngine.SceneManagement; /// /// Pico 控制器與他的好朋友們 /// [RequireComponent(typeof(Pvr_Controller))] public class PicoVRcontroller : MonoBehaviour { public static PicoVRcontroller Instance; /// /// 要看指到啥東西就把這個設 true /// public const bool PRINT_DEBUG = false; private GameObject controller0; private GameObject controller1; private Ray ray; public Ray Ray => ray; private GameObject currentController; private Transform lastHit; [SerializeField] private Transform currentHit; GameObject referenceObj; private bool isHasController = false; private RaycastHit hit; private GameObject rayLine; private GameObject dot; private Transform dragObj; private List _triggerManagers = new List(); void Awake() { Instance = this; } void Start() { ray = new Ray(); hit = new RaycastHit(); Pvr_Controller pvr_Controller = GetComponent(); controller0 = pvr_Controller.controller0; controller1 = pvr_Controller.controller1; if (Pvr_UnitySDKManager.SDK.isHasController) { Pvr_ControllerManager.PvrServiceStartSuccessEvent += ServiceStartSuccess; Pvr_ControllerManager.SetControllerStateChangedEvent += ControllerStateListener; isHasController = true; #if UNITY_EDITOR currentController = controller1; dot = controller1.transform.Find("dot").gameObject; dot.SetActive(true); rayLine = controller1.transform.Find("ray_LengthAdaptive").gameObject; rayLine.SetActive(true); #endif } referenceObj = new GameObject("ReferenceObj"); _triggerManagers = FindObjectsOfInterfaces(); } void OnDestroy() { if (isHasController) { Pvr_ControllerManager.PvrServiceStartSuccessEvent -= ServiceStartSuccess; Pvr_ControllerManager.SetControllerStateChangedEvent -= ControllerStateListener; } } void Update() { if (currentController == null) { Debug.LogWarning("No controller."); return; } ray.direction = currentController.transform.forward - currentController.transform.up * 0.25f; ray.origin = currentController.transform.Find("start").position; if (Physics.Raycast(ray, out hit)) { currentHit = hit.transform; if (currentHit != null && lastHit != null && currentHit != lastHit) { if (lastHit.GetComponent() && lastHit.transform.gameObject.activeInHierarchy && lastHit.GetComponent().enabled) { lastHit.GetComponent().enabled = false; } } if (currentHit != null && lastHit != null && currentHit == lastHit) { if (currentHit.GetComponent() && !currentHit.GetComponent().enabled) { currentHit.GetComponent().enabled = true; } } if (currentHit != null) { // Hover print("[PicoVRcontroller] Hover: "+currentHit.gameObject); _triggerManagers.ForEach(i => i.OnTriggerEnter(hit.collider)); // Click if (Controller.UPvr_GetKeyDown(0, Pvr_KeyCode.Any) || Controller.UPvr_GetKeyDown(1, Pvr_KeyCode.Any) || Input.GetMouseButtonDown(0)) { print("[PicoVRcontroller] Click: "+currentHit.gameObject); currentHit.GetComponent()?.OnClick(); } // Drag if (Controller.UPvr_GetKeyDown(0, Pvr_KeyCode.TOUCHPAD) || Controller.UPvr_GetKeyDown(1, Pvr_KeyCode.TOUCHPAD) || Input.GetMouseButtonDown(0)) { referenceObj.transform.position = hit.point; dragObj = currentHit; print("[PicoVRcontroller] DragStart: "+currentHit.gameObject); } if (Controller.UPvr_GetKey(0, Pvr_KeyCode.TOUCHPAD) || Controller.UPvr_GetKey(1, Pvr_KeyCode.TOUCHPAD) || Input.GetMouseButton(0)) { if (currentHit == dragObj.transform) { print("[PicoVRcontroller] Drag: "+currentHit.gameObject); currentHit.GetComponent()?.OnDrag(); } } } // Exit from last stuff (if hit changes) if (lastHit != null && lastHit != currentHit) { print("[PicoVRcontroller] Exit: "+lastHit.transform.gameObject); _triggerManagers.ForEach(i => i.OnTriggerExit(lastHit.GetComponent())); } lastHit = currentHit; #if UNITY_EDITOR Debug.DrawLine(ray.origin, hit.point, Color.red); #endif currentController.transform.Find("dot").position = hit.point; if (Pvr_ControllerManager.Instance.LengthAdaptiveRay) { float scale = 0.178f * currentController.transform.Find("dot").localPosition.z / 3.3f; Mathf.Clamp(scale, 0.05f, 0.178f); currentController.transform.Find("dot").localScale = new Vector3(scale, scale, 1); } } else // hit nothing { if (lastHit != null) { print("[PicoVRcontroller] Exit: "+lastHit.transform.gameObject); _triggerManagers.ForEach(i => i.OnTriggerExit(lastHit.GetComponent())); } lastHit = null; currentHit = null; if(Pvr_ControllerManager.Instance.LengthAdaptiveRay) { currentController.transform.Find("dot").localScale = new Vector3(0.178f, 0.178f, 1); } } #if UNITY_EDITOR rayLine.GetComponent().SetPosition(0,currentController.transform.TransformPoint(0, 0, 0.072f)); rayLine.GetComponent().SetPosition(1, dot.transform.position); #endif } private void ServiceStartSuccess() { if (Controller.UPvr_GetMainHandNess() == 0) { currentController = controller0; } if (Controller.UPvr_GetMainHandNess() == 1) { currentController = controller1; } } private void ControllerStateListener(string data) { if (Controller.UPvr_GetMainHandNess() == 0) { currentController = controller0; } if (Controller.UPvr_GetMainHandNess() == 1) { currentController = controller1; } } /// /// https://answers.unity.com/questions/863509/how-can-i-find-all-objects-that-have-a-script-that.html /// /// /// public static List FindObjectsOfInterfaces( ) { List interfaces = new List(); GameObject[] rootGameObjects = SceneManager.GetActiveScene().GetRootGameObjects(); foreach( var rootGameObject in rootGameObjects ) { T[] childrenInterfaces = rootGameObject.GetComponentsInChildren(); foreach( var childInterface in childrenInterfaces ) { interfaces.Add(childInterface); } } return interfaces; } new void print(object obj) { if(PRINT_DEBUG) Debug.Log(obj); } }