[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 2]

※ 주의 

이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.



Menu


1. 조이스틱 만들기.

2. 조이스틱의 벡터를 받아 캐릭터를 회전 및 이동 시키기.





2. 조이스틱의 벡터를 받아 캐릭터를 회전 및 이동 시키기.


필요한 재료.

- 플레이어의 Trsnform 컴포넌트

- 움직임 플래그 값.


조이스틱을 만들었다면 움직이는것은 그다지 어렵지 않다.

조이스틱을 움직이기 위해서 구했던 벡터를 그대로 캐릭터를 회전 시키는데 쓰면 되기 때문이다.


물론 그 벡터를 그대로 갔다 쓰면 안되고 약간의 변경이 필요하다.

아크탄젠트를 사용해서 각도를 바꿔주고 그것을 디그리로 변경하면 되는데,

이러한 함수도 유니티에서 제공해주고 있다.


※ 삼각비,삼각함수,라디안,디그리 등은 블로그내에 게임수학 부분을 참고하기 바란다.




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
62
63
64
65
66
67
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
 
public class JoyStick : MonoBehaviour {
 
    // 공개
    public Transform Player;        // 플레이어.
    public Transform Stick;         // 조이스틱.
 
    // 비공개
    private Vector3 StickFirstPos;  // 조이스틱의 처음 위치.
    private Vector3 JoyVec;         // 조이스틱의 벡터(방향)
    private float Radius;           // 조이스틱 배경의 반 지름.
    private bool MoveFlag;          // 플레이어 움직임 스위치.
 
    void Start()
    {
        Radius = GetComponent<RectTransform>().sizeDelta.y * 0.5f;
        StickFirstPos = Stick.transform.position;
 
        // 캔버스 크기에대한 반지름 조절.
        float Can = transform.parent.GetComponent<RectTransform>().localScale.x;
        Radius *= Can;
 
        MoveFlag = false;
    }
 
    void Update()
    {
        if (MoveFlag)
            Player.transform.Translate(Vector3.forward * Time.deltaTime * 10f);
    }
 
    // 드래그
    public void Drag(BaseEventData _Data)
    {
        MoveFlag = true;
        PointerEventData Data = _Data as PointerEventData;
        Vector3 Pos = Data.position;
        
        // 조이스틱을 이동시킬 방향을 구함.(오른쪽,왼쪽,위,아래)
        JoyVec = (Pos - StickFirstPos).normalized;
 
        // 조이스틱의 처음 위치와 현재 내가 터치하고있는 위치의 거리를 구한다.
        float Dis = Vector3.Distance(Pos, StickFirstPos);
        
        // 거리가 반지름보다 작으면 조이스틱을 현재 터치하고 있는 곳으로 이동.
        if (Dis < Radius)
            Stick.position = StickFirstPos + JoyVec * Dis;
        // 거리가 반지름보다 커지면 조이스틱을 반지름의 크기만큼만 이동.
        else
            Stick.position = StickFirstPos + JoyVec * Radius;
 
        Player.eulerAngles = new Vector3(0, Mathf.Atan2(JoyVec.x, JoyVec.y) * Mathf.Rad2Deg, 0);
    }
 
    // 드래그 끝.
    public void DragEnd()
    {
        Stick.position = StickFirstPos; // 스틱을 원래의 위치로.
        JoyVec = Vector3.zero;          // 방향을 0으로.
        MoveFlag = false;
    }
}
 
cs



MoveFlag같은 경우 조이스틱을 드래그 할때만 true로 바뀌고 드래그가 끝난다면 곧바로 false로 돌아간다.

플래그 값이 true인 동안에만 transform.Translate를 통해 캐릭터가 움직인다.


플레이어를 움직이는 구문을 Drag함수 안에 놓으면 드래그 하는동안만 움직이지 않냐고 물을수도 있다.


맞다. 드.래.그 하는 동안 움직인다. 조이스틱을 잡고 끝으로 땡겨놓고 가만히 있으면 조이스틱을 땡기는 동안만 움직이고

가만히 있을때에는 움직이지 않는다. 말 그대로 조이스틱을 잡고 움직이는 동안만 함수가 들어오는 것이다.

아무튼 움직이는 것은 지속적으로 체크가 가능한 Update함수에서 해야한다. (코루틴을 사용해도 좋다.)


플레이어를 어떤 축을 중심으로 회전시켜야 할까?

y축이다. y축을 원하는 방향으로 회전만 시킨다면 플레이어는 그 방향으로 나아가게 될 것이다.

그렇다면 그 방향을 어떻게 구할수 있을까?

바로 조이스틱의 벡터이다. 하지만 이 벡터는 바로 쓸수 없다.

쓰기 위해선 아크탄젠트를 통해 변환하고, 나온 라디안 값을 디그리로 변환해주고 나온 디그리 값으로

플레이어의 y축 회전에 쓰면된다.




아탄을 통해 각a를 구할수 있다.

하지만 이 값은 라디안 값이므로 디그리(각도)로 변환해 주어야 한다.



결과.