You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
4.4 KiB
108 lines
4.4 KiB
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.XR.Interaction.Toolkit;
|
|
|
|
public class TwoHandGrabInteractable : XRGrabInteractable
|
|
{
|
|
public List<XRSimpleInteractable> secondHandGrabPoints = new List<XRSimpleInteractable>(); //두번째 손 잡이용 XRSimpleInteractable들
|
|
private XRBaseInteractor secondInteractor; //두 번째 손의 Interactor
|
|
private Quaternion attachInitialRotation; //첫 번째 손의 원래 회전값
|
|
|
|
public enum TwoHandRotationType { None, First, Second } //어느 손의 기준으로 총을 회전할 것인가?
|
|
public TwoHandRotationType twoHandRotationType;
|
|
|
|
private Quaternion initialRotationOffset; //두번째 손으로 잡을 때, 회전각의 차이값을 저장
|
|
|
|
void Start()
|
|
{
|
|
//두 번째 손을 잡았을 때 / 손았을 때 실행할 리스너 함수 등록
|
|
foreach (var item in secondHandGrabPoints)
|
|
{
|
|
item.onSelectEntered.AddListener(OnSecondHandGrab);
|
|
item.onSelectExited.AddListener(OnSecondHandRelease);
|
|
}
|
|
}
|
|
|
|
//사물을 잡고 있는 동안 계쏙 실행
|
|
public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
|
|
{
|
|
//양 손으로 잡고 있을 때만 회전값을 계산하도록
|
|
if(selectingInteractor && secondInteractor)
|
|
{
|
|
//회전값을 계산
|
|
//오브젝트의 Pivot중심점이 아닌, 첫 번째 손을 잡은 AttachTransform을 기준으로 회전하기 위해 잡은 손의 attachTransform의 회전각을 변경해줌
|
|
selectingInteractor.attachTransform.rotation = GetTwoHandRotation() * initialRotationOffset;
|
|
}
|
|
|
|
base.ProcessInteractable(updatePhase);
|
|
}
|
|
|
|
|
|
private Quaternion GetTwoHandRotation()
|
|
{
|
|
Quaternion targetRotation;
|
|
|
|
switch (twoHandRotationType)
|
|
{
|
|
default:
|
|
case TwoHandRotationType.None:
|
|
//회전하지 않음
|
|
targetRotation = Quaternion.LookRotation(secondInteractor.transform.position - selectingInteractor.transform.position);
|
|
break;
|
|
case TwoHandRotationType.First:
|
|
targetRotation = Quaternion.LookRotation(secondInteractor.transform.position - selectingInteractor.transform.position, selectingInteractor.attachTransform.up);
|
|
break;
|
|
case TwoHandRotationType.Second:
|
|
targetRotation = Quaternion.LookRotation(secondInteractor.transform.position - selectingInteractor.transform.position, secondInteractor.attachTransform.up);
|
|
break;
|
|
}
|
|
|
|
return targetRotation;
|
|
}
|
|
|
|
public override bool IsSelectableBy(XRBaseInteractor interactor)
|
|
{
|
|
//이미 다른 Interactor가 잡고 있는가?
|
|
//현재 잡고 있는 Interactor가 있고, 그게 지금 새로 잡으려는 interactor가 아닌 경우에만 true
|
|
bool isAlreadyGrabbed = selectingInteractor && !interactor.Equals(selectingInteractor);
|
|
|
|
//'다른 Interactor'가 잡고 있지 않을 때'라는 조건 추가
|
|
return base.IsSelectableBy(interactor) && !isAlreadyGrabbed;
|
|
}
|
|
|
|
public void OnSecondHandGrab(XRBaseInteractor interactor)
|
|
{
|
|
print("Second Hand Grab");
|
|
secondInteractor = interactor; //두번째 Interactor 설정
|
|
|
|
//Quaternion의 회전값의 차이를 구하기 위해, 한 Quaternion의 Inverse값에 다른 Quaternion을 곱해줌
|
|
initialRotationOffset = Quaternion.Inverse(GetTwoHandRotation()) * selectingInteractor.attachTransform.rotation;
|
|
}
|
|
|
|
public void OnSecondHandRelease(XRBaseInteractor interactor)
|
|
{
|
|
print("Second Hand Release");
|
|
secondInteractor = null; //두번쨰 Interactor 비워줌
|
|
}
|
|
|
|
protected override void OnSelectEntered(XRBaseInteractor interactor)
|
|
{
|
|
base.OnSelectEntered(interactor);
|
|
|
|
print("First Hand Enter");
|
|
|
|
attachInitialRotation = interactor.attachTransform.localRotation; //첫 번째 손의 원래 회전값 저장
|
|
}
|
|
|
|
protected override void OnSelectExited(XRBaseInteractor interactor)
|
|
{
|
|
base.OnSelectExited(interactor);
|
|
|
|
print("First Hand Exit");
|
|
|
|
secondInteractor = null; //첫번째 손을 놓으면, 두번째 손도 놓게
|
|
|
|
interactor.attachTransform.localRotation = attachInitialRotation; //첫 번째 손의 회전값 리셋
|
|
}
|
|
}
|