본문 바로가기
게임 엔진 - 유니티/[루키스] 유니티

[유니티 Note] 섹션 6-2

by 묻공러 2025. 7. 2.

# 클릭한 위치로 캐릭터 이동하는 기능 구현

- InputManager 클래스 코드 추가 및 수정

기존 KeyAction 뿐 아니라 MouseAction 델리게이트 이벤트를 생성해서

이를 활용하면 된다

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

public class InputManager
{
    public event Action KeyAction = null;
    public event Action<Define.MouseEvent> MouseAction = null;
    bool _mousePressed = false;

    public void OnUpdate()
    {
        if (KeyAction != null && Input.anyKey)
            KeyAction.Invoke();


        if (MouseAction != null)
        {
            if (Input.GetMouseButton(0))
            {
                MouseAction.Invoke(Define.MouseEvent.Press);
                _mousePressed = true;
            }
            else
            {
                if (_mousePressed == true)
                    MouseAction.Invoke(Define.MouseEvent.Click);

                _mousePressed = false;
            }
        }
    }
}

 

- PlayerController 클래스 코드 추가 및 수정

InputManager의 MouseAction과 바인드 할 함수를 추가하면 된다

그리고 PlayerController Update에서 마우스로 지속적으로 이동을 하는 코드를 작성하면 된다

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

public class PlayerController : MonoBehaviour
{
    [SerializeField]
    float _positionSpeed = 10.0f;
    [SerializeField]
    private float _rotationSpeed = 10.0f;

    bool _mouseMoveToDest = false;
    Vector3 _mouseMoveDestPos;

    void Start()
    {
        Managers.Input.KeyAction -= OnKeyboard;
        Managers.Input.KeyAction += OnKeyboard;
        Managers.Input.MouseAction -= OnMouseClicked;
        Managers.Input.MouseAction += OnMouseClicked;
    }

    void Update()
    {
        if (_mouseMoveToDest == true)
        {
            Vector3 dir = _mouseMoveDestPos - transform.position;
            dir.y = 0.0f;
            if(dir.magnitude < 0.0001f)
            {
                _mouseMoveToDest = false;
            }
            else
            {
                transform.position += dir.normalized * _positionSpeed * Time.deltaTime;
                transform.LookAt(_mouseMoveDestPos);
            }
        }
    }

    void OnKeyboard()
    {
        ...
        _mouseMoveToDest = false;
		
        ...
    }

    void OnMouseClicked(Define.MouseEvent evt)
    {
        if (evt != Define.MouseEvent.Click)
            return;

        Debug.Log("OnMouseClicked");

        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.red, 1.0f);

        RaycastHit hit;
        if (Physics.Raycast(ray, out hit, 100.0f, LayerMask.GetMask("Wall")))
        {
            _mouseMoveDestPos = hit.point;
            _mouseMoveToDest = true;
        }
    }
}

 

 

# 오류 발생 1

플레이어의 속도가 있다보니 계속 목적지를 지나쳐서

다시 해당 위치로 가려고 부들부들 떨리며 이동하는 문제가 있다

따라서 거리(== 시 * 속)를 통제하는 코드를 추가해야 한다

    void Update()
    {
        if (_mouseMoveToDest == true)
        {
            Vector3 dir = _mouseMoveDestPos - transform.position;
            dir.y = 0.0f;
            if(dir.magnitude < 0.0001f)
            {
                _mouseMoveToDest = false;
            }
            else
            {
                float moveDist = Mathf.Clamp(_positionSpeed * Time.deltaTime, 0, dir.magnitude); // 거리 통제

                transform.position += dir.normalized * moveDist;
                transform.LookAt(_mouseMoveDestPos);
            }
        }
    }

 

# 오류 발생 2

LookAt을 사용하는 경우

회전을 천천히 진행하는 것이 아니라

바로 딱 회전을 진행하는 문제가 있다

그렇기에 이를 해결하기 위해서는 Slerp를 활용하면 된다

    void Update()
    {
        if (_mouseMoveToDest == true)
        {
            Vector3 dir = _mouseMoveDestPos - transform.position;
            dir.y = 0.0f;
            if(dir.magnitude < 0.0001f)
            {
                _mouseMoveToDest = false;
            }
            else
            {
                float moveDist = Mathf.Clamp(_positionSpeed * Time.deltaTime, 0, dir.magnitude);

                transform.position += dir.normalized * moveDist;
                transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 10 * Time.deltaTime); // Slerp 활용
            }
        }
    }

'게임 엔진 - 유니티 > [루키스] 유니티' 카테고리의 다른 글

[유니티 Note] 섹션 7-1  (0) 2025.07.05
[유니티 Note] 섹션 6-3  (0) 2025.07.02
[유니티 Note] 섹션 6-1  (0) 2025.07.02
[유니티 Note] 섹션 5-6  (0) 2025.07.02
[유니티 Note] 섹션 5-5  (0) 2025.07.02