캐릭터 생성 - Collider : 충돌을 감지를 위한 컴포넌트
캐릭터 생성 - Rigidbody : 강체를 뜻하는 단어로 오브젝트들에게 물리 효과를 적용시켜 주는 컴포넌트
캐릭터 생성 - PlayerBasicControl.cs
플레이어에 대한 기본적인 움직임 동작을 구현할 스크립트이다.
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 isWalk = false;
private bool isRun = false;
private bool isCrouch = false;
private bool isGround = true;
// 움직임 체크 변수
private Vector3 lastPos;
// 앉았을 때 얼마나 앉을지 결정하는 변수
[SerializeField]
private float crouchPosY;
private float originPosY;
private float applyCrouchPosY;
// 땅 착지여부
private CapsuleCollider capsuleCollider;
// 민감도
[SerializeField]
private float lookSens;
// 카메라 한계
[SerializeField]
private float cameraRotationLimit;
private float currentCameraRotationX = 0f;
-> 위 처럼 [SerializeField]로 선언된 요소들이 인스펙터 창에서 값을 입력할 수 있도록 표시된다.
상하/좌우 카메라 : 1인칭 캐릭터가 마우스를 통해 상하좌우 모든 각도로 자유롭게 시야 전환이 가능하도록 구현
private void CharacterRotation() //좌우 캐릭터 회전
{
float _yRotation = Input.GetAxisRaw("Mouse X");
Vector3 _characterRotationY = new Vector3(0f, _yRotation, 0f) * lookSensitivity;
myRigid.MoveRotation(myRigid.rotation * Quaternion.Euler(_characterRotationY));
}
private void CameraRotation() // 상하 카메라 회전
{
float _xRotation = Input.GetAxisRaw("Mouse Y");
float _cameraRotationX = _xRotation * lookSensitivity;
currentCameraRotationX -= _cameraRotationX;
currentCameraRotationX = Mathf.Clamp(currentCameraRotationX, -cameraRotationLimit, cameraRotationLimit);
theCamera.transform.localEulerAngles = new Vector3(currentCameraRotationX, 0f, 0f);
}
-> GetAxisRaw : 키보드나 조이스틱의 입력값에 따라 -1, 0, 1의 값을 가지는 메소드
-> Quaternion.Euler : Euler는 x, y, z 3개의 축을 기준으로 하여 0 ~ 360도 만큼 회전시키는 좌표계이다. 사물체의 원활한 시야 전환을 위하여 Euler로 캐릭터의 좌표값을 선언하고 Quaternion을 통해 유니티 객체의 rotarion값을 저장한다.
자연스러운 앉기 동작 구현
앉기 동작을 구현하는데에 있어서 마치 화면 전환이 되는듯한 앉기 동작의 문제점 발견
-> 이에따라 자연스러운 앉기 동작 시스템을 구현
IEnumerator CrouchCoroutine() // 부드러운 앉기 동작
{
float _posY = theCamera.transform.localPosition.y;
int count = 0;
while (_posY != applyCrouchPosY)
{
count++;
_posY = Mathf.Lerp(_posY, applyCrouchPosY, 0.3f);
theCamera.transform.localPosition = new Vector3(0, _posY, 0);
if (count > 15)
break;
yield return null;
}
theCamera.transform.localPosition = new Vector3(0, applyCrouchPosY, 0f);
}
-> IEnumerator : Custom state를 만들어 각종 반복문으로 편리하게 사용하거나 Coroutine으로 사용하는 Interface의 일종
-> Coroutine : 한 컴포넌트 내에서 Update 함수와 따로 일시적으로 돌아가는 서브 동작을 구현하거나, 어떤 다른 작업이 처리되는 것을 기다리는 기능을 구현하는데 쓰이는 것
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 MoveCheck() // 움직임 체크
{
if (!isRun && !isCrouch && isGround)
{
if (Vector3.Distance(lastPos, transform.position) >= 0.01f)
isWalk = true;
else
isWalk = false;
theCrosshair.WalkingAnimation(isWalk);
lastPos = transform.position;
}
}
-> 수평적 움직임, 수직적 움직임 모두를 구현하여 Vector3 값에 저장하고 객체 선언이 같이 선언한 Rigid에 적용시킨다.
-> 달리기, 앉기, 점프 움직이 구현될 시 걷기 상태를 변화시켜 움직임의 변화를 체크한다.
private void stJump() // 점프 시도
{
if (Input.GetKeyDown(KeyCode.Space) && isGround)
{
Jump();
}
}
private void Jump() // 점프 동작
{
// 앉은 상태에서 점프 시 점프 해제
if (isCrouch)
Crouch();
myRigid.velocity = transform.up * jumpForce;
}
private void Running() // 달리기 실행
{
// 앉은 상태에서 점프 시 점프 해제
if (isCrouch)
Crouch();
theGunController.CancelFineSight();
isRun = true;
theCrosshair.RunningAnimation(isRun);
applySpeed = runSpeed;
}
private void RunningX() // 달리기 취소
{
isRun = false;
theCrosshair.RunningAnimation(isRun);
applySpeed = walkSpeed;
}
private void stCrouch() // 앉기 시도
{
if (Input.GetKeyDown(KeyCode.LeftControl))
{
Crouch();
}
}
private void Crouch() // 앉기 동작
{
isCrouch = !isCrouch;
theCrosshair.CrouchingAnimation(isCrouch);
if (isCrouch)
{
applySpeed = crouchSpeed;
applyCrouchPosY = crouchPosY;
}
else
{
applySpeed = walkSpeed;
applyCrouchPosY = originPosY;
}
StartCoroutine(CrouchCoroutine());
} // 앉는 상태가 아니면 walkSpeed로 변환
Start()
Capsule 1인칭 캐릭터에 스크립트 적용을 위해 GetComponent 선언
applySpeed 등 변화량을 담을 변수값을 초기화
void Start()
{
capsuleCollider = GetComponent<CapsuleCollider>();
myRigid = GetComponent<Rigidbody>();
// 초기화
applySpeed = walkSpeed;
originPosY = theCamera.transform.localPosition.y;
applyCrouchPosY = originPosY;
}
Update() : 스크립트에 만든 여러 동작 함수를 호출
void Update()
{
IsGround();
stJump();
stRun();
stCrouch();
Move();
MoveCheck();
CameraRotation();
CharacterRotation();
}
▣ 최종적으로 캐릭터의 상하좌우 고개 전환과 점프, 달리기, 앉기 기본 동작 구현 완료