본문 바로가기

Programming/Unity

가상 조이스틱 구현

포폴 개발초기에는 키보드로 테스트하였기에 별 문제없이 테스트했지만

유니티 어플을 통해 스마트폰으로 테스트하려니 가상조이스틱이 필요하게 되었다.

NGUI 튜토리얼에 가상 조이스틱이 있다고 들었는데 찾지를 못 해서 스스로 구현하게 되었는데

조이스틱을 만들 때 기준이 되는 큰원, 내부에 왔다갔다 할 작은 원, 작은원의 최대 위치를 가르킬 빈오브젝트

이렇게 3개의 게임오브젝트를 이용하였다 


코드 요약 

1. 오브젝트가 눌렸을 때 눌려진 터지번호를 기억하고 update에서 이용한다. 터치번호가 없다면 update에서는 동작을 

   하지않는다.

2. 기억된 터치번호를 이용하여 터치된 위치를 스크린 좌표에서 직교좌표계로 좌표값으로 변경한다.

3. 변경된 좌표값에 작은원 오브젝트인 Inner_Pad를 이동시킨다. 이동된 작은원과 큰원의 중점을 이용해 벡터를 얻고

   그 벡터에 대해 길이와 정규화한 방향벡터를 얻는다.

4. 만약 길이가 미리 정해놓은 최대 길이보다 길다면 강제로 해당 방향벡터의 최대길이 위치로 이동시킨다.

5. 현재길이 / 최대길이 식으로 최대속도 1를 나올 수 있게 하고 해당 방향을 캐릭터 이동에 넘겨준다.

6. 캐릭터 이동에서는 속도와 방향을 얻어 해당방향으로 이동할 수 있도록 한다.




처음에는 포토샵으로 알파채널이 들어간 동그라미 큰것 작은것으로 구현했었으나 인터넷으로 적당한 그림을 찾아서 대충 바꿔놨음.


아래는 개발한 코드들이다.



using UnityEngine;
using System.Collections;

public class VI_Pad : MonoBehaviour 
{
    public      Camera          UICam               = null;
    public      Transform       InnerPad            = null;
                Vector3         dir                 = new Vector3(0,0,0);
                float           distance            = 0.0f;
                float           distanceMax         = 0.0f;
    public      CharactorMove   CharMove            = null;
                bool            IsPress             = false;
                int             touch_ID            = -1;

    void Awake ()
    {
        // InnerPad가 null일 경우 스스로 찾음
        if (!InnerPad)
        {
            InnerPad = GameObject.Find("VI_Pad_Inner").transform;
        }

        // CharMove이 null 일 경우 스스로 찾음
        if (!CharMove)
        {
            CharMove = GameObject.Find("PLAYER").GetComponent<charactormove>();
        }

        // 최대 거리
        distanceMax = (transform.position - GameObject.Find("UI Root/UICam/UIPanel/VI_Pad/MaxXpos").transform.position).magnitude;
    }

	// Use this for initialization
	void Start () 
    {
	    
	}
	
	// Update is called once per frame
	void Update () 
    {
        if (IsPress && touch_ID > -1)
        {
            // Touch 코드
            Vector3 touch = Input.GetTouch(touch_ID).position;
            Vector3 padPos = UICam.ScreenToWorldPoint(new Vector3(touch.x, touch.y, 0));
            // 최대 Touch 거리를 넘어섰을 경우 최대거리로 제한
            if( (padPos - transform.position).magnitude > distanceMax)
            {
                padPos = transform.position + (padPos - transform.position).normalized * distanceMax;
            }
            InnerPad.position = padPos;
        }

        // 방향벡터 얻기
        Vector3 Temp = (InnerPad.position - transform.position).normalized;
        dir.x = Temp.x;
        dir.y = 0.0f;
        dir.z = Temp.y;

        // 거리 계산
        distance = (InnerPad.position - transform.position).magnitude;
        //Debug.Log(InnerPad.position);

        // 캐릭터 이동 회전 호출
        CharMove.playerMove(dir, distance / distanceMax);
    }

    void OnPress(bool _IsPress)
    {
        // 패드가 눌렸을 경우 터치의 충돌여부 판단과 충돌된 터치번호를 얻음
        IsPress = _IsPress;
        if( IsPress)
        {
            for (int i = 0; i < Input.touchCount; ++i)
            {
                Ray ray = UICam.ScreenPointToRay(Input.GetTouch(i).position);
                RaycastHit2D rayhit = Physics2D.GetRayIntersection(ray, Mathf.Infinity);
                if (rayhit.collider == this.GetComponent<collider2d>())
                {
                    touch_ID = i;
                }
            }
        }
    }

    void OnRelease()
    {
        IsPress = false;
        touch_ID = -1;
    }
}


'Programming > Unity' 카테고리의 다른 글

Unity C# Zoom in out  (0) 2015.08.03
NGUI HUDText 사용  (2) 2015.07.30
NGUI HP Bar 만들기  (0) 2015.07.30
몬스터 FSM 구현  (3) 2015.07.30
유니티(unity) 디버깅 하기  (0) 2014.01.28