반응형
SMALL
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UIJoystick : MonoBehaviour , IBeginDragHandler, IEndDragHandler,IDragHandler
{
public RectTransform lever; //레버의(조이스틱) 의 렉트 트랜스폼
private RectTransform rectTransform; //레버 bg의 렉트 트랜스폼
[SerializeField, Range(10f, 150f)] //SerializeField 뒤에 "," 를 부팅고 Rage 클래스를 이용해 범위 지정 가능
private float leverRange; //레버의(조이스틱) 의 렉트 트랜스폼 과 레버 bg의 렉트 트랜스폼 사이의 거리
private Vector2 inputVector; //플레이어를 이동시킬 Vector2 형식의 최종값
private bool isInput; //터치패드 아날로그가 눌렸는지 아닌지를 알기위한 부울값
public GameObject player; // 플레이어 움직임 제어를 위한 플레이어 오브젝트 변수
public float clampedSpeed = 500.0f; // 레버 범위에 따른 플레이어 스피드 제어
public enum state
{
Idle = 0,
Up = 1,
Right = 2,
Down = 3,
Left = 4
}
public void Awake()
{
//레버 bg의 렉트 트랜스폼 변수 할당
this.rectTransform = GetComponent<RectTransform>();
}
public void OnBeginDrag(PointerEventData eventData)
{
//이벤트 데이터 형식 값을 ControlJoystickLever 함수에 할당
ControlJoystickLever(eventData);
//아날로그 패드가 눌렸을떄 부울값 true
this.isInput = true;
}
public void OnDrag(PointerEventData eventData)
{
ControlJoystickLever(eventData);
}
public void OnEndDrag(PointerEventData eventData)
{
//아날로그 에서 손을 떼면 레버의 엥커 포지션 초기화(0,0)
this.lever.anchoredPosition = Vector2.zero;
//인풋 부울값 false
this.isInput = false;
}
public void ControlJoystickLever(PointerEventData eventData)
{
//인풋 방향은 이벤트 데이터의 포지션에서 레버 bg의 렉트 트랜스폼 앵커드포지션 값을 뺀 값을 방향으로 변수에 담기
Vector2 inputDir = eventData.position - rectTransform.anchoredPosition;
//조건연산자 ? 는 조건을 기준으로 true라면 ":"의 왼쪽 false라면 오른쪽의 값을 변수에 대입할수 있는 연산자이다.
//magnitude는 백터의 길이 즉 bg의 앵커 중앙 값부터 터치한 부분까지의 거리를 말함
//magnitude가 leverRange의 범위를 벗어난다면 normalized한 값(1) 에 레버의 레인지를 곱해 캐릭터의속도가 너무 빨라지는걸 방지
Vector2 clampedDir = inputDir.magnitude < leverRange ? inputDir
: inputDir.normalized * leverRange;
//레버의 앵커드포지션에 vector2 clampedDir 값 할당 (레버의 범위가 벗어나지 않게)
this.lever.anchoredPosition = clampedDir;
//플레이어를 이동시킬 Vector2 형식의 최종값은 앵커드 포지션 / leverRange
this.inputVector = clampedDir / this.clampedSpeed;
Debug.Log(this.inputVector);
}
private void InputControlVector()
{
//캐릭터 컨트롤러를 이용하여 플레이어 오브젝트 이동
this.player.GetComponent<CharacterController>().Move(this.inputVector);
}
void Update()
{
//인풋이 들어왔다면
if (isInput)
{
//플레이어 이동 함수 실행
InputControlVector();
}
if (this.lever.anchoredPosition.y > 0) this.player.GetComponent<Animator>().SetInteger("state",(int)state.Up);
if (this.lever.anchoredPosition.x > 0) this.player.GetComponent<Animator>().SetInteger("state", (int)state.Right);
if (this.lever.anchoredPosition.y < 0) this.player.GetComponent<Animator>().SetInteger("state", (int)state.Down);
if (this.lever.anchoredPosition.x < 0) this.player.GetComponent<Animator>().SetInteger("state", (int)state.Left);
if (this.lever.anchoredPosition.x == 0 && this.lever.anchoredPosition.y == 0) this.player.GetComponent<Animator>().SetInteger("state", (int)state.Idle);
}
}
우선 조건 연산자에 대해 좀더 찾아봐야 할듯하고 magnitude 와 anchoredPosition 의 경우 처음 사용해보는 프로퍼티기에 좀더 익숙해질 필요가 있어보인다.
또 애니메이션을 추가해보았는데 아날로그 인풋 기준으로 애니메이션을 정해주니 뭔가 자연스럽지 않은 느낌이 강해 이걸 좀더 자연스럽게 구현하는 방향으로 애니메이션을 연구해 보아야겠다.
또 조작감의 경우 아날로그 inputVector의 값을 그대로 사용하니 좀 가속도가 붙는 느낌이 있어 노말라이즈 된 (1로 고정된) 값을 받게 할지 여부도 고민을 해보아야겠다 ( 아케이드 적인 느낌을 살리려면 노말라이즈된 조작감이 좀더 좋을듯하다)
반응형
LIST
'프로젝트 > 건즈앤 레이첼스' 카테고리의 다른 글
[유니티] 게임 진입 구조잡기 - as연산자, 비동기식 데이터 로드 (0) | 2023.02.27 |
---|---|
[유니티] 대쉬 (회피) 기능 고민 (0) | 2023.02.26 |
[유니티] 터치 아날로드 패드를 이용한 무기 회전 (0) | 2023.02.26 |
[유니티] 2d 스프라이트 회전 (스크린 터치 회전 시키기) (0) | 2023.02.26 |
[유니티] 캐릭터 카메라 제어 : Update() 와 FixedUpdate() 그리고 LateUpdate() (0) | 2023.02.26 |