commit
8c45104f18
9 changed files with 503 additions and 0 deletions
-
83ContinuousMovement.cs
-
80FadeTeleportationProvider.cs
-
48LocomotionController.cs
-
43ObjectActivator.cs
-
17SceneLoad.cs
-
50SocketTarget.cs
-
108TwoHandGrabInteractable.cs
-
30XRExclusiveSocketInteractor.cs
-
44XROffsetGrabInteractable.cs
@ -0,0 +1,83 @@ |
|||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.XR; |
||||
|
using UnityEngine.XR.Interaction.Toolkit; |
||||
|
|
||||
|
public class ContinuousMovement : MonoBehaviour |
||||
|
{ |
||||
|
public float gravity = -9.81f; //중력 상수
|
||||
|
public float speed = 1f; |
||||
|
public float additionalHeight = 0.2f; //눈~정수리 위까지의 추가 키
|
||||
|
public XRNode inputSource; //인풋을 가져올 XRNode => Left Hand로 설정
|
||||
|
public LayerMask groundLayer; //히트 체크할 땅의 레이어
|
||||
|
|
||||
|
private float fallingSpeed; //떨어지는 속도
|
||||
|
private Vector2 inputAxis; //조이스틱 인풋값
|
||||
|
private CharacterController character; //이동용 컴포넌트
|
||||
|
private XRRig rig; //카메라 바라보는 방향 가져오기 위해 레퍼런스 가져옴
|
||||
|
|
||||
|
|
||||
|
// Start is called before the first frame update
|
||||
|
void Start() |
||||
|
{ |
||||
|
character = GetComponent<CharacterController>(); |
||||
|
rig = GetComponent<XRRig>(); |
||||
|
} |
||||
|
|
||||
|
// Update is called once per frame
|
||||
|
void Update() |
||||
|
{ |
||||
|
//XRNode로 device가져와서 인풋값 받기
|
||||
|
InputDevice device = InputDevices.GetDeviceAtXRNode(inputSource); |
||||
|
device.TryGetFeatureValue(CommonUsages.primary2DAxis, out inputAxis); |
||||
|
} |
||||
|
|
||||
|
//CharacterController는 물리적으로 반응하며 움직이기 떄문에 FixedUpdate에서 처리해줘야 함
|
||||
|
private void FixedUpdate() //0.02 * 50 = 1
|
||||
|
{ |
||||
|
CapsuleFollowHeadset(); |
||||
|
|
||||
|
//※사원수를 쓰는 이유 : https://hoodymong.tistory.com/3
|
||||
|
//카메라의 y 앵글값(=Yaw)을 사원수(Quaternion)으로 변환
|
||||
|
Quaternion headYaw = Quaternion.Euler(0f, rig.cameraGameObject.transform.eulerAngles.y, 0f); |
||||
|
|
||||
|
//Quaternion x Vector3 하면 회전
|
||||
|
Vector3 direction = headYaw * new Vector3(inputAxis.x, 0f, inputAxis.y); |
||||
|
|
||||
|
character.Move(direction * Time.fixedDeltaTime * speed); |
||||
|
|
||||
|
//중력 적용 : 발이 땅에 붙어있지 않을 때만 하강 속도가 증가하도록
|
||||
|
bool isGrounded = CheckIfGrounded(); |
||||
|
|
||||
|
if (isGrounded) |
||||
|
fallingSpeed = 0f; |
||||
|
else |
||||
|
fallingSpeed += gravity * Time.fixedDeltaTime; |
||||
|
|
||||
|
character.Move(Vector3.up * fallingSpeed * Time.fixedDeltaTime); |
||||
|
} |
||||
|
|
||||
|
//발이 땅에 붙었는지?를 리턴하는 함수
|
||||
|
private bool CheckIfGrounded() |
||||
|
{ |
||||
|
Vector3 rayStart = transform.TransformPoint(character.center); //CharacterController의 중심점을 월드 스페이스 변환
|
||||
|
float rayLength = character.center.y + 0.01f; //광선 길이는 CC의 키/2 보다 살짝만 더 길게해서 발 밑을 확실히 체크하도록 해줌
|
||||
|
bool hasHit = Physics.SphereCast(rayStart, character.radius, Vector3.down, out RaycastHit hitInfo, rayLength, groundLayer); |
||||
|
|
||||
|
return hasHit; |
||||
|
} |
||||
|
|
||||
|
//캐릭터 컨트롤러의 캡슐이 내 머리 위치 따라오도록 설정
|
||||
|
void CapsuleFollowHeadset() |
||||
|
{ |
||||
|
//카메라의 위치를 자기 자신 기준 local 좌표로 보정하여 저장
|
||||
|
Vector3 capsuleCenter = transform.InverseTransformPoint(rig.cameraGameObject.transform.position); |
||||
|
|
||||
|
//Capsule의 높이를 rig의 높이 + 약간의 여유값에 맞춰줌
|
||||
|
character.height = rig.cameraInRigSpaceHeight + additionalHeight; |
||||
|
|
||||
|
//수평(x, z) 좌표는 capsuleCenter를 따라가고, y는 character.height의 절반으로 해서 발을 땅에 붙이도록 해줌
|
||||
|
character.center = new Vector3(capsuleCenter.x, character.height / 2f, capsuleCenter.z); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.UI; |
||||
|
using UnityEngine.XR.Interaction.Toolkit; |
||||
|
using DG.Tweening; //DOTween 네임스페이스
|
||||
|
using UnityEngine.Assertions; |
||||
|
|
||||
|
public class FadeTeleportationProvider : TeleportationProvider |
||||
|
{ |
||||
|
public Image fadeScreen; |
||||
|
public Color fadeColor = Color.black; |
||||
|
public float fadeDuration = 0.5f; |
||||
|
|
||||
|
// Start is called before the first frame update
|
||||
|
void Start() |
||||
|
{ |
||||
|
startLocomotion += FadeTeleportationProvider_startLocomotion; |
||||
|
endLocomotion += FadeTeleportationProvider_endLocomotion; |
||||
|
fadeScreen.color = fadeColor; |
||||
|
} |
||||
|
|
||||
|
private void FadeTeleportationProvider_startLocomotion(LocomotionSystem obj) |
||||
|
{ |
||||
|
print("Start Locomotion"); |
||||
|
//페이드아웃이 끝나면 Teleport 함수를 실행해라
|
||||
|
fadeScreen.DOFade(1f, fadeDuration).OnComplete(Teleport); |
||||
|
} |
||||
|
|
||||
|
private void FadeTeleportationProvider_endLocomotion(LocomotionSystem obj) |
||||
|
{ |
||||
|
print("End Locomotion"); |
||||
|
fadeScreen.DOFade(0f, fadeDuration); |
||||
|
} |
||||
|
|
||||
|
protected override void Update() |
||||
|
{ |
||||
|
//텔레포트 요청
|
||||
|
if (!validRequest || !BeginLocomotion()) |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
void Teleport() |
||||
|
{ |
||||
|
print("Begin TeleporT!!!"); |
||||
|
|
||||
|
//실제 텔레포트 하는 부분
|
||||
|
var xrRig = system.xrRig; |
||||
|
if (xrRig != null) |
||||
|
{ |
||||
|
switch (currentRequest.matchOrientation) |
||||
|
{ |
||||
|
case MatchOrientation.WorldSpaceUp: |
||||
|
xrRig.MatchRigUp(Vector3.up); |
||||
|
break; |
||||
|
case MatchOrientation.TargetUp: |
||||
|
xrRig.MatchRigUp(currentRequest.destinationRotation * Vector3.up); |
||||
|
break; |
||||
|
case MatchOrientation.TargetUpAndForward: |
||||
|
xrRig.MatchRigUpCameraForward(currentRequest.destinationRotation * Vector3.up, currentRequest.destinationRotation * Vector3.forward); |
||||
|
break; |
||||
|
case MatchOrientation.None: |
||||
|
// Change nothing. Maintain current rig rotation.
|
||||
|
break; |
||||
|
default: |
||||
|
Assert.IsTrue(false, $"Unhandled {nameof(MatchOrientation)}={currentRequest.matchOrientation}."); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
var heightAdjustment = xrRig.rig.transform.up * xrRig.cameraInRigSpaceHeight; |
||||
|
|
||||
|
var cameraDestination = currentRequest.destinationPosition + heightAdjustment; |
||||
|
|
||||
|
xrRig.MoveCameraToWorldLocation(cameraDestination); |
||||
|
} |
||||
|
|
||||
|
EndLocomotion(); |
||||
|
validRequest = false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.XR.Interaction.Toolkit; |
||||
|
|
||||
|
public class LocomotionController : MonoBehaviour |
||||
|
{ |
||||
|
public XRController leftTeleportRay; |
||||
|
public XRController rightTeleportRay; |
||||
|
public InputHelpers.Button teleportActivationButton; //텔레포트 활성화 버튼
|
||||
|
public float activationThreshold = 0.1f; //살짝만 누르면 텔레포트 활성화 되도록
|
||||
|
|
||||
|
//각 손의 텔레포트 활성화 할것인가? => UnityEvent 에서 설정
|
||||
|
public bool EnableLeftTeleport { get; set; } = true; |
||||
|
public bool EnableRightTeleport { get; set; } = true; |
||||
|
|
||||
|
public XRRayInteractor leftRayInteractor; |
||||
|
public XRRayInteractor rightRayInteractor; |
||||
|
|
||||
|
// Update is called once per frame
|
||||
|
void Update() |
||||
|
{ |
||||
|
//각 컨트롤러의 텔레포트를 활성화/비활성화
|
||||
|
if (leftTeleportRay) |
||||
|
{ |
||||
|
//InteractorRay가 무엇에 닿았는가?
|
||||
|
bool isLeftInteractorRayHovering = leftRayInteractor.TryGetHitInfo(out Vector3 pos, out Vector3 norm, out int posInLine, out bool isValid); |
||||
|
leftTeleportRay.gameObject.SetActive(CheckIfActivated(leftTeleportRay) && EnableLeftTeleport && !isLeftInteractorRayHovering); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if (rightTeleportRay) |
||||
|
{ |
||||
|
bool isRightInteractorRayHovering = rightRayInteractor.TryGetHitInfo(out Vector3 pos, out Vector3 norm, out int posInLine, out bool isValid); |
||||
|
rightTeleportRay.gameObject.SetActive(CheckIfActivated(rightTeleportRay) && EnableRightTeleport && !isRightInteractorRayHovering); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
//특정 컨트롤러의 특정 버튼이 눌렀는가? 를 리턴하는 함수
|
||||
|
public bool CheckIfActivated(XRController controller) |
||||
|
{ |
||||
|
//controller의 활성화 버튼을 activationThreshold 이상으로 눌렀으면, 그 값을 저장하고 리턴
|
||||
|
InputHelpers.IsPressed(controller.inputDevice, teleportActivationButton, out bool isActivated, activationThreshold); |
||||
|
|
||||
|
return isActivated; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Events; |
||||
|
|
||||
|
public class ObjectActivator : MonoBehaviour |
||||
|
{ |
||||
|
public bool Toggle; |
||||
|
public UnityEvent OnActivated; |
||||
|
public UnityEvent OnDeactivated; |
||||
|
public AudioClip audioClip; |
||||
|
public AudioSource audioSource; |
||||
|
|
||||
|
bool m_Activated = false; |
||||
|
|
||||
|
public void Activated() |
||||
|
{ |
||||
|
if (Toggle) |
||||
|
{ |
||||
|
if (m_Activated) |
||||
|
OnDeactivated.Invoke(); |
||||
|
else |
||||
|
OnActivated.Invoke(); |
||||
|
m_Activated = !m_Activated; |
||||
|
audioSource.PlayOneShot(audioClip); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
OnActivated.Invoke(); |
||||
|
m_Activated = true; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Deactivated() |
||||
|
{ |
||||
|
if (!Toggle) |
||||
|
{ |
||||
|
OnDeactivated.Invoke(); |
||||
|
m_Activated = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.SceneManagement; |
||||
|
|
||||
|
public class SceneLoad : MonoBehaviour |
||||
|
{ |
||||
|
public void ChangeScene(string sceneName) |
||||
|
{ |
||||
|
SceneManager.LoadScene(sceneName); |
||||
|
} |
||||
|
|
||||
|
public void OnApplicationQuit() |
||||
|
{ |
||||
|
Application.Quit(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
using System; |
||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.XR.Interaction.Toolkit; |
||||
|
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Special script that work with the XRExclusiveSocket script. This allow to define a SocketType and if that SocketType
|
||||
|
/// does not match the XRExclusiveSocket SocketType, this won't be accepted by the socket as a valid target
|
||||
|
/// </summary>
|
||||
|
[RequireComponent(typeof(XRBaseInteractable))] |
||||
|
public class SocketTarget : MonoBehaviour |
||||
|
{ |
||||
|
public string SocketType; |
||||
|
public XRInteractableEvent SocketedEvent; |
||||
|
public bool DisableSocketOnSocketed; |
||||
|
|
||||
|
void Awake() |
||||
|
{ |
||||
|
var interactable = GetComponent<XRBaseInteractable>(); |
||||
|
|
||||
|
interactable.onSelectEntered.AddListener(SelectedSwitch); |
||||
|
} |
||||
|
|
||||
|
public void SelectedSwitch(XRBaseInteractor interactor) |
||||
|
{ |
||||
|
var socketInteractor = interactor as XRExclusiveSocketInteractor; |
||||
|
|
||||
|
if(socketInteractor == null) |
||||
|
return; |
||||
|
|
||||
|
if(SocketType != socketInteractor.AcceptedType) |
||||
|
return; |
||||
|
|
||||
|
if (DisableSocketOnSocketed) |
||||
|
{ |
||||
|
//TODO : find a better way, delay feel very wrong
|
||||
|
StartCoroutine(DisableSocketDelayed(socketInteractor)); |
||||
|
} |
||||
|
|
||||
|
SocketedEvent.Invoke(interactor); |
||||
|
} |
||||
|
|
||||
|
IEnumerator DisableSocketDelayed(XRExclusiveSocketInteractor interactor) |
||||
|
{ |
||||
|
yield return new WaitForSeconds(0.5f); |
||||
|
interactor.socketActive = false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,108 @@ |
|||||
|
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; //첫 번째 손의 회전값 리셋
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.XR.Interaction.Toolkit; |
||||
|
|
||||
|
public class XRExclusiveSocketInteractor : XRSocketInteractor |
||||
|
{ |
||||
|
public string AcceptedType; //SocketTarget의 SocketType과 비교할 값
|
||||
|
|
||||
|
|
||||
|
public override bool CanSelect(XRBaseInteractable interactable) |
||||
|
{ |
||||
|
//이 소켓과 인터렉션하려는 사물의 SocketTarget을 가져오고
|
||||
|
SocketTarget socketTarget = interactable.GetComponent<SocketTarget>(); |
||||
|
|
||||
|
//SocketTarget이 없으면 선택 불가
|
||||
|
if (socketTarget == null) |
||||
|
return false; |
||||
|
|
||||
|
//baseClass에서도 선택할 수 있고, SocketTarget의 타입도 같으면 선택 가능하게
|
||||
|
return base.CanSelect(interactable) && (socketTarget.SocketType == AcceptedType); |
||||
|
} |
||||
|
|
||||
|
//선택 가능한 사물만이 Hover 가능하도록
|
||||
|
public override bool CanHover(XRBaseInteractable interactable) |
||||
|
{ |
||||
|
return CanSelect(interactable); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.XR.Interaction.Toolkit; |
||||
|
|
||||
|
public class XROffsetGrabInteractable : XRGrabInteractable |
||||
|
{ |
||||
|
//Pivot을 리셋시키기 위해 원래 로컬 위치, 회전 저장
|
||||
|
private Vector3 initialAttachLocalPos; |
||||
|
private Quaternion initialAttachLocalRot; |
||||
|
|
||||
|
protected virtual void Start() |
||||
|
{ |
||||
|
//attachTransform 이 없다면 만들어준다.
|
||||
|
if(!attachTransform) |
||||
|
{ |
||||
|
GameObject pivot = new GameObject("Attach Pivot"); //피봇용 빈 게임오브젝트를 만들어서
|
||||
|
pivot.transform.SetParent(transform, false); //자신의 자식으로 넣고, 위치를 0, 0, 0 으로
|
||||
|
attachTransform = pivot.transform; |
||||
|
} |
||||
|
|
||||
|
initialAttachLocalPos = attachTransform.localPosition; |
||||
|
initialAttachLocalRot = attachTransform.localRotation; |
||||
|
} |
||||
|
|
||||
|
//잡는 순간 실행되는 함수 오버라이드
|
||||
|
protected override void OnSelectEntering(XRBaseInteractor interactor) |
||||
|
{ |
||||
|
//직접 손으로 잡으면 Offset Grabbing
|
||||
|
if(interactor is XRDirectInteractor) |
||||
|
{ |
||||
|
attachTransform.position = interactor.attachTransform.position; |
||||
|
attachTransform.rotation = interactor.attachTransform.rotation; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
//그 외에는 Pivot값을 원래대로 리셋시켜줌
|
||||
|
attachTransform.localPosition = initialAttachLocalPos; |
||||
|
attachTransform.localRotation = initialAttachLocalRot; |
||||
|
} |
||||
|
|
||||
|
base.OnSelectEntering(interactor); |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue