(Unity) 조이스틱 구현
포스트
취소

(Unity) 조이스틱 구현

모바일에서 자주 사용되는 조이스틱을 구현합니다.

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);
    }
}


3. 결과


💡 참고

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

(Unity) Draw Call 최적화

(Unity) Fake Null 정리