게임클라이언트 프로그래밍/Guns N Rachel's

Chest 에서 DropItem 생성 로직 변경, 버그 수정

Game Client Lee Hwanguk 2023. 5. 22. 02:24

* Chest에서 DropItem이 생성되는 로직을 변경하고 버그를 수정했다.

기존에는 2f의 반지름을 갖은 원 안에서 랜덤한 위치에 생성되게 하는 로직이 었지만 

아이템들 간의 거리가 너무 좁고 한쪽으로 치우치게 생성되는 문제가 있어서 연출 적으로 너무 어색해보였다.

로직을 어서 변경해야겠다

 

12개의 위치를 잡은 후 해당 위치에 DropItem이 생성되게 변경해야겠다

한쪽으로 치우치게 보이는 문제는             

*Vector2 randomOffset = Quaternion.Euler(0f, 0f, randomAngle) * Vector2.right * randomRadius;

의 Vector2.right 로 정해져있기 떄문에 생기는 문제였다.

*Random.insideUnitCircle.normalized * radius;

로 변경 후 해결했다.

 

12개의 포인트로 위치를 지정해주게 하는 로직 코드이다

Vector2 playerPosition = callPosition.position;
        float radius = 3f;
        float minDistance = 1.5f;

        int maxAttempts = 12; //12개의 요소를 돌아가며 비어있는 요소 체크
        int attempts = 0;

        Vector2 randomOffset = Vector2.zero;
        Vector2 randomPosition = Vector2.zero;

        do
        {
            randomOffset = Random.insideUnitCircle.normalized * radius;
            randomPosition = playerPosition + randomOffset;
            attempts++;
        }
        while (attempts < maxAttempts && Vector2.Distance(playerPosition, randomPosition) < minDistance);

        if (attempts >= maxAttempts)
        {
            // 최대 시도 횟수를 초과하여 위치를 찾지 못한 경우
            return;
        }

        dropItemGo.transform.position = callPosition.position;

각자 다른 메서드에서 구현하고 있으니 중복되면 안되는 문제가 있었다. 

각 요소에 오브잭트가 있는지 중복 체크를 해야한다. 아직 이 문제는 좀더 손봐야한다

지금은 12개의 방향으로 골고루 생성은 되지만 DiamondChest에서는 여러 아이템(Item,Goods,Weapon,Relic)이 생성되기때문에 중복문제를 피할수 없었다. 분명 가까운 곳에 해결방법이 있을 것같다.

 

연출도 추가했다. 상자에서 부터 생성되어 waypoint로 갈때 선형적으로 움직이게 하고 
"Weapon"은 가장 중요한 Item임을 보여주기 위해 DoScale을 이용해 연출을 추가해주었다

dropItemGo.transform.DOMove(randomPosition, 1f).SetEase(Ease.InQuart).OnComplete(() =>
        {
            if (dropItemGo.CompareTag("Weapon"))
            {
                Vector3 originalScale = dropItemGo.transform.localScale;
                float assetScalePercent = 1.5f;
                Vector3 targetScale = originalScale * assetScalePercent;

                // 아이템의 크기를 반복적으로 변경하는 연출
                dropItemGo.transform.DOScale(targetScale, 1f).SetEase(Ease.InOutQuad).SetLoops(-1, LoopType.Yoyo);
            }

            // 충돌 감지 활성화
            collider.enabled = true;
        });

*연출을 추가해보니 치명적인 문제가 생겼다. 플레이어가 상자와 충돌후 상자의 위치에 있다면 연출을 보기도 전에, 그리고 아이템이 waypoint로 가기전에 아이템을 먹게되는 버그가 보였다

Dotween의 애니메이션이 끝나는 시점에서 콜라이더를 활성화 시켜줘야했다.

수정된 코드이다

//충돌 레이어 설정
        int playerLayer = LayerMask.NameToLayer("Player");
        int itemLayer = LayerMask.NameToLayer("item");
        Physics2D.IgnoreLayerCollision(playerLayer, itemLayer); //IgnoreLayerCollision:두개의 레이어간의 충돌을 무시하도록 함

        // BoxCollider2D 컴포넌트 참조
        BoxCollider2D collider = dropItemGo.GetComponent<BoxCollider2D>();

        // 충돌 감지 비활성화
        collider.enabled = false;

        dropItemGo.transform.DOMove(randomPosition, 1f).SetEase(Ease.InQuart).OnComplete(() =>
        {
            if (dropItemGo.CompareTag("Weapon"))
            {
                Vector3 originalScale = dropItemGo.transform.localScale;
                float assetScalePercent = 1.5f;
                Vector3 targetScale = originalScale * assetScalePercent;

                // 아이템의 크기를 반복적으로 변경하는 연출
                dropItemGo.transform.DOScale(targetScale, 1f).SetEase(Ease.InOutQuad).SetLoops(-1, LoopType.Yoyo);
            }

            // 충돌 감지 활성화
            collider.enabled = true;
        });

 

*구현한 전체 코드이다. 아직 다른 종류의 아이템이 겹치는 문제는 있으나 12개으 방향으로 잘 생성되긴한다.

조금 더 수정이 필요하다

private void SetRandomPos(Transform callPosition, GameObject dropItemGo)
    {
        Vector2 playerPosition = callPosition.position;
        float radius = 3f;
        float minDistance = 1.5f;

        int maxAttempts = 12; //12개의 요소를 돌아가며 비어있는 요소 체크
        int attempts = 0;

        Vector2 randomOffset = Vector2.zero;
        Vector2 randomPosition = Vector2.zero;

        do
        {
            randomOffset = Random.insideUnitCircle.normalized * radius;
            randomPosition = playerPosition + randomOffset;
            attempts++;
        }
        while (attempts < maxAttempts && Vector2.Distance(playerPosition, randomPosition) < minDistance);

        if (attempts >= maxAttempts)
        {
            // 최대 시도 횟수를 초과하여 위치를 찾지 못한 경우
            return;
        }

        dropItemGo.transform.position = callPosition.position;

        

        //충돌 레이어 설정
        int playerLayer = LayerMask.NameToLayer("Player");
        int itemLayer = LayerMask.NameToLayer("item");
        Physics2D.IgnoreLayerCollision(playerLayer, itemLayer); //IgnoreLayerCollision:두개의 레이어간의 충돌을 무시하도록 함

        // BoxCollider2D 컴포넌트 참조
        BoxCollider2D collider = dropItemGo.GetComponent<BoxCollider2D>();

        // 충돌 감지 비활성화
        collider.enabled = false;

        dropItemGo.transform.DOMove(randomPosition, 1f).SetEase(Ease.InQuart).OnComplete(() =>
        {
            if (dropItemGo.CompareTag("Weapon"))
            {
                Vector3 originalScale = dropItemGo.transform.localScale;
                float assetScalePercent = 1.5f;
                Vector3 targetScale = originalScale * assetScalePercent;

                // 아이템의 크기를 반복적으로 변경하는 연출
                dropItemGo.transform.DOScale(targetScale, 1f).SetEase(Ease.InOutQuad).SetLoops(-1, LoopType.Yoyo);
            }

            // 충돌 감지 활성화
            collider.enabled = true;
        });
    }

# Equipment 만 생성된다면 문제 없이 생성되지만

# 다른 종류의 아이템 gold, ether, weapon, relic 과 같이 생성될때 아이템이 겹치는 문제가있다.

waypoint가 겹치는 문제로 보인다.