Skip to content

Instantly share code, notes, and snippets.

@JCxYIS
Last active April 10, 2022 08:49
Show Gist options
  • Save JCxYIS/02877f8e3904695c51cd076f631efe9c to your computer and use it in GitHub Desktop.
Save JCxYIS/02877f8e3904695c51cd076f631efe9c to your computer and use it in GitHub Desktop.
/// by JCxYIS
/// 20220406
using UnityEngine;
/// <summary>
/// 繼承此介面以監聽物件點擊事件
/// </summary>
public interface IClickable
{
void OnClick();
}
/// <summary>
/// 繼承此介面以監聽物件拖移事件
/// </summary>
public interface IDragable
{
void OnDrag();
}
/// <summary>
/// 繼承此介面以管理控制器 Hover 事件
/// </summary>
public interface ITriggerManager
{
/// <summary>
/// Hover Enter
/// </summary>
void OnTriggerEnter(Collider other);
/// <summary>
/// Hover Exit
/// </summary>
void OnTriggerExit(Collider other);
}
/// by JCxYIS / Modded from Pico VR demo script
/// 20220410
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Pvr_UnitySDKAPI;
using UnityEngine.SceneManagement;
/// <summary>
/// Pico 控制器與他的好朋友們
/// </summary>
[RequireComponent(typeof(Pvr_Controller))]
public class PicoVRcontroller : MonoBehaviour
{
public static PicoVRcontroller Instance;
/// <summary>
/// 要看指到啥東西就把這個設 true
/// </summary>
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<ITriggerManager> _triggerManagers = new List<ITriggerManager>();
void Awake()
{
Instance = this;
}
void Start()
{
ray = new Ray();
hit = new RaycastHit();
Pvr_Controller pvr_Controller = GetComponent<Pvr_Controller>();
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<ITriggerManager>();
}
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<Pvr_UIGraphicRaycaster>() && lastHit.transform.gameObject.activeInHierarchy && lastHit.GetComponent<Pvr_UIGraphicRaycaster>().enabled)
{
lastHit.GetComponent<Pvr_UIGraphicRaycaster>().enabled = false;
}
}
if (currentHit != null && lastHit != null && currentHit == lastHit)
{
if (currentHit.GetComponent<Pvr_UIGraphicRaycaster>() && !currentHit.GetComponent<Pvr_UIGraphicRaycaster>().enabled)
{
currentHit.GetComponent<Pvr_UIGraphicRaycaster>().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<IClickable>()?.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<IDragable>()?.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<Collider>()));
}
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<Collider>()));
}
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<LineRenderer>().SetPosition(0,currentController.transform.TransformPoint(0, 0, 0.072f));
rayLine.GetComponent<LineRenderer>().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;
}
}
/// <summary>
/// https://answers.unity.com/questions/863509/how-can-i-find-all-objects-that-have-a-script-that.html
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static List<T> FindObjectsOfInterfaces<T>( )
{
List<T> interfaces = new List<T>();
GameObject[] rootGameObjects = SceneManager.GetActiveScene().GetRootGameObjects();
foreach( var rootGameObject in rootGameObjects )
{
T[] childrenInterfaces = rootGameObject.GetComponentsInChildren<T>();
foreach( var childInterface in childrenInterfaces )
{
interfaces.Add(childInterface);
}
}
return interfaces;
}
new void print(object obj)
{
if(PRINT_DEBUG)
Debug.Log(obj);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment