[Unity] 클릭 이벤트 관리 : GameManager
요약
클릭 이벤트는 여러 스크립트에서 사용하므로 유일성을 가지는 GameManager로 관리된다. 다만 클릭하여도 오브젝트의 데이터가 갱신되지 않거나, RaycastHit2D클래스로 오브젝트의 데이터를 전역 변수에 저장되어도 다른 곳을 클릭 시 갱신되어 버그가 발생하는 등 여러 문제가 발생한다. 이를 해결하기 위해 RaycastHit2D[] hits로 한 지점에 여러 오브젝트가 있어도 가장 가까운 오브젝트를 선택하거나 MyHit클래스를 만들어 이름만 초기화하는 방법을 고안하였다.
GameManager.cs
public class GameManager : MonoBehaviour
{
... 생략 ...
public Hit MyHit { get; set; }
... 생략 ...
private void Update()
{
... 생략 ...
if (player.Die) return;
MousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
MousePosInt = new Vector3Int(
(int)Mathf.Round(MousePos.x),
(int)Mathf.Round(MousePos.y),
(int)Mathf.Round(MousePos.z)
);
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D[] hits = Physics2D.RaycastAll(MousePos, Vector2.zero);
if (hits.Length > 0)
{
if (EventSystem.current.IsPointerOverGameObject()) return;
print(hits[0].transform.name);
}
try{
MyHit.name = hits[0].collider.name;
MyHit.positionInt = new Vector3Int(
(int)Mathf.Round(hits[0].collider.transform.position.x),
(int)Mathf.Round(hits[0].collider.transform.position.y),
(int)Mathf.Round(hits[0].collider.transform.position.z)
);
}
catch
{
MyHit.name = "";
}
}
... 생략 ...
}
}
MousePos: 마우스 현재 위치를 저장 (정수)
MousePosInt: 마우스 현재 위치를 저장 (실수)
MyHit: 마우스 클릭한 오브젝트 이름, 마우스 클릭 위치를 저장 (정수)
클릭 관리
Hit클래스에는 string과 Vertor3Int의 자료형을 가졌다. 이를 클릭 시 충돌된 오브젝트 이름, 위치를 가져올 수 있도록 한다.
여기서 RaycastHit2D클래스를 통해 바로 가져오는 방법을 생각할 수 있지만, 실제로 RaycastHit2D클래스에서 바로 가져오면 중간에 다른 것을 클릭하여 정보가 소실되는 경우가 있다.
예를 들어 클릭한 위치를 기반으로 오브젝트가 이동 중인데 다른 곳을 클릭하여 클릭한 위치가 달라지면 코드가 원치 않은 방향으로 동작할 수 있다.
그 외에도 전역변수를 사용하여 클릭한 정보를 저장해 두거나, 클릭을 잠가버리는 방법도 존재하겠지만 string, Vertor3Int을 저장하는 클래스를 두고 다른 곳을 클릭 시 string만 초기화하고 Vertor3Int을 유지하는 방법이 간단하였다. 개인적인 생각으로는 불안정한 방법이라 생각한다.
try{
MyHit.name = hits[0].collider.name;
MyHit.positionInt = new Vector3Int(
(int)Mathf.Round(hits[0].collider.transform.position.x),
(int)Mathf.Round(hits[0].collider.transform.position.y),
(int)Mathf.Round(hits[0].collider.transform.position.z)
);
}
catch
{
MyHit.name = "";
}
try catch를 통해 오브젝트가 아무것도 없을 시 MyHit의 name을 초기화한다.
클릭 오류
중복되는 코드를 통합하기 위해 클릭 이벤트를, 유일성을 가지는 GameManager로 관리하게 되었다. 하지만 중요한 건 클릭 이벤트가 잘 작동하지 않은 점도 존재한다.
RaycastHit2D[] hits = Physics2D.RaycastAll(MousePos, Vector2.zero);
if (hits.Length > 0)
{
if (EventSystem.current.IsPointerOverGameObject()) return;
print(hits[0].transform.name);
}
해당 코드를 보면 특이하게 RaycastHit2D[] hits의 배열인 것을 볼 수 있다. 이는 클릭 시 여러 오브젝트와 부딪히는데 이를 배열에 넣고 가장 가까운 오브젝트를 가져오는 것이다. 실제로 이것이 효과가 좋은진 모르겠지만 일단 오브젝트 생성 시 카메라 가까이 생성하게 하여 조금 나아지긴 하였다.