[Unity] 3인칭 - 1. 조이스틱

홍예주·2021년 8월 24일

Unity - 3인칭 시점

목록 보기
1/1
post-thumbnail

1. UI 카메라 & UI Canvas 설정

1) UI 카메라 생성

UI만 렌더링해줄 카메라를 생성한다.

Clear Flags : Depth only로 변경
Culling Mask : UI로 변경(변경 전에 Layer에서 UI 레이어를 만들어줘야함)

2) 플레이어 화면(UI Canvas)

Layer를 UI로 설정한다.

  • Render Mode : Screen Space-Camera로 변경
  • Render Camera : 위에서 생성한 UI Camera를 넣어줌


  • CameraTouch : 조이스틱 부분을 제외하고 화면 드레그 시 카메라 회전 위한 오브젝트
  • joystick : 조이스틱 배경
  • lever : 조이스틱 레버

조이스틱을 Hierarchy 상으로 CameraTouch 밑에 둬서 렌더링 시 조이스틱이 위에 렌더링 되도록 한다. (조이스틱 드레그 시 카메라 회전 막기 위해)

2. 조이스틱 설정

1) Game object

  • 레버는 조이스틱의 자식 객체로 넣는다.
  • 조이스틱은 Rect Transform으로 좌측 하단 기준으로 생성되게 한다.

    (조이스틱 컨트롤러에서 좌측 하단부터 좌표값을 계산하게 하기 위함)

2) script - JoystickController

using UnityEngine;
using UnityEngine.EventSystems; 

//조이스틱 컨트롤러
public class JoystickController : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    [SerializeField]
    private RectTransform lever;
    private RectTransform rectTransform;

    //레버가 움직일 수 있는 범위
    [SerializeField, Range(10f, 150f)]
    private float leverRange;

    private Vector2 inputVector;
    private bool isInput;

    public Transform player;

    // CharacterController characterController;
    public  PlayerController characterController; //플레이어 움직임 제어
    public Animator animator;


    private Vector3 leverRotation;

    private void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
    }

    void Update()
    {
        //조이스틱 인풋이 발생할 때 마다
        if (isInput)
        {
            InputControlVector();
        }
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        //Debug.Log("Begin");

        ControlJoystickLever(eventData);
        isInput = true;

    }

    public void OnDrag(PointerEventData eventData)
    {
        //Debug.Log("Drag");
        ControlJoystickLever(eventData);

    }


    public void OnEndDrag(PointerEventData eventData)
    {
        //Debug.Log("End");

        lever.anchoredPosition = Vector2.zero;
        animator.SetBool("isMove", false);
        isInput = false;
    }

    //조이스틱 입력을 벡터로 전환
    //조이스틱 각도를 벡터로 전환
    public void ControlJoystickLever(PointerEventData eventData)
    {
        var inputDir = eventData.position - rectTransform.anchoredPosition;
        var clampedDir = inputDir.magnitude < leverRange ? inputDir
            : inputDir.normalized * leverRange;

        lever.anchoredPosition = clampedDir;
        inputVector = clampedDir / leverRange;

	//조이스틱 각도에 따라 플레이어 회전 위해
        //270을 더한 이유 : x축 기준으로 반대 방향으로 뒤집어져서 이동해서 270도 더해줌
        leverRotation = new Vector3(0, (Mathf.Atan2(lever.anchoredPosition.x, lever.anchoredPosition.y)+270) * Mathf.Rad2Deg,0);

    }

    private void InputControlVector()
    {
        //Debug.Log(inputVector.x + " / " + inputVector.y);
        if (characterController)
        {
            //플레이어 컨트롤러의 Move 호출
            characterController.Move(inputVector, leverRotation);
        }
    }
}

3. 플레이어 컨트롤러 설정

1) script - PlayerController

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

//플레이어 이동 제어
public class PlayerController : MonoBehaviour
{

    public float speed = 4;    //플레이어 속도
    public Transform Maincam;

    Rigidbody rid;
    Animator animator;


    public void Start()
    {
        rid = GetComponent<Rigidbody>();
        animator = GetComponent<Animator>();

    }


    //JoystickController에서 사용
    //moveInput - 조이스틱 입력
    //rotate - 조이스틱 각도
    public void Move(Vector2 moveInput, Vector3 rotate)
    {
        bool isMove = moveInput.magnitude != 0;

        //달리기 모션 재생
        animator.SetBool("isMove", isMove);

        if (isMove)
        {
            //조이스틱 각도에 따라 플레이어 회전
            rid.transform.rotation = Quaternion.Euler(rotate);


	    // 플레이어 캐릭터가 실제 사용자에게 등을 보이고 움직이기 때문에 방향을 모두 뒤집어줌
            Vector3 moveHorizontal = transform.right * -moveInput.y;
            Vector3 moveVertical = transform.forward * -moveInput.x;


            Vector3 velocity = (moveHorizontal + moveVertical).normalized * speed;
            
            //플레이어 이동
            rid.transform.Translate(velocity * Time.fixedDeltaTime);

        }

        else
        {
            //멈췄을때 빙글빙글 도는거 방지
            rid.transform.rotation = Quaternion.Euler(new Vector3(0,0,0));

        }

        
    }

}

4. 현재 문제점

1) 카메라 회전과 플레이어 회전이 엇나감

-> 270도 더하고 x방향 뒤집어서 해결

profile
기록용.

0개의 댓글