모바일에서 자주 사용되는 조이스틱을 구현합니다.
1. 준비물
- Object
- Player
- UI
- 원형 틀
- 원형 (원형 틀의 자식 객체로 넣기)
- 원형 틀
2. 코드
💻 Scene UI 코드
플레이어의 터치를 확인하고 조이스틱의 활성화/비활성화, 드래그 역할을 담당합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class UI_GameScene : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler,
{
[SerializeField]
private UI_Joystick _joystickUI;
// 드래그 시작 시 조이스틱 시작
public void OnBeginDrag(PointerEventData eventData)
{
_joystickUI.OnJoystick(eventData);
}
// 드래그 중일 시 플레이어 이동
public void OnDrag(PointerEventData eventData)
{
_joystickUI.JoystickDrag(eventData);
}
// 드래그 해제 시 조이스틱 비활성화
public void OnEndDrag(PointerEventData eventData)
{
_joystickUI.OffJoystick();
}
}
💻 조이스틱 코드
조이스틱을 조작하고 플레이어에게 이동값을 전달합니다.
조이스틱의 밋밋한 사용감을 _speed
, _length
를 통해 자연스럽게 구현합니다.
_speed
: 원형(Handle)이 터치한 손가락을 따라가는 속도_length
: 원형(Handle)이 원형 틀에 딱 걸치는 것을 1이라고 할때 얼마나 덜 걸치게 할지
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class UI_Joystick : MonoBehaviour
{
[SerializeField]
private PlayerController _player; // 플레이어 객체
[SerializeField]
private RectTransform _handle; // 원형 틀 안에 있는 원형 객체
private Vector2 _touch; // 터치한 위치
private float _widthHalf; // 원형 틀의 반지름
[SerializeField]
private float _speed = 0.35f; // _speed의 Handle이 터치한 손가락을 쫓는 속도
[SerializeField]
private float _length = 0.8f; // _handle의 최대 이동 길이
private void Start()
{
// 원형 틀의 반지름
_widthHalf = GetComponent<RectTransform>().sizeDelta.x * 0.5f;
gameObject.SetActive(false);
}
// 조이스틱 핸들러 드래그
public void JoystickDrag(PointerEventData eventData)
{
// 터치한 위치와 원형의 위치 차이를 구하고 반지름으로 나눠주기
_touch = ((eventData.position - (Vector2)transform.position) * _speed) / _widthHalf;
// 원형 틀에 걸치는 Handle 길이 확인
if (_touch.magnitude > _length)
_touch = _touch.normalized * _length;
// Handle 위치 설정
_handle.anchoredPosition = _touch * _widthHalf;
// 플레이어에게 조이스틱값 전달
_player.joystickValue = new Vector2(_touch.x, _touch.y);
}
// 마우스 위치에 조이스틱 활성화
public void OnJoystick(PointerEventData eventData)
{
gameObject.SetActive(true);
transform.position = eventData.position;
}
// 조이스틱 비활성화
public void OffJoystick()
{
gameObject.SetActive(false);
// 위치 초기화
_touch = Vector2.zero;
_handle.anchoredPosition = Vector2.zero;
}
}
💻 플레이어 코드
조이스틱의 이동값을 전달받아 움직임을 구현합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class PlayerController : MonoBehaviour
{
public Vector2 joystickValue = Vector2.zero;
[SerializeField]
private float speed = 6.5f;
private void Update()
{
UpdateMove();
}
private void UpdateMove()
{
// 조이스틱 값을 가지고 이동값 계산
Vector3 rightMovement = Vector3.right * Time.deltaTime * joystickValue.x * speed;
Vector3 upMovement = Vector3.forward * Time.deltaTime * joystickValue.y * speed;
// 위치 이동
transform.position += upMovement;
transform.position += rightMovement;
// 위치 방향 바라보기
transform.rotation = Quaternion.Euler(0f, Mathf.Atan2(joystickValue.x, joystickValue.y) * Mathf.Rad2Deg, 0f);
}
}