미디어 콘텐츠 스터디
Part08. 양손 잡기 상호작용(Two Hand Grab Interation) 본문
Part08. 양손 잡기 상호작용(Two Hand Grab Interation)
danmujicat 2022. 8. 11. 14:23
1. 총 잡기
① 하이러키 창에 M4_Complete 모델을 추가하고 인스펙터 창에서 Transform 재설정한다.
Position(-0.747, 0.54, 0.116)
② 하이러키 창에서 M4_Complete 을 선택하고 TwoHandGrabInteractable.cs 스크립트를 추가한다.
TwoHandGrabInteractable.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
public class TwoHandGrabInteractable : XRGrabInteractable
void Start()
{
}
void Update()
{
}
③ 하이러키 창에서 M4_Complete 을 선택하고 인스펙터 창에서 Rigidbody 추가한다.
④ 하이러키 창에서 M4_Complete 하위의 모든 오브젝트를 선택하고 인스펙터 창에서 [Add Componenent]버튼을 선택하여 Box Collider를 추가한다.
⑤ 하이러키 창에서 M4_Complete를 선택하고 인스펙터 창에 Colliders로 M4_Complete 하위의 모든 오브젝트를 드래그앤 드룹하여 설정함
⑥ 하이러키 창에서 M4_Complete를 선택하고 인스펙스 창에서 Layer를 Grab을 설정한다.
⑦ 하이러키 창에서 M4_Complete를 선택하고 GameObject | Create Empty 메뉴 선택하여 하위에 GameObject 추가하고 이름을 Attach Transform으로 변경하고 중심좌표를 총 뒤쪽 손잡이로 이동 및 y축을 -180도 회전한다.
- Position(0.0318, 0.0031, 0.0498), Rotation(0, -180, 0)
⑧ 하이러키 창에서 M4_Complete-> Attach Transform을 선택하여 인스펙터 창에 TwoHandGrabInteractable 컴포넌트의 Attatch Transfrom에 드래그앤드룹하여 설정한다.
⑨ 실행하기
2. 총 쏘기
① 하이러키 창에서 M4_Complete를 선택하고 인스펙트 창에서 [Add component] 버튼을 클릭하여 Gun.cs과 Audio Source 컴포넌트를 추가한다. (또는 이전 권총의 Gun과 Audio Source 컴포넌트 복사하여 붙여넣기 해도 된다)
② 하이러키 창에서 M4_Complete를 선택하고 하위에 GameObject | Create Empty 메뉴를 선택하여 GameObject를 만들고 이름을 Barrel를 변경한다.
③ 하이러키 창에서 Barrel를 선택하고 중심좌표를 총입구로 이동하고 y축으로 -180도 회전한다.
- Position(0, 0.06, -0.499), Rotation(0, -180, 0)
④하이러키 창에서 Barrel를 선택하여 인스펙터 창에서 Gun 컴포넌트의 Barrel에 드래드앤드룹, Audio Source을 Gun 컴포넌트의 Audio Source에 드래드앤드롭하여 설정한다
⑤ 하이러키 창에서 M4_Complete를 선택하고 인스펙트 창에서 Two Hand Grab Interactable 컴포넌트의 Activate에 Gun 컴포넌트로 드래그앤드룹하여 설정하고 함수는 Gun->Fire()을 설정한다.
⑥실행하기
3. 총 회전시키기
3.1 총 머리와 총 손잡이 회전 만들기
① 하이러키 창에서 M4_Complete 선택하고 Cube 추가하고 이름을 Second Grab Point로 변경하고 중심좌표를 총 머리쪽이으로 이동하고 크기를 조정한다.
Position(0.016, 0.073, -0.222) Scale(0.0610, 0.066, 0.163)
② 하이러키 창에서 Second Grab Point를 선택하고 인스펙터 창에서 Cube(Mesh Filter), Mesh Renderer 삭제한다.
③하이러키 창에서 Second Grab Point를 선택하고 인스펙터 창에서 RigidBody 컴포넌트 추가하고 Is Kinematic 체크,
XR Simple Interactable 컴포넌트 추가하고 Colliders에 Box Collider을 드래그앤 드룹하여 설정한다.
④ 하이러키 창에서 Second Grab Point를 복사하여 Second Grab Point(1)을 총 앞쪽 손잡이로 이동한다. 또는 인스펙터 창에서 Transform 재설정한다
Position(0.019, -0.052, -0.07) Rotation(-80.28, 0,0) Scale(0.033, 0.071 , 0.163)
⑤ 인스펙터 창에서 Layer에서 Add Layer 클릭하여 Second Hand Grab 를 추가한다.
⑥ 하이러키 창에서 Second Grab Point와 Second Grab Point(1)을 선택하고 인스펙터 창에서 Layer를 Second Hand Grab로 설정한다
⑦ Edit | Project Setting 메뉴 선택하여 Physics항목을 선택하여 Layer Collision Matrix 설정한다.
⑧ 회전 코딩하기
TwoHandGrabInteractable
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>();
private XRBaseInteractor secondInteractor;
void Start()
{
foreach (var item in secondHandGrabPoints)
{
item.onSelectEntered.AddListener(OnSecondHandGrab);
item.onSelectExited.AddListener(OnSecondHandRelease);
}
}
public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
{
if (secondInteractor && selectingInteractor)
{
selectingInteractor.attachTransform.rotation = Quaternion.LookRotation(secondInteractor.attachTransform.position - selectingInteractor.attachTransform.position); ;
}
base.ProcessInteractable(updatePhase);
}
public void OnSecondHandGrab(XRBaseInteractor interactor)
{
Debug.Log("SECOND HAND GRAB");
secondInteractor = interactor;
// initialRotationOffset = Quaternion.Inverse(GetTwoHandRotation()) * selectingInteractor.attachTransform.rotation;
}
public void OnSecondHandRelease(XRBaseInteractor interactor)
{
Debug.Log("SECOND HAND RELEASE");
secondInteractor = null;
}
protected override void OnSelectEntered(XRBaseInteractor interactor)
{
Debug.Log("First Grab Enter");
base.OnSelectEntered(interactor);
}
protected override void OnSelectExited(XRBaseInteractor interactor)
{
Debug.Log("First Grab Exit");
base.OnSelectExited(interactor);
secondInteractor = null;
}
public override bool IsSelectableBy(XRBaseInteractor interactor)
{
bool isalreadygrabbed = selectingInteractor && !interactor.Equals(selectingInteractor);
return base.IsSelectableBy(interactor) && !isalreadygrabbed;
}
}
⑨ 실행하기
3.2 회전 개선하기
① 총을 다시 잡을 경우 손 위치 초기화 시키기
TwoHandGrabInteractable.cs
public class TwoHandGrabInteractable : XRGrabInteractable
{
private Quaternion attachInitialRotation;
....
protected override void OnSelectEntered(XRBaseInteractor interactor)
{
Debug.Log("First Grab Enter");
base.OnSelectEntered(interactor);
attachInitialRotation = interactor.attachTransform.localRotation;
}
protected override void OnSelectExited(XRBaseInteractor interactor)
{
Debug.Log("First Grab Exit");
base.OnSelectExited(interactor);
secondInteractor = null;
interactor.attachTransform.localRotation = attachInitialRotation;
}
...
}
② 하이러키 창에서 M4_Complete를 선택하고 인스펙트 창에서 Second Hand Points에 하이러키창의 M4_Complete하위에 있는 Second Grab Point와 Second Grab Point(1)을 드래그앤드룹하여 설정한다.
③ 코딩 하기
TwoHandGrabInteractable .cs
...
public class TwoHandGrabInteractable : XRGrabInteractable
{
public List<XRSimpleInteractable> secondHandGrabPoints = new List<XRSimpleInteractable>();
private XRBaseInteractor secondInteractor;
private Quaternion attachInitialRotation;
public bool snapToSecondHand = true;
public TwoHandRotationType twoHandRotationType;
public enum TwoHandRotationType { None, First, Second };
private Quaternion initialRotationOffset;
// Start is called before the first frame update
void Start()
{
foreach (var item in secondHandGrabPoints)
{
item.onSelectEntered.AddListener(OnSecondHandGrab);
item.onSelectExited.AddListener(OnSecondHandRelease);
}
}
public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
{
if (secondInteractor && selectingInteractor)
{
//Compute the rotation
if (snapToSecondHand)
selectingInteractor.attachTransform.rotation = GetTwoHandRotation();
else
selectingInteractor.attachTransform.rotation = GetTwoHandRotation() * initialRotationOffset;
}
base.ProcessInteractable(updatePhase);
}
private Quaternion GetTwoHandRotation()
{
Quaternion targetRotation;
if (twoHandRotationType == TwoHandRotationType.None)
{
targetRotation = Quaternion.LookRotation(secondInteractor.attachTransform.position - selectingInteractor.attachTransform.position); ;
}
else if (twoHandRotationType == TwoHandRotationType.First)
{
targetRotation = Quaternion.LookRotation(secondInteractor.attachTransform.position - selectingInteractor.attachTransform.position, selectingInteractor.attachTransform.up);
}
else
{
targetRotation = Quaternion.LookRotation(secondInteractor.attachTransform.position - selectingInteractor.attachTransform.position, secondInteractor.attachTransform.up);
}
return targetRotation;
}
public void OnSecondHandGrab(XRBaseInteractor interactor)
{
Debug.Log("SECOND HAND GRAB");
secondInteractor = interactor;
initialRotationOffset = Quaternion.Inverse(GetTwoHandRotation()) * selectingInteractor.attachTransform.rotation;
}
public void OnSecondHandRelease(XRBaseInteractor interactor)
{
Debug.Log("SECOND HAND RELEASE");
secondInteractor = null;
}
protected override void OnSelectEntered(XRBaseInteractor interactor)
{
Debug.Log("First Grab Enter");
base.OnSelectEntered(interactor);
attachInitialRotation = interactor.attachTransform.localRotation;
}
protected override void OnSelectExited(XRBaseInteractor interactor)
{
Debug.Log("First Grab Exit");
base.OnSelectExited(interactor);
secondInteractor = null;
interactor.attachTransform.localRotation = attachInitialRotation;
}
public override bool IsSelectableBy(XRBaseInteractor interactor)
{
bool isalreadygrabbed = selectingInteractor && !interactor.Equals(selectingInteractor);
return base.IsSelectableBy(interactor) && !isalreadygrabbed;
}
}
④실행하기
'가상현실(Virtual Reality) > 가상현실 기초 다루기' 카테고리의 다른 글
Part00. XR 환경 설정 (0) | 2022.08.17 |
---|---|
Part09. 암벽 오르기(Climbing) (0) | 2022.08.13 |
Part07. 스냅 존(Snap Zone) (0) | 2022.08.10 |
Part06. 문(Door), 서랍(Drawer), 레버(Lever) 조작 (0) | 2022.08.09 |
Part05. 광선 상호작용(Ray Interaction) (0) | 2022.08.09 |