FPS서바이벌 디펜스
27.마우스 커서 숨기기
ruripanda
2025. 6. 2. 17:17
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 스크립트를 열어보자
밑줄친 부분을 추가하여 인벤토리 활성화, 비활성화시 마우스를 보일지 말지 선택한다
이것으로 이번 강좌를 마친다
이건 마우스 포인터라서 움짤로 촬영을 못 할거 같다
여기까지 하겠다