SW 중심대학 OSS GIT 서버 새로운 리포
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

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; //첫 번째 손의 회전값 리셋
}
}