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.
83 lines
3.6 KiB
83 lines
3.6 KiB
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);
|
|
}
|
|
}
|