FPS서바이벌 디펜스

27.마우스 커서 숨기기

ruripanda 2025. 6. 2. 17:17

본 강좌는 케이디님의 유튜브강좌 영상을 보고 유니티6로 구현한 것 입니다 이렇게 멋진 강좌를 만드신 케이디님을 존경합니다

using UnityEngine;

public class GameManager : MonoBehaviour
{
    public static bool canPlayerMove = true;//플레이어의 움직임 제어

    public static bool isOpenInventory = false;// 인벤토리 활성화
    public static bool isOpenCraftManual = false;//건축메뉴창 활성화

    // Update is called once per frame
    void Update()
    {
        if (isOpenInventory || isOpenCraftManual)
        {
            Cursor.lockState = CursorLockMode.None; //마우스 커서를 보임
            Cursor.visible = true;                  //마우스를 보이게 함
            canPlayerMove = false;
        }
        else
        {
            Cursor.lockState = CursorLockMode.Locked;   //커서를 장금
            Cursor.visible = false;                     //마우스를 보이지 않게 함
            canPlayerMove = true;
        }
    }
}
using System.Collections;
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 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 lookSensitivity;
    [SerializeField]

    //카메라 한계
    private float cameraRotationLimit;
    private float currentCameraRotationX = 0;

    //필요 컴포넌트
    [SerializeField]
    private Camera theCamera;//카메라
    private Rigidbody myRigid;//리지드바디
    [SerializeField]
    private GunController theGunController;
    private Crosshair theCrosshair;
    private StatusController theStatusController;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        capsuleCollider = GetComponent<CapsuleCollider>();
        myRigid = GetComponent<Rigidbody>();//Player에 있는 리지드바디 장착
        theGunController = FindAnyObjectByType<GunController>();
        theCrosshair = FindAnyObjectByType<Crosshair>();
        theStatusController = FindAnyObjectByType<StatusController>();
        //초기화
        applySpeed = walkSpeed;
        originPosY = theCamera.transform.localPosition.y;
        applyCrouchPosY = originPosY;
    }

    // Update is called once per frame
    void Update()
    {
        if (GameManager.canPlayerMove)
        {
            IsGround();
            TryJump();
            TryRun();
            TryCrouch();
            Move();
            MoveCheck();
            CameraRotation();
            CharacterRotation();
        }
    }
    
    private void TryCrouch()//앉기 시도
    {
        if (Input.GetKeyDown(KeyCode.LeftControl))
        {
            Crouch();
        }
    }

    private void Crouch()//실제 앉기
    {
        isCrouch = !isCrouch;
        theCrosshair.CrouchingingAnimation(isCrouch);

        //if (isCrouch)
        //    isCrouch = false;
        //else
        //    isCrouch = true;위 한줄짜리 코드 축약임
        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.5f);
            theCamera.transform.localPosition = new Vector3(0, _posY, 0);
            if (count > 15)
                break;
            yield return new WaitForSeconds(0.1f);
        }
        theCamera.transform.localPosition = new Vector3(0, applyCrouchPosY, 0f);
    }

    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.linearVelocity = 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 Move()//걷기 실행
    {
        float _moveDirX = Input.GetAxisRaw("Horizontal");//좌우 방향키를 입력시 +1 ~ -1이 반환된다
        float _moveDirZ = Input.GetAxisRaw("Vertical");//상하 움직임 입력시 +1 ~ -1이 반환된다

        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 void CharacterRotation()//좌우 캐릭터 회전
    {
        float _yRotation = Input.GetAxisRaw("Mouse X");
        Vector3 _characterRotationY = new Vector3(0f, _yRotation, 0f) * lookSensitivity;
        myRigid.MoveRotation(myRigid.rotation * Quaternion.Euler(_characterRotationY));
        //Debug.Log(myRigid.rotation);
        //Debug.Log(myRigid.rotation.eulerAngles);
    }

    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);
    }
}
using UnityEngine;

public class Inventory : MonoBehaviour
{
    public static bool inventoryActivated = false;

    //필요한 컴포넌트
    [SerializeField]
    private GameObject go_InventoryBase;
    [SerializeField]
    private GameObject go_SlotsParent;

    private Slot[] slots;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        slots = go_SlotsParent.GetComponentsInChildren<Slot>();    
    }

    // Update is called once per frame
    void Update()
    {
        TryOpenInventory();
    }

    private void TryOpenInventory()
    {
        if (Input.GetKeyDown(KeyCode.I))
        {
            inventoryActivated = !inventoryActivated;

            if (inventoryActivated)
                OpenInventory();
            else
                CloseInventory();
        }
    }

    private void OpenInventory()
    {
        GameManager.isOpenInventory = true;
        go_InventoryBase.SetActive(true);
    }

    private void CloseInventory()
    {
        GameManager.isOpenInventory = false;
        go_InventoryBase.SetActive(false);
    }

    public void AcquireItem(Item _item, int _count = 1)
    {
        if (Item.ItemType.Equipment != _item.itemType)
        {
            for (int i = 0; i < slots.Length; i++)
            {
                if (slots[i].item != null)
                {
                    if (slots[i].item.itemName == _item.itemName)
                    {
                        slots[i].SetSlotCount(_count);
                        return;
                    }
                }
            }
        }

        for (int i = 0; i < slots.Length; i++)
        {
            if (slots[i].item == null)
            {
                slots[i].AddItem(_item, _count);
                return;
            }
        }
    }
}

 

이번 시간에는 마우스가 조준모드일때는 나타나지 않고 인벤토리를 열면 나타나게 하겠다

 

C#스크립트를 만들어주고 GameManager 이라고 명명해준다

 

기본 변수 설명에 들어간다

이 변수들은 어느스크립트와 씬에서든 작동되어야 하므로 static로 공유한다

5번 줄은 플레이어가 움직일때 true로 제어해주는 것이고

7번 줄은 인벤토리 활성화 여부

8번 줄은 건축창 활성화 여부이다

 

이제 void Update를 보자

if문으로 인벤토리나 건축창이 활성화 되었을때 실행되게 한다

15~17줄은 설명한 그대로 작동되는 것이고

else로 21~23번은 설명한 그대로 작동되는 것이다

 

이제 PlayerController 스크립트를 열어주자

밑줄친 부분을 추가하여 평소 동작을 잠궈준다

 

다음은 Inventory 스크립트를 열어보자

 

밑줄친 부분을 추가하여 인벤토리 활성화, 비활성화시 마우스를 보일지 말지 선택한다

 

이것으로 이번 강좌를 마친다

이건 마우스 포인터라서 움짤로 촬영을 못 할거 같다

여기까지 하겠다