공부/인프런 - Rookiss

Part 3-13-3. 미니 RPG : 타겟 락온

셩잇님 2023. 8. 31. 18:52
반응형

 

 

미니 RPG

 

📜Define

    public enum MouseEvent
    {
        Press,
        PointerDown,  // 마우스 뗀 상태에서 처음 눌렀을 때
        PointerUp,  // 마우스 누르고 있던 상태에서 처음 뗏을 때
        Click,
    }

 

 

Press : 누르는 동안

PointerDown : 안 누르고 있던 상태에서 처음으로 눌렀을 때

PointerUp : 0.2초 이상 꾹 누르고 있던 상태에서 처음으로 뗏을 때 (꽤 누르고 있다가 뗐을 때)

Click : 0.2초 이하로 누르고 있던 상태에서 처음으로 뗏을 때 (말 그대로 클릭 수준. 찰나만 누르고 뗐을 떄)

 

📜InputManager

public class InputManager
{
    public Action KeyAction = null;
    public Action<Define.MouseEvent> MouseAction = null;

    bool _pressed = false;
    float _pressedTime = 0;

    public void OnUpdate()
    {
        if (EventSystem.current.IsPointerOverGameObject())
            return;

        if (Input.anyKey && KeyAction != null)
				KeyAction.Invoke();

        if (MouseAction != null)
        {
            if (Input.GetMouseButton(0)) // PointerDown -> Press
            {
                if (!_pressed) // 한번도 눌렀던적이 없었는데 클릭 들어온거면 
                {
                    MouseAction.Invoke(Define.MouseEvent.PointerDown);
                    _pressedTime = Time.time; // start 이후 경과 시간 (구분만 할 수 있으면 됨)
                }
                MouseAction.Invoke(Define.MouseEvent.Press); // 비효율적일 수 있음(이벤트 발생)
                _pressed = true;
            }
            else // Click(금방 뗏을 때) -> PointerUp(좀 오래 눌려있다가 뗏을 때)
            {
                if (_pressed)  // 클릭 이벤트는 안들어왔는데 눌린 상태였었다면
                {
                    if (Time.time < _pressedTime + 0.2f) // 0.2초 내에 뗐을때
                        MouseAction.Invoke(Define.MouseEvent.Click);
                    MouseAction.Invoke(Define.MouseEvent.PointerUp);
                }
                _pressed = false;
                _pressedTime = 0;
            }
        }
    }

 

MouseAction : Define.MouseEvent 을 인수로 받는 함수만 등록 가능한 액션. 📜PlayerController에서 이 인수가 무엇인지에 따라 다르게 동작하도록 설정한다.

 

_pressedTime : Click 과 PointerUp 을 구분하기 위해 누르는 시간을 샐 것이다. 0.2 초 이하로 누르면 Click, 0.2 초 이상으로 누르면 PointerUp 로 인식되게 설정한다.

 

마우스 클릭 발생 ⭕ if (Input.GetMouseButton(0))

1. if (!_pressed) 👉 한번도 눌렀던적이 없었는데 클릭 들어온거면 PointerDown

  • 이제부터 누르는 동안의 시간인 _pressedTime 타이밍을 시작해야 한다. Time.time은 Start() 함수 시작 후 실행 시간이다. 현재 플레이한 초 단위의 시간이라고 생각하면 될 것 같다. Time.time < _pressedTime + 0.2f 로 0.2초 이상 눌렀는지 아닌지를 비교하는데 쓸거라 Time.time 이용한 것이다.

 

마우스 클릭 발생 ❌

1. if (_pressed) 👉 방금까지 누르고 있더 상태였다면

  • 누른지 0.2초 이내 Click
  • 누른지 0.2초 이상 PointerUp
  • _pressed와 _pressedTime 리셋

 

 

누르는 동안엔 MouseAction.Invoke(Define.MouseEvent.Press); 로 인해 매 프레임마다 이벤트를 발생시킬 수 있으니 성능상 비효율적일 수도 있다. Update문에서 Input.GetMouseButton

 

📜PlayerController

	void UpdateMoving()
	{
		// ...
			if (Physics.Raycast(transform.position + Vector3.up * 0.5f, dir, 1.0f, LayerMask.GetMask("Block")))
			{
				if (Input.GetMouseButton(0) == false) //
					State = PlayerState.Idle;
				return;
			}
		}
	}

 

마우스를 꾹 누르고 있는 상태면 (그러니까 Input.GetMouseButton(0)가 true 이면) 커서가 “Block”에 있더라도 달리는 상태를 유지하도록 한다.

    int _mask = (1 << (int)Define.Layer.Ground) | (1 << (int)Define.Layer.Monster);

    GameObject _lockTarget;

	void OnMouseEvent(Define.MouseEvent evt)
	{
		switch (State)
		{
			case PlayerState.Idle:
				OnMouseEvent_IdleRun(evt);
				break;
			case PlayerState.Moving:
				OnMouseEvent_IdleRun(evt);
				break;
			case PlayerState.Skill:
				{
					if (evt == Define.MouseEvent.PointerUp)
						_stopSkill = true;
				}
				break;
		}
	}

	void OnMouseEvent_IdleRun(Define.MouseEvent evt)
	{
		RaycastHit hit;
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		bool raycastHit = Physics.Raycast(ray, out hit, 100.0f, _mask);

		switch (evt)
		{
			case Define.MouseEvent.PointerDown: // 처음으로 누른 순간
				{
					if (raycastHit)
					{
						// 몬스터 클릭했든 아니든 클릭한 곳으로 이동은 해야.
						_destPos = hit.point;
						State = PlayerState.Moving;

						if (hit.collider.gameObject.layer == (int)Define.Layer.Monster) // 몬스터 타겟
							_lockTarget = hit.collider.gameObject; // 몬스터 저장
						else  // 몬스터 타겟이 아닐 때
							_lockTarget = null;
					}
				}
				break;
			case Define.MouseEvent.Press:  // 누르는 동안
				{
					if (_lockTarget != null)
						_destPos = _lockTarget.transform.position; // 누르는 동안에도 몬스터를 따라가야
                    else if (raycastHit)
                        _destPos = hit.point;  // 누르는 쪽으로!
				}
				break;
		}
	}

 

PointerDown일 때 (처음 누른 순간)

if (raycastHit) 몬스터 혹은 땅에 화면클릭 Raycast 가 충돌했을 때  클릭한 곳으로 이동해야 한다. (_destPos, State 업데이트)

 

1. 몬스터를 클릭했을 때

  • _lockTarget에 몬스터 오브젝트 저장

2. 땅 클릭했을 때

  • _lockTarget null

 

 

Press일 때 (누르는 동안)

1. 몬스터 타겟인 상태라면 if (_lockTarget != null)

누르고 있는 동안에도 몬스터를 향해 가야한다. (위 gif 참고)

 

2.땅 타겟인 상태라면

누르고 있는 동안이더라도 커서가 향하는 곳으로 가야 한다.

 

 

 

반응형