내일배움캠프/TIL

[내배캠][Unity6기][TIL] Unity 숙련 주차 개인 과제 점검

binary는 호남선 2024. 10. 30. 11:37

내집 마련의 소망을 담아 열심히 제작한 과제입니다...

근데 아직 공사중

https://github.com/00ovo00/APeTitexplore

Preview

- 보완할 점

- 트러블슈팅


보완할 점

(개인 점검)

- 사운드 미지원

- 아이템 ScriptableOject 상속으로 분리하기

- 평면도 오브젝트 위에서 내려다 봤을 때만 상호 작용 가능하도록 제한

(튜터님 점검은 피드백 받고 추가 예정..)

 

트러블슈팅

문제상황:  커지는 아이템 사용 시 이미 플레이어가 커진 상태임에도 아이템 사용 버튼이 활성화되는 버그 발생

문제 분석: 유니티에 디버거를 연결하여 문제 동작을 확인

문제 원인:

/* UIInventory.cs */
public void OnUseButton()
{
    if(selectedItem.item.type == ItemType.Consumable)
    {
        for(int i = 0; i < selectedItem.item.consumables.Length; i++)
        {
            switch (selectedItem.item.consumables[i].type)
            {
                case ConsumableType.Health:
                    condition.Heal(selectedItem.item.consumables[i].value);
                    break;
                case ConsumableType.Duration:   // 지속시간 타입의 아이템이면
                    // 아이템 효과 적용하는 코루틴 시작
                    StartCoroutine(condition.ScaleChange(selectedItem.item.consumables[i].value, useButton));
                    break;
            }
        }
        RemoveSelctedItem();    // 사용하면 인벤토리에서 삭제
    }
}

 

/* PlayerCondition.cs */
public IEnumerator ScaleChange(float duration, GameObject useButton)
{
    useButton.SetActive(false); // 사용 버튼 비활성화(효과 발동 중 재사용 방지)
    // 플레이어 크기와 카메라 위치 일시적으로 변경
    Vector3 originalScale = playerController.size.localScale;
    Vector3 originalPos = playerController.mainCamera.localPosition;
    playerController.mainCamera.transform.localPosition = new Vector3(originalPos.x, originalPos.y * 1.5f, originalPos.z);
    transform.localScale = originalScale * 2;
    StartCoroutine(size.DecreaseTime(duration));    // 지속 시간 적용하는 코루틴 시작
    yield return new WaitForSeconds(duration);


    // 지속 시간 종료되고 원상태로 복구
    transform.localScale = originalScale;
    playerController.mainCamera.transform.localPosition = new Vector3(originalPos.x, originalPos.y, originalPos.z);
    useButton.SetActive(true);
}

 

위와 같이 ScaleChange 코루틴에 시작할 때 사용 버튼을 비활성화하고 종료할 때 활성화하는 코드를 작성했다.

이렇게 작성하면 ScaleChange 코루틴이 시작되어도 사용 버튼이 비활성화 되지 않는다.

 

문제 해결:

/* UIInventory.cs */
public void OnUseButton()
{
    if(selectedItem.item.type == ItemType.Consumable)
    {
        for(int i = 0; i < selectedItem.item.consumables.Length; i++)
        {
            switch (selectedItem.item.consumables[i].type)
            {
                case ConsumableType.Health:
                    condition.Heal(selectedItem.item.consumables[i].value);
                    break;
                case ConsumableType.Duration:   // 지속시간 타입의 아이템이면
                    useButton.SetActive(false); // 사용 버튼 비활성화(효과 발동 중 재사용 방지)
                    // 아이템 효과 적용하는 코루틴 시작
                    StartCoroutine(condition.ScaleChange(selectedItem.item.consumables[i].value, useButton));
                    break;
            }
        }
        RemoveSelctedItem();    // 사용하면 인벤토리에서 삭제
    }
}

 

코루틴 시작 전 먼저 버튼을 비활성화하고 코루틴에서는 활성화만 하도록 만들어준다.

 

그런데 여기서 다른 문제 발생!

다른 아이템을 클릭했다가 다시 크기가 커지는 아이템을 클릭하면 이미 크기가 커졌음에도 버튼이 활성화된다.

 

문제 원인:

/* UIInventory.cs */
public void SelectItem(int index)
{
    // 아이템이 Consumable 타입이면 Usebutton 활성화
    useButton.SetActive(selectedItem.item.type == ItemType.Consumable);
    // 아이템이 Openable 타입이면 Openbutton 활성화
    openButton.SetActive(selectedItem.item.type == ItemType.Openable);
}

다른 아이템을 누르거나 크기가 커지는 아이템을 다시 누르면 다음 메소드가 호출된다.

플레이어가 커진 상태인지 확인하지 않고, 크기가 커지는 아이템이 Consumable이니까 사용 버튼을 활성화 해버린다.

 

문제 해결:

플레이어가 커진 상태인지 확인하는 변수를 추가하고 사용 시 이를 체크하게 하는 로직을 추가해야한다.

/* Player.cs */
public class Player : MonoBehaviour
{
    public bool isBig;  // 플레이어가 커진 상태인지 확인

    private void Awake()
    {
        isBig = false;
    }
}

 

/* UIInventory.cs */

public void OnUseButton()
{
    if(selectedItem.item.type == ItemType.Consumable)
    {
        for(int i = 0; i < selectedItem.item.consumables.Length; i++)
        {
            switch (selectedItem.item.consumables[i].type)
            {
                case ConsumableType.Health:
                    condition.Heal(selectedItem.item.consumables[i].value);
                    break;
                case ConsumableType.Duration:   // 지속시간 타입의 아이템이면
                    CharacterManager.Instance.Player.isBig = true;  // 플레이어 커진 상태로 설정
                    useButton.SetActive(false); // 사용 버튼 비활성화(효과 발동 중 재사용 방지)
                    // 아이템 효과 적용하는 코루틴 시작
                    StartCoroutine(condition.ScaleChange(selectedItem.item.consumables[i].value, useButton));
                    break;
            }
        }
        RemoveSelctedItem();    // 사용하면 인벤토리에서 삭제
    }
}
public void SelectItem(int index)
{
    // 아이템이 Openable 타입이면 Openbutton 활성화
    openButton.SetActive(selectedItem.item.type == ItemType.Openable);
    // 아이템이 지속시간이 있고 플레이어가 커진 상태라면 UseButton 비활성화
    if (selectedItem.item.hasDuration && CharacterManager.Instance.Player.isBig)
        useButton.SetActive(false);
    else
        useButton.SetActive(selectedItem.item.type == ItemType.Consumable);
}
/* PlayerCondition.cs */
public IEnumerator ScaleChange(float duration, GameObject useButton)
{
	//...
    CharacterManager.Instance.Player.isBig = false;
    useButton.SetActive(true);
}

스크립트를 위와 같이 변경하여 아이템 효과가 이미 적용 중일 때는 사용하지 못하도록 제한한다.