게임개발/드림랜드

2024.09.02 NPC 애니메이션, 카메라 스크립트와 플레이어 스크립트 그리고 커서

서지현 2024. 9. 2. 17:27

 

NPC Idle 애니메이션과 Hello 애니메이션을 완성하고 fbx모델에 적용한 다음 캐릭터 프리팹스를 만들었다.

 

서치와 챗 gpt의 도움을 통해 Main Camera 코드와 CharacterMove 코드를 손봤다.

 

MainCameraAction

 

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

public class MainCamera_Action : MonoBehaviour
{
    public Transform target;  // 따라갈 캐릭터
    public float distance = 5.0f;  // 캐릭터와의 거리
    public float height = 2.0f;  // 캐릭터 위의 높이
    public float horizontalOffset = 1.0f;  // 캐릭터 정면에서의 수평 오프셋
    public float rotationSpeed = 5.0f;  // 마우스 회전 속도
    public float zoomSpeed = 2.0f;  // 줌 속도
    public LayerMask collisionLayers;  // 카메라 충돌을 처리할 레이어

    private float currentX = 0.0f;
    private float currentY = 15.0f;  // 살짝 아래를 바라보게 하기 위해 초기값을 설정
    private float currentDistance;
    private CursorManager cursorManager;


    void Start()
    {
        currentDistance = distance;  // 초기 거리 설정

        cursorManager = GetComponent<CursorManager>();
        
        if ( cursorManager != null)
        {

            cursorManager.LockCursor();


        } 
    }

    void LateUpdate()
    {
        HandleCameraRotation();
        HandleCameraZoom();
        HandleCameraPosition();
    }

    void HandleCameraRotation()
    {
        // 마우스 입력 받기 (드래그 중이 아닐 때도)
        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");

        // X축 회전 (좌우)
        currentX += mouseX * rotationSpeed;

        // Y축 회전 (상하)
        currentY -= mouseY * rotationSpeed;
        currentY = Mathf.Clamp(currentY, 5, 60);  // 상하 회전 각도 제한
    }


    void HandleCameraZoom()
    {
        // 줌 인/아웃 처리
        float scroll = Input.GetAxis("Mouse ScrollWheel");
        currentDistance = Mathf.Clamp(currentDistance - scroll * zoomSpeed, 2.0f, 10.0f);
    }

    void HandleCameraPosition()
    {
        // 카메라 회전 계산
        Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);

        // 카메라 위치 계산
        Vector3 offset = new Vector3(horizontalOffset, height, -currentDistance);
        Vector3 desiredPosition = target.position + rotation * offset;

        // 충돌 처리: 카메라가 벽이나 장애물에 겹치지 않도록 처리
        RaycastHit hit;
        if (Physics.Linecast(target.position + Vector3.up * height, desiredPosition, out hit, collisionLayers))
        {
            desiredPosition = hit.point;  // 충돌한 지점으로 카메라 위치 조정
        }

        transform.position = desiredPosition;

        // 캐릭터를 바라보도록 카메라 설정
        transform.LookAt(target.position + Vector3.up * height);
    }
}

 

 

 

Character Move

 

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;


[RequireComponent(typeof(CharacterController), typeof(Animator))]
public class CharacterMove : MonoBehaviour
{
    private CharacterController controller;
    private Animator animator;

    [SerializeField]
    float gravity = -9.81f; // 중력의 크기
    float yVelocity = 0f; // 캐릭터의 현재 y축 속도
    [SerializeField]
    public float moveSpeed;
    [SerializeField]
    public float rotationSpeed = 5f; // 회전 속도를 조절하는 변수
    float hAxis;
    float vAxis;

    Vector3 moveVec;


    public Transform cameraTransform;

    // Start is called before the first frame update
    void Start()
    {
        controller = GetComponent<CharacterController>();
        animator = GetComponent<Animator>();

        if (cameraTransform == null)
        {


            cameraTransform = Camera.main.transform;


        }
    }

    // Update is called once per frame
    void Update()
    {
        hAxis = Input.GetAxisRaw("Horizontal");
        vAxis = Input.GetAxisRaw("Vertical");

        Vector3 inputDirection = new Vector3(hAxis, 0f, vAxis).normalized;

        Vector3 CameraForward = cameraTransform.forward;
        Vector3 CameraRight = cameraTransform.right;


        CameraForward.y = 0f;
        CameraRight.y = 0f;


        Vector3 moveDirection = CameraForward * inputDirection.z + CameraRight * inputDirection.x;

       

        // 애니메이터 상태 설정
        animator.SetBool("IsRunning", moveDirection != Vector3.zero);

        // 캐릭터 회전
        if (moveDirection != Vector3.zero)
        {
            // 목표 회전 값 계산
            Quaternion targetRotation = Quaternion.LookRotation(moveDirection);

            // 현재 회전 값과 목표 회전 값을 선형 보간하여 부드럽게 회전
            transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);

            controller.Move(moveDirection * moveSpeed * Time.deltaTime);
        }


        if(controller.isGrounded)
        {


            yVelocity = 0f;


        }

        else
        {

            yVelocity += gravity * Time.deltaTime;


        }

        
       

    }


}

 

 

이를 통하여 카메라 방향에 따라 캐릭터의 입력방식이 할당되고, 커서를 움직이면 카메라가 회전한다.

캐릭터 컨트롤러를 통한 중력 작용도 스크립트에 적용했다.

 

테스트 화면