Chapter 4. 체력 : Status UI

Date:     Updated:

카테고리:

태그:

인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click

Chapter 4. 허기와 갈증, 스태미나와 체력

🚖 상태 UI 만들기

이미지 UI 생성

image

  • 하나의 부모 이미지에 6 개의 자식 이미지를 만든다.
    • Status_Base
      • HP 나타내는 이미지
      • DP 나타내는 이미지
      • SP 나타내는 이미지
      • 배고픔 나타내는 이미지
      • 목마름 나타내는 이미지
      • 만족감 나타내는 이미지

image

Status_Base 부모 이미지

image

  • Status_Base 위에 배치한 6 개의 자식 이미지
    • 가운데 초록 바는 SP 나타내는 이미지다.

이미지 컴포넌트 설정

image

  • Source Image
    • 텍스처 타입을 Sprite(2D and UI)로 적용시켜주어야 이미지 UI 에 할당할 수 있다.
    • Max Size를 이미지 크기에 맞게 설정
  • Width, Height는 실제 Source Image 이미지 크기와 동일하게 해준다.
  • 알맞는 Status_Base 자리에 배치될 수 있도록 위치시켜 준다.
  • Image Type
    • Filled 👉 상태 값에 따라 이미지 게이지가 채워지도록 한다. (어떻게 동작하는지 Fill Amount를 이리저리 드래그 해서 확인해보자)
      • dp, sp, hp는 상태 값에 따라 아래서부터 시작하여 수직 방향으로 이미지가 채워져 그려질 수 있도록 Vertical, Bottom 으로 설정 해 준다.
      • hungry, thirsy는 상태 값에 따라 90 도 방향(오른쪽)에서 시작하여 시계 방향으로 360 도로 이미지가 채워져 그려질 수 있도록 Radial 360, Right, Clockwise체크 로 설정해주자.
      • satisfy는 상태 값에 따라 270 도 방향(왼쪽)에서 시작하여 시계 방향으로 360 도로 이미지가 채워져 그려질 수 있도록 Radial 360, Left, Clockwise체크 로 설정해주자.


🚖 상태 업데이트

모든 상태의 공통 부분

📜StatusController.cs

    // 필요한 이미지
    [SerializeField]
    private Image[] images_Gauge;

    // 각 상태를 대표하는 인덱스
    private const int HP = 0, DP = 1, SP = 2, HUNGRY = 3, THIRSTY = 4, SATISFY = 5;

    void Start()
    {
        currentHp = hp;
        currentDp = dp;
        currentSp = sp;
        currentHungry = hungry;
        currentThirsty = thirsty;
        currentSatisfy = satisfy;
    }

    void Update()
    {
        Hungry();
        Thirsty();
        SPRechargeTime();
        SPRecover();
        GaugeUpdate();
    }

    private void GaugeUpdate()
    {
        images_Gauge[HP].fillAmount = (float)currentHp / hp;
        images_Gauge[SP].fillAmount = (float)currentSp / sp;
        images_Gauge[DP].fillAmount = (float)currentHp / dp;
        images_Gauge[HUNGRY].fillAmount = (float)currentHungry / hungry;
        images_Gauge[THIRSTY].fillAmount = (float)currentThirsty / thirsty;
        images_Gauge[SATISFY].fillAmount = (float)currentSatisfy / satisfy;
    }
  • images_Gauge
    • 각각의 상태를 대표하는 이미지 6 개가 배열로 관리 될 것
    • enum 처럼 배열의 인덱스가 각각 어떤 상태인지 알 수 있도록 아래와 같이 선언해주었다.
      private const int HP = 0, DP = 1, SP = 2, HUNGRY = 3, THIRSTY = 4, SATISFY = 5;
      
  • Start()
    • 게임이 시작 되면 6 개의 현재 상태값들 초기화
      • 최대 값으로 초기화 한다. 현재 체력을 최대 체력으로 업뎃 등등
  • Update()
    • 매 프레임마다 자동으로 계속해서 업데이트 되야할 것은 1️⃣ 배고픔, 2️⃣ 목마름, 3️⃣ SP 회복해도 될지 시간 업뎃, 4️⃣ SP 회복(스태미나) 이며 마지막으로 5️⃣ 이미지 게이지 업데이트

    • 배고픔, 목마름은 일정 시간 지날 때마다 감소되게 할 것이라 그렇다.
  • GaugeUpdate()
    • 이미지 게이지 업데이트
      • (현재 상태 값 / 최대 상태 값) 👉 이 값만큼 해당 이미지를 채운다.
    • Image 의 fillAmount 이미지 채울 값. 이미지 컴포넌트에 Filled 슬라이더 값


1️⃣ 배고픔

📜StatusController.cs

    // 배고픔
    [SerializeField]
    private int hungry;  // 최대 배고픔. 유니티 에디터 슬롯에서 지정할 것.
    private int currentHungry;

    // 배고픔이 줄어드는 속도
    [SerializeField]
    private int hungryDecreaseTime;
    private int currentHungryDecreaseTime;

    private void Hungry()
    {
        if (currentHungry > 0)
        {
            if (currentHungryDecreaseTime <= hungryDecreaseTime)
                currentHungryDecreaseTime++;
            else
            {
                currentHungry--;
                currentHungryDecreaseTime = 0;
            }
        }
        else
            Debug.Log("배고픔 수치가 0 이 되었습니다.");
    }

    public void IncreaseHungry(int _count)
    {
        if (currentHungry + _count < hungry)
            currentHungry += _count;
        else
            currentHungry = hungry;
    }

    public void DecreaseHungry(int _count)
    {
        if (currentHungry - _count < 0)
            currentHungry = 0;
        else
            currentHungry -= _count;
    }
  • Hungry()
    • 업데이트 문 안에서 매 프레임마다 실행 된다.
      • 매프레임마다 일정 시간 씩 지나면 자연스럽게 배고픔 수치가 떨어지도록 할 것이다.
    • 현재 배고픔 수치가 0 보다 크다면 👉
      • currentHungryDecreaseTimehungryDecreaseTime가 도달 했다면 현재 배고픔 currentHungry 수치를 감소시키고 currentHungryDecreaseTime을 다시 0 으로 만든다.
      • currentHungryDecreaseTimehungryDecreaseTime가 도달 하지 못했다면 계속 1 씩 증가하도록 한다.
    • 현재 배고픔 수치가 0 이하라면
      • 플레이어가 죽어서 게임이 종료되는 등등의 처리를 해주면 좋을 것 같다.
  • IncreaseHungry(int _count)
    • 다른 곳에서 배고픔 증가 처리를 하고자 할 때 사용할 public 함수
      • 현재 배고픔에서 인수로 들어온 _count 만큼 증가시킨다.
        • 단, 현재 배고픔에서 _count를 더한다고 가정했을 때 최대 배고픔 hungry를 넘는다면 현재 배고픔을 최대 배고픔인 hungry로 설정해준다.
        • 그런게 아니라면 그냥 현재 배고픔에서 _count를 더해준다.
  • DecreaseHungry(int _count)
    • 다른 곳에서 배고픔 증가 처리를 하고자 할 때 사용할 public 함수
      • 현재 배고픔에서 인수로 들어온 _count 만큼 차감시킨다.
        • 단, 현재 배고픔에서 _count를 뺀다고 가정했을 때 0 보다 작아진다면 현재 배고픔을 음수가 되지 않도록 0으로 설정해준다.
        • 그런게 아니라면 그냥 현재 배고픔에서 _count를 빼준다.


2️⃣ 목마름

📜StatusController.cs

    // 목마름
    [SerializeField]
    private int thirsty;  // 최대 목마름. 유니티 에디터 슬롯에서 지정할 것.
    private int currentThirsty;

    // 목마름이 줄어드는 속도
    [SerializeField]
    private int thirstyDecreaseTime;
    private int currentThirstyDecreaseTime;

    private void Thirsty()
    {
        if (currentThirsty > 0)
        {
            if (currentThirstyDecreaseTime <= thirstyDecreaseTime)
                currentThirstyDecreaseTime++;
            else
            {
                currentThirsty--;
                currentThirstyDecreaseTime = 0;
            }
        }
        else
            Debug.Log("목마름 수치가 0 이 되었습니다.");
    }

    public void IncreaseThirsty(int _count)
    {
        if (currentThirsty + _count < thirsty)
            currentThirsty += _count;
        else
            currentThirsty = thirsty;
    }

    public void DecreaseThirsty(int _count)
    {
        if (currentThirsty - _count < 0)
            currentThirsty = 0;
        else
            currentThirsty -= _count;
    }
  • Thirsty()
    • 업데이트 문 안에서 매 프레임마다 실행 된다.
      • 매프레임마다 일정 시간 씩 지나면 자연스럽게 목마름 수치가 떨어지도록 할 것이다.
  • 다른 것들도 다 배고픔이랑 똑같다.


3️⃣ 만족감

📜StatusController.cs

    // 만족감
    [SerializeField]
    private int satisfy;  // 최대 만족감. 유니티 에디터 슬롯에서 지정할 것.
    private int currentSatisfy;

나머지 구현 아직 X


4️⃣ HP

📜StatusController.cs

    // 체력
    [SerializeField]
    private int hp;  // 최대 체력. 유니티 에디터 슬롯에서 지정할 것.
    private int currentHp;

    public void IncreaseHP(int _count)
    {
        if (currentHp + _count < hp)
            currentHp += _count;
        else
            currentHp = hp;
    }

    public void DecreaseHP(int _count)
    {
        if(currentDp > 0)
        {
            DecreaseDP(_count);
            return;
        }
        currentHp -= _count;

        if (currentHp <= 0)
            Debug.Log("캐릭터의 체력이 0이 되었습니다!!");
    }
  • IncreaseHP(int _count)
    • 배고픔 목마름과 비슷
  • DecreaseHP(int _count)
    • 방어력이 있을 땐 체력을 깎지 않고 대신 방어력을 깎고 종료시킨다.
      • DecreaseDP(_count) 호출
    • 방어력이 없을 때만 체력을 깎는다.


5️⃣ DP

방어력

📜StatusController.cs

    // 방어력
    [SerializeField]
    private int dp;  // 최대 방어력. 유니티 에디터 슬롯에서 지정할 것.
    private int currentDp;

    public void IncreaseDP(int _count)
    {
        if (currentDp + _count < dp)
            currentDp += _count;
        else
            currentDp = dp;
    }

    public void DecreaseDP(int _count)
    {
        currentDp -= _count;

        if (currentDp <= 0)
            Debug.Log("캐릭터의 방어력이 0이 되었습니다!!");
    }


6️⃣ SP

스태미나

📜StatusController.cs

    // 스태미나
    [SerializeField]
    private int sp;  // 최대 스태미나. 유니티 에디터 슬롯에서 지정할 것.
    private int currentSp;

    // 스태미나 증가량
    [SerializeField]
    private int spIncreaseSpeed;

    // 스태미나 재회복 딜레이 시간
    [SerializeField]
    private int spRechargeTime;  
    private int currentSpRechargeTime;

    // 스태미나 감소 여부
    private bool spUsed;


    public void DecreaseStamina(int _count)
    {
        spUsed = true;
        currentSpRechargeTime = 0;

        if (currentSp - _count > 0)
        {
            currentSp -= _count;
        }
        else
            currentSp = 0;
    }

    private void SPRechargeTime()
    {
        if (spUsed)
        {
            if (currentSpRechargeTime < spRechargeTime)
                currentSpRechargeTime++;
            else
                spUsed = false;
        }
    }

    private void SPRecover()
    {
        if (!spUsed && currentSp < sp)
        {
            currentSp += spIncreaseSpeed;
        }
    }

    public int GetCurrentSP()
    {
        return currentSp;
    }
  1. 스태미나는 점프, 달리기에 의해 감소된다.
  2. 스태미나가 0 이 되면 점프, 달리기를 할 수 없다.
  3. 감소된 스태미나는 일정 시간이 지나고 난 후에 최대 스태미나로 회복을 시작한다.
  • DecreaseStamina(int _count)
    • 스태미나가 감소 되었었다는 표시를 해주기 위해 spUsed을 True로 업데이트 해준다.
    • 인수만큼 스태미나를 차감해준다. 음수가 되자 않도록 0 보다 떨어지면 0 으로 설정한다.
  • SPRechargeTime()
    • 업데이트 문 안에서 매프레임마다 실행된다.
    • 스태미나가 감소된 이후 ~ 스태미나가 재충전 될 수 있는 시작 점 까지의 시간을 재어 스태미나가 다시 재충전 될 수 있는지를 확인한다.
    • 스태미나가 감소된적이 있는 경우에만 if (spUsed)
      • currentSpRechargeTimespRechargeTime에 도달할 때까지 1 씩 증가시킨다. 도달했다면 spUsed를 False로 업데이트 한다.
  • SPRecover()
    • 업데이트 문 안에서 매프레임마다 실행된다.
    • 재충전 할 수 있을 타이밍이고 (!spUsed) 현재 스태미나가 최대 스태미나를 넘지 않는다면
      • spIncreaseSpeed만큼 스테미나를 매 프레임마다 회복 시켜 나간다.
  • GetCurrentSP()
    • 현재 스태미나 리턴


📜PlayerController.cs


private StatusController theStatusController;

    void Start()
    {
        // ...
        theStatusController = FindObjectOfType<StatusController>();
        // ...
    }

    // 점프 시도
    private void TryJump()
    {
        if (Input.GetKeyDown(KeyCode.Space) && isGround && theStatusController.GetCurrentSP() > 0)
        {
            Jump();
        }
    }

    // 점프
    private void Jump()
    {
        if (isCrouch)
            Crouch();

        theStatusController.DecreaseStamina(100);
        myRigid.velocity = transform.up * jumpForce;
    }

    // 달리기 시도
    private void TryRun()
    {
        if (Input.GetKey(KeyCode.LeftShift) && theStatusController.GetCurrentSP() > 0)
        {
            Running();
        }
        if (Input.GetKeyUp(KeyCode.LeftShift) || theStatusController.GetCurrentSP() <= 0)
        {
            RunningCancel();
        }
    }

    // 달리기
    private void Running()
    {
        if (isCrouch)
            Crouch();

        theGunController.CancelFineSight();

        isRun = true;
        theCrosshair.RunningAnimation(isRun);
        theStatusController.DecreaseStamina(10);
        applySpeed = runSpeed;
    }
  • Start() 에서 theStatusControlelr에 📜StatusController.cs 가져 오기
  • 점프를 시도하려 할 때
    • theStatusController.GetCurrentSP() > 0 현재 스태미나가 0 보다 클 때만 가능하도록 한다.
  • 점프 할 때
    • theStatusController.DecreaseStamina(100) 스태미나 값 100 씩 감소시킴
  • 달리기 시도하려 할 때
    • theStatusController.GetCurrentSP() > 0 현재 스태미나가 0 보다 클 때만 가능하도록 한다.
    • theStatusController.GetCurrentSP() <= 0 현재 스태미나가 0 이하일 때도 RunningCancel() 을 실행하도록 하자.
      • 더 이상 달리지 못하도록
  • 점프 할 때
    • theStatusController.DecreaseStamina(100) 스태미나 값 10 씩 감소시킴


🚔 전체 코드

📜StatusController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class StatusController : MonoBehaviour
{
    // 체력
    [SerializeField]
    private int hp;  // 최대 체력. 유니티 에디터 슬롯에서 지정할 것.
    private int currentHp;

    // 스태미나
    [SerializeField]
    private int sp;  // 최대 스태미나. 유니티 에디터 슬롯에서 지정할 것.
    private int currentSp;

    // 스태미나 증가량
    [SerializeField]
    private int spIncreaseSpeed;

    // 스태미나 재회복 딜레이 시간
    [SerializeField]
    private int spRechargeTime;  
    private int currentSpRechargeTime;

    // 스태미나 감소 여부
    private bool spUsed;

    // 방어력
    [SerializeField]
    private int dp;  // 최대 방어력. 유니티 에디터 슬롯에서 지정할 것.
    private int currentDp;

    // 배고픔
    [SerializeField]
    private int hungry;  // 최대 배고픔. 유니티 에디터 슬롯에서 지정할 것.
    private int currentHungry;

    // 배고픔이 줄어드는 속도
    [SerializeField]
    private int hungryDecreaseTime;
    private int currentHungryDecreaseTime;

    // 목마름
    [SerializeField]
    private int thirsty;  // 최대 목마름. 유니티 에디터 슬롯에서 지정할 것.
    private int currentThirsty;

    // 목마름이 줄어드는 속도
    [SerializeField]
    private int thirstyDecreaseTime;
    private int currentThirstyDecreaseTime;

    // 만족감
    [SerializeField]
    private int satisfy;  // 최대 만족감. 유니티 에디터 슬롯에서 지정할 것.
    private int currentSatisfy;

    // 필요한 이미지
    [SerializeField]
    private Image[] images_Gauge;

    // 각 상태를 대표하는 인덱스
    private const int HP = 0, DP = 1, SP = 2, HUNGRY = 3, THIRSTY = 4, SATISFY = 5;

    void Start()
    {
        currentHp = hp;
        currentDp = dp;
        currentSp = sp;
        currentHungry = hungry;
        currentThirsty = thirsty;
        currentSatisfy = satisfy;
    }

    void Update()
    {
        Hungry();
        Thirsty();
        SPRechargeTime();
        SPRecover();
        GaugeUpdate();
    }

    private void GaugeUpdate()
    {
        images_Gauge[HP].fillAmount = (float)currentHp / hp;
        images_Gauge[SP].fillAmount = (float)currentSp / sp;
        images_Gauge[DP].fillAmount = (float)currentHp / dp;
        images_Gauge[HUNGRY].fillAmount = (float)currentHungry / hungry;
        images_Gauge[THIRSTY].fillAmount = (float)currentThirsty / thirsty;
        images_Gauge[SATISFY].fillAmount = (float)currentSatisfy / satisfy;
    }

    private void Hungry()
    {
        if (currentHungry > 0)
        {
            if (currentHungryDecreaseTime <= hungryDecreaseTime)
                currentHungryDecreaseTime++;
            else
            {
                currentHungry--;
                currentHungryDecreaseTime = 0;
            }
        }
        else
            Debug.Log("배고픔 수치가 0 이 되었습니다.");
    }

    private void Thirsty()
    {
        if (currentThirsty > 0)
        {
            if (currentThirstyDecreaseTime <= thirstyDecreaseTime)
                currentThirstyDecreaseTime++;
            else
            {
                currentThirsty--;
                currentThirstyDecreaseTime = 0;
            }
        }
        else
            Debug.Log("목마름 수치가 0 이 되었습니다.");
    }

    public void IncreaseHP(int _count)
    {
        if (currentHp + _count < hp)
            currentHp += _count;
        else
            currentHp = hp;
    }

    public void DecreaseHP(int _count)
    {
        if(currentDp > 0)
        {
            DecreaseDP(_count);
            return;
        }
        currentHp -= _count;

        if (currentHp <= 0)
            Debug.Log("캐릭터의 체력이 0이 되었습니다!!");
    }

    public void IncreaseDP(int _count)
    {
        if (currentDp + _count < dp)
            currentDp += _count;
        else
            currentDp = dp;
    }

    public void DecreaseDP(int _count)
    {
        currentDp -= _count;

        if (currentDp <= 0)
            Debug.Log("캐릭터의 방어력이 0이 되었습니다!!");
    }

    public void IncreaseHungry(int _count)
    {
        if (currentHungry + _count < hungry)
            currentHungry += _count;
        else
            currentHungry = hungry;
    }

    public void DecreaseHungry(int _count)
    {
        if (currentHungry - _count < 0)
            currentHungry = 0;
        else
            currentHungry -= _count;
    }

    public void IncreaseThirsty(int _count)
    {
        if (currentThirsty + _count < thirsty)
            currentThirsty += _count;
        else
            currentThirsty = thirsty;
    }

    public void DecreaseThirsty(int _count)
    {
        if (currentThirsty - _count < 0)
            currentThirsty = 0;
        else
            currentThirsty -= _count;
    }

    public void DecreaseStamina(int _count)
    {
        spUsed = true;
        currentSpRechargeTime = 0;

        if (currentSp - _count > 0)
        {
            currentSp -= _count;
        }
        else
            currentSp = 0;
    }

    private void SPRechargeTime()
    {
        if (spUsed)
        {
            if (currentSpRechargeTime < spRechargeTime)
                currentSpRechargeTime++;
            else
                spUsed = false;
        }
    }

    private void SPRecover()
    {
        if (!spUsed && currentSp < sp)
        {
            currentSp += spIncreaseSpeed;
        }
    }

    public int GetCurrentSP()
    {
        return currentSp;
    }
}


📜PlayerController.cs

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 isWalk = false; 
    private bool isRun = false;
    private bool isGround = true;
    private bool isCrouch = false;

    // 움직임 체크 변수
    private Vector3 lastPos;  // 전 프레임의 위치. 현재 프레임의 위치와 비교했을 때 달라지면 움직임이 있었던 것이다.


    // 앉았을 때 얼마나 앉을지 결정하는 변수
    [SerializeField]
    private float crouchPosY;
    private float originPosY;
    private float applyCrouchPosY;

    // 민감도
    [SerializeField]
    private float lookSensitivity;  

    // 카메라 한계
    [SerializeField]
    private float cameraRotationLimit;  
    private float currentCameraRotationX; 

    // 필요한 컴포넌트
    [SerializeField]
    private Camera theCamera; 
    private Rigidbody myRigid;
    private CapsuleCollider capsuleCollider;
    private GunController theGunController;
    private Crosshair theCrosshair;
    private StatusController theStatusController;

    void Start()
    {
        // 컴포넌트 할당
        capsuleCollider = GetComponent<CapsuleCollider>();
        myRigid = GetComponent<Rigidbody>();
        theGunController = FindObjectOfType<GunController>();
        theCrosshair = FindObjectOfType<Crosshair>();
        theStatusController = FindObjectOfType<StatusController>();

        applySpeed = walkSpeed;
        originPosY = theCamera.transform.localPosition.y;
        applyCrouchPosY = originPosY;
    }

    void Update()  
    {
        IsGround();
        TryJump();
        TryRun();
        TryCrouch();
        Move();
        MoveCheck();
        CameraRotation();
        CharacterRotation();
    }

    // 지면 체크
    private void IsGround()
    {
        isGround = Physics.Raycast(transform.position, Vector3.down, capsuleCollider.bounds.extents.y + 0.1f);
        theCrosshair.JumpingAnimation(!isGround);
    }

    // 점프 시도
    private void TryJump()
    {
        if (Input.GetKeyDown(KeyCode.Space) && isGround && theStatusController.GetCurrentSP() > 0)
        {
            Jump();
        }
    }

    // 점프
    private void Jump()
    {
        if (isCrouch)
            Crouch();

        theStatusController.DecreaseStamina(100);
        myRigid.velocity = transform.up * jumpForce;
    }

    // 달리기 시도
    private void TryRun()
    {
        if (Input.GetKey(KeyCode.LeftShift) && theStatusController.GetCurrentSP() > 0)
        {
            Running();
        }
        if (Input.GetKeyUp(KeyCode.LeftShift) || theStatusController.GetCurrentSP() <= 0)
        {
            RunningCancel();
        }
    }

    // 달리기
    private void Running()
    {
        if (isCrouch)
            Crouch();

        theGunController.CancelFineSight();

        isRun = true;
        theCrosshair.RunningAnimation(isRun);
        theStatusController.DecreaseStamina(10);
        applySpeed = runSpeed;
    }

    // 달리기 취소
    private void RunningCancel()
    {
        isRun = false;
        theCrosshair.RunningAnimation(isRun);
        applySpeed = walkSpeed;
    }

    // 앉기 시도
    private void TryCrouch()
    {
        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());
    }

    // 부드러운 앉기 동작
    IEnumerator CrouchCoroutine()
    {
        float _posY = theCamera.transform.localPosition.y;
        int count = 0;

        while(_posY != applyCrouchPosY)
        {
            count++;
            _posY = Mathf.Lerp(_posY, applyCrouchPosY, 0.2f);
            theCamera.transform.localPosition = new Vector3(0, _posY, 0);
            if(count > 15)
                break;
            yield return null;
        }
        theCamera.transform.localPosition = new Vector3(0, applyCrouchPosY, 0);
    }

    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;
        }  
    }


    private bool pauseCameraRotation = false;

    private void CameraRotation() 
    {
        if (!pauseCameraRotation)
        {
            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);
        }
    }

    public IEnumerator TreeLookCoroutine(Vector3 _target)
    {
        pauseCameraRotation = true;

        Quaternion direction = Quaternion.LookRotation(_target - theCamera.transform.position);
        Vector3 eulerValue = direction.eulerAngles;
        float destinationX = eulerValue.x;

        while(Mathf.Abs(destinationX - currentCameraRotationX) >= 0.5f)
        {
            eulerValue = Quaternion.Lerp(theCamera.transform.localRotation, direction, 0.3f).eulerAngles;
            theCamera.transform.localRotation = Quaternion.Euler(eulerValue.x, 0f, 0f);
            currentCameraRotationX = theCamera.transform.localEulerAngles.x;
            yield return null;
        }
        pauseCameraRotation = false;
    }

    private void CharacterRotation()
    {
        float _yRotation = Input.GetAxisRaw("Mouse X");
        Vector3 _characterRotationY = new Vector3(0f, _yRotation, 0f) * lookSensitivity;
        myRigid.MoveRotation(myRigid.rotation * Quaternion.Euler(_characterRotationY));
    }
}





🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Unity Lesson 3 카테고리 내 다른 글 보러가기

댓글 남기기