Unity 공부

[Unity] 카메라 이동(드래그)

때류기 2024. 2. 4. 17:39

 

안녕하세요.

이번 시간엔 마우스 및 화면 터치 & 드래그로 카메라, 오브젝트를 이동하게 하는 방법에 대해 작성하고자 합니다.

 

 

먼저 카메라 및 오브젝트들을 임의의 위치로 생성합니다.

 

 

 

다음 CameraController.cs 를 생성합니다.

 

 

 

CameraController.cs

using UnityEngine;

public class CameraController : MonoBehaviour
{
    [SerializeField] private GameObject _camera;

    [Tooltip("드래그 하여 이동할 거리 비율")]
    [SerializeField] private float _moveRate;

    private Vector3 _tmpClickPos;

    private Vector3 _tempCameraPos;


    private void Update()
    {
        MouseMovement();
    }


    /// <summary>마우스로 카메라를 이동시키는 함수</summary>
    private void MouseMovement()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //좌클릭시 카메라, 클릭 위치 값을 저장해둔다.
            //좌클릭을 꾹 누르고 있을 때 위치를 이동시키기 위함
            _tmpClickPos = Input.mousePosition;
            _tempCameraPos = _camera.transform.position;
        }

        else if (Input.GetMouseButton(0))
        {
            //(저장한 클릭 위치 - 현재 마우스 위치)로 이동할 방향 및 거리를 계산한다.
            Vector3 movePos = Camera.main.ScreenToViewportPoint(_tmpClickPos - Input.mousePosition);
            _camera.transform.position = _tempCameraPos + (movePos * _moveRate);
        }
    }
}

 

 

 

위의 코드와 같이 작성하여 Hierarchy창의 Main Camera에 해당 스크립트를 추가해줍니다.

Inspector창에서 Camera항목에는 MainCamera 자신

MoveRate란에는 드래그 시 카메라의 이동속도를 넣어주시면 됩니다.

 

 

 

자 PC에서의 카메라 드래그 이동은 끝났습니다

이제 실행하여 화면을 드래그 하시면 카메라가 이동하는 것을 볼 수 있습니다!

 

 

 

하지만 이렇게 드래그 하는 방식은 보통 모바일에서 많이 사용하죠?

모바일 방식인 터치 방식을 추가하여 스크립트를 수정해보겠습니다.

 

CameraController.cs

using UnityEngine;

public class CameraController : MonoBehaviour
{
    [SerializeField] private GameObject _camera;

    [Tooltip("드래그 하여 이동할 거리 비율")]
    [SerializeField] private float _moveRate;

    private Vector3 _tmpClickPos;

    private Vector3 _tmpCameraPos;


    private void Update()
    {

#if UNITY_EDITOR //유니티 에디터로 실행하고 있을 경우

        MouseMovement();

#elif UNITY_ANDROID || UNITY_IOS //안드로이드 및 IOS에서 실행하고 있을 경우

        TouchMovement();    
        
#endif
    }


    /// <summary>마우스로 카메라를 이동시키는 함수</summary>
    private void MouseMovement()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //좌클릭시 카메라, 클릭 위치 값을 저장해둔다.
            //좌클릭을 꾹 누르고 있을 때 위치를 이동시키기 위함
            _tmpClickPos = Input.mousePosition;
            _tmpCameraPos = _camera.transform.position;
        }

        else if (Input.GetMouseButton(0))
        {
            //(저장한 클릭 위치 - 현재 마우스 위치)로 이동할 방향 및 거리를 계산한다.
            Vector3 movePos = Camera.main.ScreenToViewportPoint(_tmpClickPos - Input.mousePosition);
            _camera.transform.position = _tmpCameraPos + (movePos * _moveRate);
        }
    }


    private void TouchMovement()
    {
        //한손가락으로 터치하지않으면 함수를 종료
        if (Input.touchCount != 1)
            return;

        Touch touch = Input.GetTouch(0);

        //첫 터치 상태일때
        if (touch.phase == TouchPhase.Began)
        {
            //화면 터치시 카메라, 클릭 위치 값을 저장해둔다.
            //화면을 꾹 누르고 있을 때 위치를 이동시키기 위함
            _tmpClickPos = touch.position;
            _tmpCameraPos = _camera.transform.position;
        }

        //터치 중일때
        else if (touch.phase == TouchPhase.Moved)
        {
            //(저장한 터치 위치 - 현재 터치 위치)로 이동할 방향 및 거리를 계산한다.
            Vector3 movePos = Camera.main.ScreenToViewportPoint(_tmpClickPos - (Vector3)touch.position);
            _camera.transform.position = _tmpCameraPos + (movePos * _moveRate);

        }
    }
}

 

 

 

자 거의다 왔습니다.

이제는 카메라 이동에 디테일을 추가해보도록 하겠습니다.

화면 터치 후 드래그로 이동하다 터치를 떼는 순간 감속을 추가하여 스무스한 움직임을 구현하겠습니다.

 

CameraController.cs

using UnityEngine;

public class CameraController : MonoBehaviour
{
    [SerializeField] private GameObject _camera;

    [Space]
    [Tooltip("드래그 하여 이동할 거리 비율")]
    [SerializeField] private float _moveRate;

    [Space]
    [Tooltip("카메라 가속 배율")]
    [SerializeField] private float _accelerationRate;

    [Tooltip("카메라 감속 배율")]
    [SerializeField] private float _decelerationRate;

    private Vector3 _tmpClickPos;

    private Vector3 _tmpCameraPos;

    private Vector3 _distancemoved;

    private Vector3 _lastPos;

    private Vector3 _velocity;

    private void Update()
    {

#if UNITY_EDITOR //유니티 에디터로 실행하고 있을 경우

        MouseMovement();

#elif UNITY_ANDROID || UNITY_IOS //안드로이드 및 IOS에서 실행하고 있을 경우

        TouchMovement();    
        
#endif

        RunningAcceleration();
    }


    /// <summary>마우스로 카메라를 이동시키는 함수</summary>
    private void MouseMovement()
    {
        //좌클릭했을때
        if (Input.GetMouseButtonDown(0))
        {
            //좌클릭시 카메라, 클릭 위치 값을 저장해둔다.
            //좌클릭을 꾹 누르고 있을 때 위치를 이동시키기 위함
            _tmpClickPos = Input.mousePosition;
            _tmpCameraPos = _camera.transform.position;

            //가속도 관련 변수를 초기화한다.
            ResetAcceleration();
        }

        //좌클릭 중 일때
        else if (Input.GetMouseButton(0))
        {
            //(저장한 클릭 위치 - 현재 마우스 위치)로 이동할 방향 및 거리를 계산한다.
            Vector3 movePos = Camera.main.ScreenToViewportPoint(_tmpClickPos - Input.mousePosition);
            _camera.transform.position = _tmpCameraPos + (movePos * _moveRate);

            //가속도를 계산한다.
            CheckAcceleration();
        }

        //좌클릭을 종료했을때
        else if (Input.GetMouseButtonUp(0))
        {
            //가속도 적용
            SetAcceleration(_distancemoved);
        }
    }


    private void TouchMovement()
    {
        //한손가락으로 터치하지않으면 함수를 종료
        if (Input.touchCount != 1)
            return;

        Touch touch = Input.GetTouch(0);

        //첫 터치 상태일때
        if (touch.phase == TouchPhase.Began)
        {
            //화면 터치시 카메라, 클릭 위치 값을 저장해둔다.
            //화면을 꾹 누르고 있을 때 위치를 이동시키기 위함
            _tmpClickPos = touch.position;
            _tmpCameraPos = _camera.transform.position;

            //가속도 관련 변수를 초기화한다.
            ResetAcceleration();

        }

        //터치 중일때
        else if (touch.phase == TouchPhase.Moved)
        {
            //(저장한 터치 위치 - 현재 터치 위치)로 이동할 방향 및 거리를 계산한다.
            Vector3 movePos = Camera.main.ScreenToViewportPoint(_tmpClickPos - (Vector3)touch.position);
            _camera.transform.position = _tmpCameraPos + (movePos * _moveRate);

            //가속도를 계산한다.
            CheckAcceleration();
        }

        //터치가 종료됬을때
        else if (touch.phase == TouchPhase.Ended)
        {
            //가속도 적용
            SetAcceleration(_distancemoved);
        }
    }


    /// <summary>현재 위치와 이전 위치를 비교하여 가속도 값을 저장하는 함수</summary>
    private void CheckAcceleration()
    {
        _distancemoved = transform.position - _lastPos; //이전 프레임과 현재 프레임의 위치 차이를 계산해 삽입
        _lastPos = transform.position;
        _velocity = Vector3.zero;
    }


    /// <summary>가속도 관련 변수를 초기화 하는 함수</summary>
    private void ResetAcceleration()
    {
        _distancemoved = Vector3.zero;
        _lastPos = Vector3.zero;
        _velocity = Vector3.zero;
    }


    /// <summary>가속도를 설정하는 함수</summary>
    private void SetAcceleration(Vector3 acceleration)
    {
        _velocity = (acceleration / Time.deltaTime) * _accelerationRate;
    }


    /// <summary>_velocity값이 0이 아닐 경우 가속도를 주는 함수</summary>
    private void RunningAcceleration()
    {
        //속도가 0일 경우 리턴
        if (_velocity.sqrMagnitude == 0)
            return;

        //감속 속도를 현재 속도 * Time * 감속 비율 로 구한다.
        Vector3 _deceleration = _velocity * (Time.deltaTime * _decelerationRate);
        _velocity -= _deceleration;

        //현재 속도가 일정 수치가 되면 0으로 설정한다.
        if (_velocity.sqrMagnitude < 0.5f && _velocity.sqrMagnitude > -0.5f)
        {
            _velocity = Vector3.zero;
        }

        //위치를 이동시킨다.
        _camera.transform.position = transform.position + _deceleration;
    }
}

 

 

 

Inspector창도 이렇게 설정해줍니다.

AccelerationRate: 터치를 뗀 순간 가속도의 비율

DecelerationRate: 카메라 감속 비율

 

 

 

이렇게 수정하시면 터치를 떼는 순간 카메라가 드래그한 방향으로 이동하다 감속하게 됩니다.

아래 움짤을 확인하시면 정상적으로 가속, 감속이 적용되는 것을 볼 수 있습니다.!