아직도 햇갈리는 부분이 있다. 인풋 시스템이 XR Interaction Toolkit Input에서 가져다 쓰는 건지 Open XR인지는 좀 더 알아봐야겠지만 어쨋든 인풋을 가져다 쓸때 아직 정규화된 인풋을 가져다 쓰는것은 어려운 것 같다. 결국 커스텀을 해서 써야할 듯 하다.
몇 가지 방법을 써보려고 시도중이다. 일단 기본적인 사용법은 이렇다.
inputDevice.TryGetFeatureValue(CommonUsages.secondaryButton, out bool buttonValue
저 inputDevice는 XRController 컴포넌트에서 가져오던지 Device컴포넌트에서 가져오던지 할 수 있는것 처럼 보인다. 어쨋든 업데이트 문에서 If문을 걸러 buttonValue를 디버깅해보면 프레임마다 눌렀을때 True, 땟을때 False 계속 반환한다. 그래서 결국 Input.GetButtonDown과 같은 기능을 편하게 사용하려면 코딩을 해야한다.
private XRController xrController;
bool rightHandLastState = false;
// Start is called before the first frame update
void Start()
{
DontDestroyOnLoad(gameObject);
rightHandLastState = false; // Assumed not held when starting game, while also initializing the value
xrController = GameObject.Find("XR Rig").transform.GetChild(0).GetChild(2).GetComponent<XRController>();
}
// Update is called once per frame
void Update()
{
if (xrController.inputDevice.TryGetFeatureValue(CommonUsages.secondaryButton, out bool buttonValue))
{
if (buttonValue != rightHandLastState)
{
// Button was pressed or released this frame
// Do something with it here...
// ... then make sure to set the last known state of it for reference next Update()
if(rightHandLastState) // 버튼 때기
{
}
else // 버튼 누르기
{
LoadNextScene();
}
Debug.Log(rightHandLastState + "Press!");
rightHandLastState = buttonValue;
}
}
}
예시 코드인데 버튼을 누를 때마다 씬전환을 하는 코드이다.
어떻게든 하나만 누르면 되는 코드면 이렇게 쓰면되겠지만 전체적인 깔끔인 Input 관리를 하려면
using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.XR;
using UnityEngine.XR.Interaction.Toolkit;
public class XRInput : MonoBehaviour
{
#pragma warning disable 0649
[SerializeField] XRController controller;
[SerializeField] XRBinding[] bindings;
#pragma warning restore 0649
private void Update()
{
foreach (var binding in bindings)
binding.Update(controller.inputDevice);
}
}
[Serializable]
public class XRBinding
{
#pragma warning disable 0649
[SerializeField] XRButton button;
[SerializeField] PressType pressType;
[SerializeField] UnityEvent OnActive;
#pragma warning restore 0649
bool isPressed;
bool wasPressed;
public void Update(InputDevice device)
{
device.TryGetFeatureValue(XRStatics.GetFeature(button), out isPressed);
bool active = false;
switch (pressType)
{
case PressType.Continuous: active = isPressed; break;
case PressType.Begin: active = isPressed && !wasPressed; break;
case PressType.End: active = !isPressed && wasPressed; break;
}
if (active) OnActive.Invoke();
wasPressed = isPressed;
}
}
public enum XRButton
{
Trigger,
Grip,
Primary,
PrimaryTouch,
Secondary,
SecondaryTouch,
Primary2DAxisClick,
Primary2DAxisTouch
}
public enum PressType
{
Begin,
End,
Continuous
}
public static class XRStatics
{
public static InputFeatureUsage<bool> GetFeature(XRButton button)
{
switch (button)
{
case XRButton.Trigger: return CommonUsages.triggerButton;
case XRButton.Grip: return CommonUsages.gripButton;
case XRButton.Primary: return CommonUsages.primaryButton;
case XRButton.PrimaryTouch: return CommonUsages.primaryTouch;
case XRButton.Secondary: return CommonUsages.secondaryButton;
case XRButton.SecondaryTouch: return CommonUsages.secondaryTouch;
case XRButton.Primary2DAxisClick: return CommonUsages.primary2DAxisClick;
case XRButton.Primary2DAxisTouch: return CommonUsages.primary2DAxisTouch;
default: Debug.LogError("button " + button + " not found"); return CommonUsages.triggerButton;
}
}
}
이런식의 코드를 사용해도 좋아보인다.
구글링하다 찾은 코드인데 사용해보고 사용성이 괜찮은지 확인해봐야겠다.
몇 가지 영상을 더 찾아보고 제일 좋은걸로 올려놓겠다.