Unity_3D Survival Game Development_2

💀LeeSY·2021년 3월 30일
0
  • 개발일지의 두 번째 파트로서 이번에는 1인칭 플레이어 생성 및 기본 움직임을 구현하였다.
  • 기본적으로 Capsule 객체를 선언하여 플레이어의 몸이라 가정하고 시작한다.
  • Capsule 객체 선언 후에는 Main Camera를 Capsule 객체 안에 포함시켜야 플레이어의 시야가 구현된다.

  1. 캐릭터 생성 - Collider : 충돌을 감지를 위한 컴포넌트

    • 스피어, 박스, 캡슐 등의 각종 사물체에 알맞은 형태의 다양한 Collider 모양이 존재한다.
  2. 캐릭터 생성 - Rigidbody : 강체를 뜻하는 단어로 오브젝트들에게 물리 효과를 적용시켜 주는 컴포넌트

  3. 캐릭터 생성 - 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] : 변수를 인스펙터에서 접근 가능하지만 외부 스크립트에서는 접근이 불가능하게 방지하는 것

-> 위 처럼 [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();
    }

▣ 최종적으로 캐릭터의 상하좌우 고개 전환과 점프, 달리기, 앉기 기본 동작 구현 완료

profile
A little strange but passionate, sincere hard worker.

0개의 댓글