유니티 조이스틱 시스템 제작 방법
유니티로 모바일 게임을 제작할 때 조이스틱 시스템을 가져와 플레이어의 움직임을 구현하곤 한다. 보통은 애셋을 가져다 쓰기 때문에 조이스틱 제작 방법이 어렵다고 생각하나, 사실은 기본적인 이동 공식과 Vector3 자료형 값 만으로 구현할 수 있다. 조이스틱의 원리 역시 방향 설정(방향 벡터)과 관련이 있기 때문이다.
조이스틱 제작에 대한 기본적인 아이디어는 다음과 같다.
1. 조이스틱을 만들고 싶다.
- UI가 마우스를 따라서 이동하도록 처리
- 조이스틱이 가리키는 방향을 찾고 싶다
- <방향 벡터 : 움직인 지점 - 원래 있던 지점>
2. 플레이어의 방향을 찾는다.
외부 클래스를 static으로 선언해 플레이어 이동에 가져오는 방법
// 플레이어 이동 스크립트
float h = Joystick.GetAxis("Horizontal)";
float v = Joystick.GetAxis("Vertical");
Vector3 dir = Vector3.right * h + Vector3.up * v;
dir.Normalize();
transform.position += dir * speed * Time.deltaTime;
public Class Joysitc
{
static bool bDown = false;
static Vector3 lastMousePos;
public static float GetAxis(string axis)
{
if(axis == "Horizontal")
return GetDirection().x;
else if(axis == "Vertical")
return GetDirection().y;
else
return 0;
}
public static Vector3 GetDirection()
{
Vector3 dir = Vector3.zero;
if(Input.GetButtonDown("Fire1"))
{
bDown = true;
lastMousePos = Input.mousePosition;
}
if(Input.GetButtonUp("Fire1"))
bDown = false;
if(bDown)
dir = Input.mousePostion - lastMousePos;
return dir.normalized;
}
}
다음과 같이 Joystick 클래스를 만들어서 플레이어 이동 스크립트에 가져왔다. 이렇게 할 경우 플레이어 이동 뿐만 아니라, 여러 다른 캐릭터 이동 스크립트에서도 사용할 수 있기 때문에 사용성이 향상된다는 장점이 있다.(유틸리티 코드)
그 외에 Event Trigger의 마우스 클릭 이벤트를 사용해서 만들수 도 있다. 그 부분은 더 공부를 해서 구현해볼 것이다.
조이스틱 생성 및 이동범위 제한 응용 기능 제작 방법
추가적으로 화면을 터치했을 때 마다 조이스틱의 초기 생성 위치가 설정되고, 조이스틱의 드래그 이동 범위를 제한해주는 방법도 응용해서 구현해 볼 수 있겠다. 기본적으로 방향 벡터를 이용해 조이스틱의 드래그 UI를 보여주고 movVector 변수를 더해 범위 내로 이동을 제한하는 방식으로 아이디어를 구상해 볼 수 있겠다. 또한 Mathf.Clamp 함수를 사용해 조이스틱 초기 생성 위치에서 이동 범위를 제한할 수도 있겠다.
// 움직이는 데 사용될 방향
public Vector3 dir;
// 조이스틱 배경 이미지
public RectTransform joystickBG;
// 조이스틱 스틱
public RectTransform stick;
// 처음 마우스를 누른 위치
Vector3 basePos;
// 드래그 시 현재 위치
Vector3 currentPos;
// Start is called before the first frame update
void Start()
{
// 조이스틱을 보이게 설정한다
joystickBG.gameObject.SetActive(false);
stick.gameObject.SetActive(false);
}
// 처음 마우스를 눌렀을 때
public void OnStickDown()
{
// 그 위치를 기준점으로 잡고
basePos = Input.mousePosition;
// 조이스틱을 그 위치로 지정한다
joystickBG.anchoredPosition = basePos;
stick.anchoredPosition = basePos;
// 조이스틱을 보이게 설정한다
joystickBG.gameObject.SetActive(true);
stick.gameObject.SetActive(true);
// 방향을 초기화한다
dir = Vector3.zero;
}
// 드래그하면
public void OnStickDrag()
{
// 현재 위치를 저장하고
currentPos = Input.mousePosition;
// 기준점으로부터의 거리를 80으로 제한한다
Vector3 v = Vector3.ClampMagnitude(currentPos - basePos, 80f);
// 스틱의 위치를 기준점에서 v를 더한 위치로 지정한다
stick.anchoredPosition = basePos + v;
// 뱡항을 갱신한다
dir = v.normalized;
}
public void OnStickUp()
{
// 조이스틱을 보이지 않게 설정한다
joystickBG.gameObject.SetActive(false);
stick.gameObject.SetActive(false);
// 방향을 초기화한다
dir = Vector3.zero;
}
if (Input.GetButtonDown("Fire1"))
{
// 시작점이 발생(조이스틱의 시작점)
startPoint = Input.mousePosition;
// 시작점 UI가 나오게
startPoint_UI.SetActive(true);
startPoint_UI.transform.position = startPoint;
// 움직이는 점 UI가 나오게
movePoint_UI.SetActive(true);
movePoint_UI.transform.position = startPoint;
}
// 클릭을 하고 있는 동안
if(Input.GetButton("Fire1"))
{
movePoint = Input.mousePosition;
// UI가 마우스를 따라다니게
movePoint_UI.transform.position = movePoint;
// 방향
moveDir = movePoint - startPoint;
moveDir.Normalize();
// 만약 시작점과 움직이는 점의 거리가 30이 넘으면
if(Vector3.Magnitude(movePoint-startPoint)>=30)
{
// 거리를 30으로 제한
movePoint_UI.transform.position = startPoint_UI.transform.position + moveDir * 30f;
}
}