결과물부터 보자면 요런 느낌이다
이 글에서는 카메라에대한 구현만 기록하고 캐릭터 이동 관련은 기록하지 않는다
핵심
- Cinemachine으로 구현
- 화면을 드래그해서 카메라를 회전
- UI위 터치는 드래그 판정 무시
Cinemachine 설정
Virtual Camera
를 사용했다Aim
의 타입은POV
로 사용하되Input Axis Name
은 비워뒀다- 코드를 통해서 값을 조절할 것이다
- Follow와 LookAt은 캐릭터 머리쪽에 빈 오브젝트를 만들고 넣어줬다


마우스(포인터)가 UI위에 있는지 확인
- 앞으로의 구현을 위해서 필요하다
- 나는 이런 Tool코드는
Static
클래스에다가 몰아넣는 편이다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
namespace Oni
{
public static class Tools
{
public static bool IsPointerOverUI()
{
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
pointerEventData.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointerEventData, results);
for (int i = 0; i < results.Count; i++)
{
if (results[i].gameObject.layer == LayerMask.NameToLayer("UI"))
return true;
}
return false;
}
}
}
Unity의 드래그에대해서...
- Unity의 드래그 판정 방법은 여러가지인데 뭔가 통합이 덜된느낌이 좀 든다
- 방법 1 -
UnityEngine.EventSystems.IDragHandler
인터페이스를 상속받기- 해당 인터페이스를 상속받으면
OnDrag(PointerEventData)
멤버 함수를 상속받는다 OnDrag
함수는 드래그가 일어나면 호출되지만 UI그래픽 오브젝트에게서만 작동한다- 탈락!
- 해당 인터페이스를 상속받으면
- 방법 2 -
OnMouseDrag()
예약 함수- "
OnMouseDrag
는 사용자가GUIElement
또는Collider
를 클릭하고 마우스 단추를 누르고 있는 경우 호출됩니다." 라고 한다 - 직접 테스트해보니 일반적인 UI에서는 작동 안하고
Collider
가있는 오브젝트 위에서 드래그하면 호출이된다 - 아무튼 이 방법도 구현할 목표에 맞지않는다
- 탈락!
- "
- 방법 3 - 마우스 버튼 다운, 홀드, 업으로 직접 판단해서 구현
- 이 방법을 사용할 것이다
- 방법 1 -
드래그 판정 구현
- 클래스 이름은 취향대로 지어주자
- 유니티 이벤트를 사용했으므로
using UnityEngine.Events;
도 따로 추가해주자 - 주석으로 설명을 적었다
[SerializeField]
private bool isDragging; // 드래그 중인지 여부
[SerializeField]
private bool isTouchDownOnUI; // UI위에서 포인터 다운이 발생했는지 여부
[SerializeField]
private Vector3 dragStartPos; // 드래그를 시작한 좌표
[SerializeField]
private Vector3 previousDragPos; // 직전 드래그 좌표
[SerializeField]
private Vector3 dragVector; // 현재 좌표 - 직전 드래그 좌표(이동한 양)
public UnityEvent<Vector3> onBeginDrag; // 드래그 시작 이벤트
public UnityEvent<Vector3> onDrag; // 드래그 지속 이벤트
public UnityEvent onEndDrag; // 드래그 끝 이벤트
private void Update()
{
// 포인터 다운 감지
if(Input.GetMouseButtonDown(0))
{
// 드래그 시작 좌표 저장
dragStartPos = Input.mousePosition;
// 직전 드래그 좌표 초기화
previousDragPos = dragStartPos;
// 포인터가 UI위에있는지 확인하고 변수에 저장
isTouchDownOnUI = Tools.IsPointerOverUI();
}
if(Input.GetMouseButton(0))
{
// UI위에서 시작됐다면 드래그 무시
if (!isTouchDownOnUI)
{
// 현재 포인터 좌표
Vector3 currentMousePos = Input.mousePosition;
// 움직인 양 계산
dragVector = currentMousePos - previousDragPos;
// 처음이라면 onBeginDrag이벤트 실행
if(!isDragging)
{
isDragging = true;
onBeginDrag?.Invoke(dragVector);
}
// 처음이 아니라면 onDrag이벤트 실행
else
onDrag?.Invoke(dragVector);
// 직전 드래그 좌표 업데이트
previousDragPos = currentMousePos;
}
}
// 드래그 끝
if(Input.GetMouseButtonUp(0))
{
isDragging = false;
isTouchDownOnUI = false;
onEndDrag?.Invoke();
}
}
카메라 회전 구현
- 이제 드래그이벤트에 연결할 회전 함수를 만든다
- 파라미터로 들어오는 값을 넣어주는게 전부다
using UnityEngine;
using Cinemachine;
public class PlayerCameraRotator : MonoBehaviour
{
[SerializeField]
private CinemachineVirtualCamera cam; // Cinemachine카메라
[SerializeField]
private float multiply = 0.001f; // 보정값
public void OnDragUpdated(Vector3 dragVector)
{
// Horizontal, Vertical 입력값을 드래그값으로 넣어준다
cam.GetCinemachineComponent<CinemachinePOV>().m_HorizontalAxis.m_InputAxisValue = dragVector.x * multiply;
cam.GetCinemachineComponent<CinemachinePOV>().m_VerticalAxis.m_InputAxisValue = dragVector.y * multiply;
}
public void OnEndDrag()
{
// 드래그가 끝났으니 초기화한다
cam.GetCinemachineComponent<CinemachinePOV>().m_HorizontalAxis.m_InputAxisValue = 0f;
cam.GetCinemachineComponent<CinemachinePOV>().m_VerticalAxis.m_InputAxisValue = 0f;
}
}
- 아까 만든 드래그 이벤트에 연결해준다
onBeginDrag
이벤트는 사용하지 않았다

여담
나만 그런지 모르겠지만 Unity의 터치 입력 구현은 뭔가 직관성도 떨어지고 통합이 안된 느낌이다
그래서 할때마다 자꾸 헷갈린다 물론 나만 그럴 수도...
간단하게 Cinemachine
카메라와 같이 작동하게 드래그 회전 카메라를 구현했다.
기본 카메라를 사용하면 좀 더 쉬웠을 수도 있지만 Cinemachine
의 카메라 장애물 회피같은 플러그인을 사용할 수 없다.
여기서 좀 더 확장하면 캐릭터가 이동하는 방향으로 카메라가 서서히 에임을 맞추도록 구현하면 더 좋은 느낌이 될 것 같다.
끝
'Unity > C#' 카테고리의 다른 글
[Unity] 플레이어를 따라오는 간단한 스프링 효과 (0) | 2025.01.15 |
---|---|
[Unity] 3D 탑다운 무한 맵 (0) | 2024.11.09 |
[C#] 빠르게 C# 단일 스크립트를 슥 작성하고 쇽 실행하는 법 (polyglot notebooks) (0) | 2024.06.27 |
[Unity] JsonUtility.ToJson() 대신 Jobject.FromObject()를 쓰자 (1) | 2024.06.17 |
[Unity] Unity 3D Game Kit Lite템플릿 Damageable스크립트 분석 (1) | 2024.05.22 |