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

5 years ago
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.XR.Interaction.Toolkit;
  5. public class TwoHandGrabInteractable : XRGrabInteractable
  6. {
  7. public List<XRSimpleInteractable> secondHandGrabPoints = new List<XRSimpleInteractable>(); //두번째 손 잡이용 XRSimpleInteractable들
  8. private XRBaseInteractor secondInteractor; //두 번째 손의 Interactor
  9. private Quaternion attachInitialRotation; //첫 번째 손의 원래 회전값
  10. public enum TwoHandRotationType { None, First, Second } //어느 손의 기준으로 총을 회전할 것인가?
  11. public TwoHandRotationType twoHandRotationType;
  12. private Quaternion initialRotationOffset; //두번째 손으로 잡을 때, 회전각의 차이값을 저장
  13. void Start()
  14. {
  15. //두 번째 손을 잡았을 때 / 손았을 때 실행할 리스너 함수 등록
  16. foreach (var item in secondHandGrabPoints)
  17. {
  18. item.onSelectEntered.AddListener(OnSecondHandGrab);
  19. item.onSelectExited.AddListener(OnSecondHandRelease);
  20. }
  21. }
  22. //사물을 잡고 있는 동안 계쏙 실행
  23. public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
  24. {
  25. //양 손으로 잡고 있을 때만 회전값을 계산하도록
  26. if(selectingInteractor && secondInteractor)
  27. {
  28. //회전값을 계산
  29. //오브젝트의 Pivot중심점이 아닌, 첫 번째 손을 잡은 AttachTransform을 기준으로 회전하기 위해 잡은 손의 attachTransform의 회전각을 변경해줌
  30. selectingInteractor.attachTransform.rotation = GetTwoHandRotation() * initialRotationOffset;
  31. }
  32. base.ProcessInteractable(updatePhase);
  33. }
  34. private Quaternion GetTwoHandRotation()
  35. {
  36. Quaternion targetRotation;
  37. switch (twoHandRotationType)
  38. {
  39. default:
  40. case TwoHandRotationType.None:
  41. //회전하지 않음
  42. targetRotation = Quaternion.LookRotation(secondInteractor.transform.position - selectingInteractor.transform.position);
  43. break;
  44. case TwoHandRotationType.First:
  45. targetRotation = Quaternion.LookRotation(secondInteractor.transform.position - selectingInteractor.transform.position, selectingInteractor.attachTransform.up);
  46. break;
  47. case TwoHandRotationType.Second:
  48. targetRotation = Quaternion.LookRotation(secondInteractor.transform.position - selectingInteractor.transform.position, secondInteractor.attachTransform.up);
  49. break;
  50. }
  51. return targetRotation;
  52. }
  53. public override bool IsSelectableBy(XRBaseInteractor interactor)
  54. {
  55. //이미 다른 Interactor가 잡고 있는가?
  56. //현재 잡고 있는 Interactor가 있고, 그게 지금 새로 잡으려는 interactor가 아닌 경우에만 true
  57. bool isAlreadyGrabbed = selectingInteractor && !interactor.Equals(selectingInteractor);
  58. //'다른 Interactor'가 잡고 있지 않을 때'라는 조건 추가
  59. return base.IsSelectableBy(interactor) && !isAlreadyGrabbed;
  60. }
  61. public void OnSecondHandGrab(XRBaseInteractor interactor)
  62. {
  63. print("Second Hand Grab");
  64. secondInteractor = interactor; //두번째 Interactor 설정
  65. //Quaternion의 회전값의 차이를 구하기 위해, 한 Quaternion의 Inverse값에 다른 Quaternion을 곱해줌
  66. initialRotationOffset = Quaternion.Inverse(GetTwoHandRotation()) * selectingInteractor.attachTransform.rotation;
  67. }
  68. public void OnSecondHandRelease(XRBaseInteractor interactor)
  69. {
  70. print("Second Hand Release");
  71. secondInteractor = null; //두번쨰 Interactor 비워줌
  72. }
  73. protected override void OnSelectEntered(XRBaseInteractor interactor)
  74. {
  75. base.OnSelectEntered(interactor);
  76. print("First Hand Enter");
  77. attachInitialRotation = interactor.attachTransform.localRotation; //첫 번째 손의 원래 회전값 저장
  78. }
  79. protected override void OnSelectExited(XRBaseInteractor interactor)
  80. {
  81. base.OnSelectExited(interactor);
  82. print("First Hand Exit");
  83. secondInteractor = null; //첫번째 손을 놓으면, 두번째 손도 놓게
  84. interactor.attachTransform.localRotation = attachInitialRotation; //첫 번째 손의 회전값 리셋
  85. }
  86. }