개발/게임 교육

게임 교육 6 - 조이스틱 이동

이게될까 2023. 12. 28. 15:55
728x90
728x90

항상 만들어준 방식으로 만든다.

캐릭터 우클릭으로 가서 UI의 image를 선택하여 조이스틱을 만들어준다. CANVAS는 자동생성된다.

Canvas 설정 변경

Canvas의 설정을 위와 같이 바꿔준다.

조이스틱의 위치 설정

사각형 도넛처럼 생긴것을 클릭해서 좌측 하단부를 선택해준다.

조이스틱 안에 하나 더 만든다.

이름은 스틱이다. 여기도 사진을 넣어주고, 투명도는 절반을 해준다.(밖에 원이 절반이었다...)그럼 아래와 같은 모양이 나온다.

스크립트 만들기

조이스틱 기능을 구현할 시간이다.

스틱에서 add Component에서 추가한다.

구현 기능을 위애 이벤트 트리거를 stick에 추가시켜준다.

pointDown 선택

이벤트 타입에서 pointer Down을 선택해준다. 버튼의 온 클릭과 비슷한 역할을 한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 1. 스틱 드래그 + 제한 값 (스틱에 이벤트 트리거를 만들어줘야 한다.)
// 2. 드래그한 만큼 캐릭터를 이동

public class JoyStick : MonoBehaviour
{
    public RectTransform stick;

    bool isDrag;
    public void Update()
    {
        if (isDrag) 
        {// 스틱의 위치를 마우스로 가져간다.
            stick.position = Input.mousePosition;
        }
    }
    //스틱을 누르면 호출 될 함수
    public void ClickStick()
    {
        isDrag = true;
    }

}

스크립트의 코드이다.

joystick안에 stick를 넣어준다.
스틱에선 character를 넣고, Clickstick를 선택해준다.
플레이하면 스틱이 잘 따라오는 것을 볼 수 있다.

그러나 스틱이 너무 많이 움직인다. 범위를 한정시켜줘야 한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 1. 스틱 드래그 + 제한 값 (스틱에 이벤트 트리거를 만들어줘야 한다.)
// 2. 드래그한 만큼 캐릭터를 이동

public class JoyStick : MonoBehaviour
{
    public RectTransform stick, backGround; // 큰원의 반지름을 받아온다.

    bool isDrag;
    float limit;

    public void Start()
    {
        limit = backGround.rect.width * 0.5f;
    }
    public void Update()
    {
        if (isDrag) 
        {// 스틱의 위치를 마우스로 가져간다.
            stick.position = Input.mousePosition;
            stick.position = Vector2.ClampMagnitude(stick.position,limit);

            if (Input.GetMouseButtonUp(0))
            {// 터치가 끝났을 때
                stick.localPosition = new Vector3(0, 0, 0);
                //로컬 포지션은 부모(조이스틱)으로 부터의 위치
            }
        }
    }
    //스틱을 누르면 호출 될 함수
    public void ClickStick()
    {
        isDrag = true;
    }

}

코드를 아래와 같이 수정해본다.

또 Character에서 BackGround에 넣어준다.
뭔가 잘 못 되었다.

기준이 화면 왼쪽 하단부로 되었다. 수정해야 한다. 마우스를 때면 원상태로 돌아가는 기능도 작동하지 않는다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 1. 스틱 드래그 + 제한 값 (스틱에 이벤트 트리거를 만들어줘야 한다.)
// 2. 드래그한 만큼 캐릭터를 이동

public class JoyStick : MonoBehaviour
{
    public RectTransform stick, backGround; // 큰원의 반지름을 받아온다.

    bool isDrag;
    float limit;

    public void Start()
    {
        limit = backGround.rect.width * 0.5f;
    }
    public void Update()
    {
        if (isDrag) 
        {// 스틱의 위치를 마우스로 가져간다.
            //stick.position = Input.mousePosition;
            Vector2 vec = Input.mousePosition - backGround.position; // 큰 동그라미 기준으로 계산한다.
            stick.localPosition = Vector2.ClampMagnitude(vec,limit);

            if (Input.GetMouseButtonUp(0))
            {// 터치가 끝났을 때
                stick.localPosition = new Vector3(0, 0, 0);
                //로컬 포지션은 부모(조이스틱)으로 부터의 위치

                isDrag = false;
            }
        }
    }
    //스틱을 누르면 호출 될 함수
    public void ClickStick()
    {
        isDrag = true;
    }

}

코드를 위와 같이 다시 수정하고 다시 돌려본다.

잘 된다!

캐릭터를 이동시키는 기능을 만든다!

이제 화면 터치로 움직이는 기능과 조이스틱 기능을 나눠야 한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerCtrl : MonoBehaviour
{
    public GameObject joyStick;

    public float speed;
    public bool isJoyStick;

    private void Start()
    {
        Camera.main.transform.parent = transform; //캐릭터 이탈 방지
        Camera.main.transform.localPosition = new Vector3(0, 0, -10);
    }
    private void Update()
    {
        Move();
    }
    
    // 캐릭터 움직임 관리
    void Move()
    {
        if (isJoyStick)
        {
            joyStick.SetActive(true);
        }
        else
        {
            joyStick.SetActive(false);

            // 상하좌우를 터치하여 움직이기

            //클릭했는지 판단.
            if (Input.GetMouseButton(0))
            {            // 좌클릭 누르고 있는 중 컴퓨터 모바일 다 해준다.
                Vector3 dir = (Input.mousePosition - new Vector3(Screen.width * 0.5f, Screen.height * 0.5f)).normalized; // 화면 정중앙을 빼서 얼마나 이동하는지를 노말 백터화 한다.

                transform.position += dir * speed * Time.deltaTime;

            }
        }

    }
}

이전의 PlayerCtrl의 파일을 위와 같이 수정하고

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 1. 스틱 드래그 + 제한 값 (스틱에 이벤트 트리거를 만들어줘야 한다.)
// 2. 드래그한 만큼 캐릭터를 이동

public class JoyStick : MonoBehaviour
{
    public RectTransform stick, backGround; // 큰원의 반지름을 받아온다.
    PlayerCtrl playerCtrl_script;
    bool isDrag;
    float limit;
    

    public void Start()
    {
        playerCtrl_script = GetComponent<PlayerCtrl>();
        limit = backGround.rect.width * 0.5f;
    }
    public void Update()
    {
        // 드래그 하는 동안
        if (isDrag) 
        {// 스틱의 위치를 마우스로 가져간다.
            //stick.position = Input.mousePosition;
            Vector2 vec = Input.mousePosition - backGround.position; // 큰 동그라미 기준으로 계산한다.
            stick.localPosition = Vector2.ClampMagnitude(vec,limit);

            Vector3 dir = (stick.position - backGround.position).normalized;
            transform.position += dir * playerCtrl_script.speed * Time.deltaTime;

            // 드래그 끝나면
            if (Input.GetMouseButtonUp(0))
            {// 터치가 끝났을 때
                stick.localPosition = new Vector3(0, 0, 0);
                //로컬 포지션은 부모(조이스틱)으로 부터의 위치

                isDrag = false;
            }
        }
    }
    //스틱을 누르면 호출 될 함수
    public void ClickStick()
    {
        isDrag = true;
    }

}

조이스틱 파일도 위와 같이 수정한다.

조이스틱(C#파일 말고 Hierarchy에서) 넣기

저 박스를 선택하면 조이스틱이 나오고 선택하지 않으면 조이스틱이 나오지 않는다.

조이스틱이 있어 터치이동은 안된다.

 

728x90