내일배움캠프 53일차 7/01 TIL + 그룹 컨트롤 구현
배운 내용
제너릭 싱글톤 생성
게임을 진행할 때 게임 내에서만 사용되고 메인 화면으로 나가면 사용하지 않는 특수한 싱글톤을 제너릭으로 만들어 중복 코드를 줄였습니다.
public class InGameSingleton<T> : MonoBehaviour where T : InGameSingleton<T>
{
protected static T instance;
public static T Instance
{
get
{
if (instance == null)
{
GameObject gameObject = new GameObject();
instance = gameObject.AddComponent<T>();
}
return instance;
}
}
}//밑에 Awake와 Destroy도 있음
그룹 선택 물리 충돌 방식으로 변경
Input System을 활용한 그룹 선택 구현
Input System을 활용하여 C# 이벤트 방식으로 마우스 입력 이벤트에 따른 그룹 선택 방식을 제작했습니다. C# 이벤트 방식은 만든 Input action에서 Generate C# Class 설정을 해주고 Apply를 눌러주면 나머지는 다른 방식과 동일하게 사용할 수 있습니다.
protected override void Awake()
{
base.Awake();
playerInputActions = new PlayerInputActions();
SelectedUnits = new List<ISelectable>();
}
// 이벤트들을 실행 시켜주고, 함수를 할당해준다.
private void OnEnable()
{
mouseLeftClick = playerInputActions.User.MouseLeftClick;
mouseRightClick = playerInputActions.User.MouseRightClick;
mouseDrag = playerInputActions.User.MouseDrag;
mouseLeftClick.Enable();
mouseRightClick.Enable();
mouseDrag.Enable();
mouseLeftClick.started += MouseLeftClick;
mouseDrag.started += MouseDrag;
mouseDrag.performed += MouseDrag;
mouseLeftClick.canceled += MouseLeftUp;
}
마우스 좌클릭 초기화
마우스 좌클릭 시 드래그를 준비하는 초기화를 담당하며, 선택되어 있던 유닛 목록을 초기화합니다.
public void MouseLeftClick(InputAction.CallbackContext context)
{
isMouseLeftDown = true;
MouseStartPos = mouseDrag.ReadValue<Vector2>();
selectArea.gameObject.SetActive(false);
isDragging = false;
RemoveAllSelectedUnit();
}
드래그 실행
최종적으로 드래그를 실행하면 마우스 포인트를 RectTransformUtility.ScreenPointToWorldPointInRectangle
함수를 사용해 월드 포인트로 바꿔줍니다.
if (isDragging)
{
Debug.Log("Mouse Dragging");
selectArea.IsSelecting = true;
Vector3 worldStartPos, worldCurrentPos;
RectTransformUtility.ScreenPointToWorldPointInRectangle(selectArea.GetComponent<RectTransform>(), MouseStartPos, Camera.main, out worldStartPos);
RectTransformUtility.ScreenPointToWorldPointInRectangle(selectArea.GetComponent<RectTransform>(), currentMousePos, Camera.main, out worldCurrentPos);
selectArea.GetComponent<SelectionArea>().SetSize(worldStartPos, worldCurrentPos);
}
사각형 UI 내에서 사이즈와 콜라이더 크기 조절
사각형 UI 내에서 사이즈와 콜라이더 크기를 조절합니다. 사이즈는 WorldSpace 캔버스에 UI라 월드 좌표 사이즈와 동일합니다.
public void SetSize(Vector2 MouseStartPos, Vector2 endPoint)
{
float areaWidth = endPoint.x - MouseStartPos.x;
float areaHeight = endPoint.y - MouseStartPos.y;
rectTransform.sizeDelta = new Vector2(Mathf.Abs(areaWidth), Mathf.Abs(areaHeight));
rectTransform.anchoredPosition = (MouseStartPos + endPoint) / 2;
boxCollider.size = new Vector2(Mathf.Abs(areaWidth), Mathf.Abs(areaHeight));
}
OnTriggerEnter2D로 충돌 검사
충돌 검사를 통해 유닛들이 사각형에 들어오면 리스트에 저장하고, 나가면 빼줍니다.
드래그 중에는 범위에서 나가면 빼주지만, 드래그가 끝나면 범위에서 나가도 빼면 안 됩니다. 다시 좌클릭을 하면 선택된 유닛들을 모두 해제하고 새로 받을 준비를 합니다. 이렇게 스타크래프트와 비슷하게 드래그하여 여러 유닛을 선택할 수 있도록 구현했습니다.
느낀 점
- 그룹 선택 기능을 구현하면서 물리 충돌 방식과 UI 조작에 대해 더 깊이 이해하게 되었습니다.
- 화면 비율 변화에 따른 UI 문제를 해결하기 위한 추가적인 기능 구현이 필요하지만, 현재는 프로토타입을 완성하고 게임 사이클 1회를 구현하는 것이 목표입니다.
- 앞으로도 이러한 부가적인 기능들은 프로젝트 진행 상황에 따라 차차 구현해나갈 계획입니다.