1 minute read

배운 내용

제너릭 싱글톤 생성

게임을 진행할 때 게임 내에서만 사용되고 메인 화면으로 나가면 사용하지 않는 특수한 싱글톤을 제너릭으로 만들어 중복 코드를 줄였습니다.

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를 눌러주면 나머지는 다른 방식과 동일하게 사용할 수 있습니다.

스크린샷 2024-07-01 195810

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로 충돌 검사

충돌 검사를 통해 유닛들이 사각형에 들어오면 리스트에 저장하고, 나가면 빼줍니다.

스크린샷 2024-07-01 200352

드래그 중에는 범위에서 나가면 빼주지만, 드래그가 끝나면 범위에서 나가도 빼면 안 됩니다. 다시 좌클릭을 하면 선택된 유닛들을 모두 해제하고 새로 받을 준비를 합니다. 이렇게 스타크래프트와 비슷하게 드래그하여 여러 유닛을 선택할 수 있도록 구현했습니다.

느낀 점

  • 그룹 선택 기능을 구현하면서 물리 충돌 방식과 UI 조작에 대해 더 깊이 이해하게 되었습니다.
  • 화면 비율 변화에 따른 UI 문제를 해결하기 위한 추가적인 기능 구현이 필요하지만, 현재는 프로토타입을 완성하고 게임 사이클 1회를 구현하는 것이 목표입니다.
  • 앞으로도 이러한 부가적인 기능들은 프로젝트 진행 상황에 따라 차차 구현해나갈 계획입니다.