점프, 앉기, 달리기 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
// 스피드 조정 변수
[SerializeField]
private float walkSpeed; // 걸음속도
[SerializeField]
private float runSpeed; // 달리기속도
[SerializeField]
private float crouchSpeed; // 앉기상태에서의 속도
private float applySpeed; // 임시속도 저장변수
[SerializeField]
private float jumpForce; // 점프
// 상태 변수
private bool isCrouch = false; // 앉아있는가?
private bool isRun = false; // 달리고 있는가?
private bool isGround = true; // 땅에 붙어있는가?
// 앉기상태, 서있는상태 높이변수
[SerializeField]
private float crouchPosY; //앉기상태 시선
private float originPosY; //서있는상태 시선
private float applycrouchPosY;
// 땅 착지 여부
private CapsuleCollider capsuleCollider;
// 민감도
[SerializeField]
private float lookSensitivity; // 마우스 민감도
// 카메라 한계
[SerializeField]
private float cameraRotationLimit; // 위아래 시선 각도 제한
private float currentCameraRotationX = 0;
// 필요한 컴포넌트
[SerializeField]
private Camera theCamera;
private Rigidbody myRigid;
void Start() // 시작
{
capsuleCollider = GetComponent<CapsuleCollider>(); // 캡슐 로드
myRigid = GetComponent<Rigidbody>(); // Rigidbody 속성 가지고 있는 컴포넌트 로드
applySpeed = walkSpeed;
// 초기화
originPosY = theCamera.transform.localPosition.y; //서있는상태 카메라 상대위치 저장
applycrouchPosY = originPosY;
}
void Update() // 대략 1초에 60프레임 반복
{
IsGround();
TryJump();
TryRun(); // 달리기
TryCrouch(); // 앉기
Move(); // 캐릭터 움직임
CameraRotation(); // 카메라 상하각도
CharacterRotation(); // 캐릭터 좌우각도
}
// 앉기 시도
private void TryCrouch()
{
if(Input.GetKeyDown(KeyCode.LeftControl))
{
Crouch();
}
}
// 앉기 동작
private void Crouch()
{
isCrouch = !isCrouch; // 앉기상태 변환
if(isCrouch)
{
applySpeed = crouchSpeed;
applycrouchPosY = crouchPosY;
}
else
{
applySpeed = walkSpeed;
applycrouchPosY = originPosY;
}
StartCoroutine(CrouchCoroutine()); //카메라 위치변경
}
// 부드러운 앉기 동작
IEnumerator CrouchCoroutine() // 카메라 위치변경
{
float _posY=theCamera.transform.localPosition.y;
int count = 0; // 무한히 실행되므로 카운터를 통해 종료
while(_posY!=applycrouchPosY) //_posY가 applycrouchPosY와 같을 때 까지 반복
{
count++;
_posY = Mathf.Lerp(_posY, applycrouchPosY, 0.3f); // 0.3 속도로 서서히 변경
theCamera.transform.localPosition = new Vector3(0, _posY, 0); // 좌표 수정
if (count > 15) // 15번 반복 후 종료
break;
yield return null;
}
theCamera.transform.localPosition = new Vector3(0, applycrouchPosY, 0); // 좌표 완전히 수정
}
// 지면 체크
private void IsGround()
{
isGround = Physics.Raycast(transform.position, Vector3.down, capsuleCollider.bounds.extents.y+0.1f); // 캡슐 중간 높이에서 아래로 레이저를 쏴서 땅에 닿으면 true
}
// 점프 시도
private void TryJump()
{
if(Input.GetKeyDown(KeyCode.Space) && isGround) // 스페이스 키를 누르고 땅에 붙어있는 경우
{
Jump();
}
}
// 점프 동작
private void Jump()
{
if (isCrouch) // 앉기상태에서 점프할 경우 앉기상태 해제
Crouch();
myRigid.velocity = transform.up * jumpForce;
}
// 달리기 시도
private void TryRun()
{
if(Input.GetKey(KeyCode.LeftShift)) // 왼쪽 쉬프트를 누를때
{
Running(); // 달리기
}
if(Input.GetKeyUp(KeyCode.LeftShift)) // 왼쪽 쉬프트를 안누를때
{
RunningCancle(); // 달리기 취소
}
}
// 달리기 동작
private void Running()
{
if (isCrouch) // 앉은상태에서 달리기 누르면 일어서서 달림
Crouch();
isRun = true;
applySpeed = runSpeed; // 달리기 속도 적용
}
private void RunningCancle()
{
isRun = false;
applySpeed = walkSpeed; // 걷기 속도 적용
}
// 움직임 실행
private void Move()
{
float _moveDirX = Input.GetAxisRaw("Horizontal"); // 좌우 키
float _moveDirZ = Input.GetAxisRaw("Vertical"); // 상하 키
Vector3 _moveHorizontal = transform.right * _moveDirX; // 좌우 좌표
Vector3 _moveVertical = transform.forward * _moveDirZ; // 상하 좌표
Vector3 _velocity = (_moveHorizontal + _moveVertical).normalized * applySpeed; // 속도
myRigid.MovePosition(transform.position + _velocity * Time.deltaTime); // 속도에 따른 위치이동
}
// 좌우 캐릭터 회전
private void CharacterRotation()
{
float _yRotation = Input.GetAxisRaw("Mouse X"); // 마우스는 좌우가 X축이고 캐릭터는 좌우가 Y축이다.
Vector3 _characterRotationY = new Vector3(0f, _yRotation, 0f)*lookSensitivity;
myRigid.MoveRotation(myRigid.rotation * Quaternion.Euler(_characterRotationY));
}
// 상하 카메라 회전
private void CameraRotation()
{
float _xRotation = Input.GetAxisRaw("Mouse Y"); // 마우스는 상하가 Y축이고 카메라는 상하가 X축이다.
float _cameraRotationX = _xRotation * lookSensitivity; // 상하 민감도
currentCameraRotationX -= _cameraRotationX; // 상하각도 값
currentCameraRotationX = Mathf.Clamp(currentCameraRotationX, -cameraRotationLimit, cameraRotationLimit); // 각도 제한
theCamera.transform.localEulerAngles = new Vector3(currentCameraRotationX, 0f, 0f); // 상하각도 업데이트
}
}
'유니티 개발' 카테고리의 다른 글
3D 캐릭터 팔, 주먹 동작 구현 (0) | 2021.08.17 |
---|---|
지형제작 (나무, 잔디, 돌) (0) | 2021.08.17 |
3D 캐릭터 움직임 기초 (0) | 2021.08.16 |
2D 상하좌우 이동 (0) | 2021.08.16 |
댓글