[Unity 강의] 뱀서라이크 강의 - 조이스틱-

업데이트:

카테고리:

태그: , ,




1. Joystick

✔ 화면 전체에 투명한 판 생성
✔ 어딜 클릭하든 조이스틱이 시작점으로 작동
✔ Prefab으로 관리




Script

✔ UI_Joystick(Canvas)에 사용하고 싶은 이미지들이 포함되어 있어서
✔ [SerializeField]로 드래그 앤 드롭, GetComponentInChildren 사용 가능
✔ IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler

UI_Joystick 코드

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class UI_Joystick : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler,IDragHandler
{
    [SerializeField]
    Image _bg;
    [SerializeField]
    Image _handler;

    float _joystickRadius;
    Vector2 _touchPosition;
    Vector2 _moveDir;

    PlayerController _player;

    void Start()
    {
        _joystickRadius = _bg.gameObject.GetComponent<RectTransform>().sizeDelta.y / 2;
        // Temp1 Joystick-Player (Find)
        _player = GameObject.Find("Slime_01").GetComponent<PlayerController>();
    }

    public void OnPointerClick(PointerEventData eventData)
    {

    }

    public void OnPointerDown(PointerEventData eventData)
    {
        _touchPosition = eventData.position;
        _bg.transform.position = eventData.position;
        _handler.transform.position = eventData.position;
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        _handler.transform.position = _touchPosition;
        _moveDir = Vector2.zero;

        // Temp1 Joystick-Player (Find)
        //_player.MoveDir = _moveDir;

        // Temp2 Joystick-Player (Manager(Static))
        Managers.MoveDir = _moveDir;
    }

    public void OnDrag(PointerEventData eventData)
    {
        Vector2 touchDir = (eventData.position - _touchPosition);
        float moveDist = Mathf.Min( touchDir.magnitude, _joystickRadius);
        _moveDir = touchDir.normalized; //방향
        Vector2 newPosition = _touchPosition + _moveDir * moveDist;
        _handler.transform.position = newPosition;

        // Temp1 Joystick-Player (Find)
        //_player.MoveDir = _moveDir;

        // Temp2 Joystick-Player (Manager(Static))
        Managers.MoveDir = _moveDir;
    }
}





JoyStick - Player 연결

✔ 3가지 방법
✔ 1. Find로 PlayerContorller 찾기 -> 사용 X
✔ 2. Managers (Static) -> 매 프레임마다 통신하기 힘듦
✔ 3. 델리게이트, 콜백

1. 조이스틱스크립트에서 Find로 PlayerController
_player.MoveDir = _moveDir;
PlayerController - 프로퍼티

public class UI_Joystick : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler,IDragHandler
{
    PlayerController _player;

    void Start()
    {
        _player = GameObject.Find("Slime_01").GetComponent<PlayerController>();
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        _player.MoveDir = _moveDir;
    }

    public void OnDrag(PointerEventData eventData)
    {
        _player.MoveDir = _moveDir;
    }
}


public class PlayerController : MonoBehaviour
{
    Vector2 _moverDir = Vector2.zero;

    public Vector2 MoveDir 
    {
        get { return _moverDir; }
        set { _moverDir = value.normalized; }
    }
}





2. 공용으로 사용하는 데이터를 Managers에 담아서 사용
Static을 이용해 Managers.MoveDir

public class UI_Joystick : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler,IDragHandler
{
    public void OnPointerUp(PointerEventData eventData)
    {
        _moverDir = Managers.MoveDir;
    }

    public void OnDrag(PointerEventData eventData)
    {
        _moverDir = Managers.MoveDir;
    }
}

public class Managers : MonoBehaviour
{
    public static Vector2 MoveDir;
}

public class PlayerController : MonoBehaviour
{
    void MovePlayer() {
        _moverDir = Managers.MoveDir;

        Vector3 dir = _moverDir * _speed * Time.deltaTime;
        transform.position += dir;
    }
}





3. 델리게이트 콜백 (4강내용)
델리게이트 - 데이터가 바뀌었을 때 구독한 곳으로 알려준다.
✔ 조이스틱으로 Managers.Game.MoveDir가 변경된다.
✔ set => OnMoveDirChanged
✔ OnMoveDirChanged 구독되어 있는 곳들에게 알려준다.
✔ PlayerController Start에서 이벤트를 미리 구독했다.
✔ HandleOnMoveDirChanged(이벤트가 발생하면 실행될 메서드)로 Player의 _moverDir를 변경

public class UI_Joystick : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler,IDragHandler
{
    public void OnDrag(PointerEventData eventData)
    {
        Vector2 touchDir = (eventData.position - _touchPosition);
        float moveDist = Mathf.Min( touchDir.magnitude, _joystickRadius);
        _moveDir = touchDir.normalized; //방향
        Vector2 newPosition = _touchPosition + _moveDir * moveDist;
        _handler.transform.position = newPosition;

        // Temp2 Joystick-Player (Manager(Static))
        Managers.Game.MoveDir = _moveDir;
    }
}

public class GameManager 
{
    Vector2 _moveDir;

    public event Action<Vector2> OnMoveDirChanged;

    public Vector2 MoveDir
    {
        get { return _moveDir; }
        set 
        {   
            _moveDir = value;
            OnMoveDirChanged?.Invoke(_moveDir);
        }
    }
}

public class PlayerController : MonoBehaviour
{
    // 구독
    void Start()
    {
        Managers.Game.OnMoveDirChanged += HandleOnMoveDirChanged;
    }

    void OnDestroy()
    {
        if (Managers.Game != null)
            Managers.Game.OnMoveDirChanged -= HandleOnMoveDirChanged;
    }
    // 이벤트가 발생하면 실행될 메서드
    void HandleOnMoveDirChanged(Vector2 dir) 
    {
        _moverDir = dir;
    }
}





이것저것 메모

Canvas Scaler

✔ Canvas Scaler - UI Scale Mode -> Scale With Screen Size
✔ 화면크기에 맞게 UI 조정



Raycast Target

✔ Raycast Target 체크 확인



vector크기(거리)

✔ magnitude = vector의 크기(거리)



Static

✔ Static - 객체랑 무관하다. (종속x)





잡담, 일기?

게임 오브젝트 - 컴포넌트의 연결 좋은 방법으로 (중요!)




📔

댓글남기기