TIL - 오류 수정

빵어 ㅣ 2024. 1. 24. 20:12

음식 Trigger 관련 오류

플레이어가 가지고 있는 스크립트의 OnTriggerEnter에서 음식과 충돌했을 경우, 다 먹은 음식인지 아닌지 판별하는 코드가 있다.

손님이 음식을 다 먹었을 때 플레이어가 음식 Trigger안에 들어가 있을 경우, OnTriggerEnter가 호출되지 않아 다 먹은 음식인지 아닌지 판별하지 못해 다 먹은 음식 오브젝트를 치우지 못하는 현상이 있었다.

 

먼저 collider를 꺼줬다가 켜주면 플레이어가 음식 Trigger안에 들어와 있어도 OnTriggerEnter가 호출되니

손님이 음식을 먹기 시작하면 음식의 collider끄고, 음식을 다 먹으면 collider를 키도록 구현했다.

 

음식이 가지고 있는 스크립트인 CookedFood에 IsEating 변수를 생성했다.

public bool IsEating
{
    set { _collider.enabled = !value }
}

IsEating에 들어오는 값에 따라 _collider를 꺼주거나 켜주도록 만들었고

 

손님이 가지고 있는 스크립트인 CustomerController에서 지금 먹는 음식을 담는 _targetFood에

음식을 먹을땐 _targetFood.IsEating = true; 다 먹었을 땐 false 값을 넣어줬다.

 

그리고 실행했더니..

오류가 떴다.

음식 오브젝트에 Collider가 들어있지 않다는 오류다.

 

Awake에서 GetComponent로 collider를 받아오는데도 collider에 값이 들어있지 않다는거다..

아무리 생각해도 어디서 잘못됐는지 이해가 안돼서 튜터님을 찾아갔다.

 

결과적으로 CustomerController 스크립트의 이 부분이 문제였다.

손님이 요청하는 음식을 지정하는 SelectFood 함수의 일부 코드다.

        List<GameObject> foodPrefabs = _tycoonManager.CustomerTargetFoodPrefabs;

        int targetFoodNum = UnityEngine.Random.Range(0, foodPrefabs.Count);
        _targetFood = foodPrefabs[targetFoodNum].GetComponent<CookedFood>();

 

실제 생성되는 객체의 CookedFood를 가져오는 것이 아닌, Prefab의 CookedFood를 가져와서 사용하고 있었다.

그리고 CookedFood만 가져왔으므로 그 CookedFood스크립트가 붙어있는 게임 오브젝트도 존재하지 않았는데, 게임 오브젝트가 존재하는 것처럼 코드를 짜니 오류가 났던 거다.

 

 

해결

원래 하려던 방향인 CustomerController 스크립트의 TargetFood값을 이용해 해결하는 방향말고

음식을 놓을 수 있는 자리(오브젝트)마다 들어있는 FoodPlace스크립트와 음식에 들어있는 CookedFood 스크립트를 고치는 걸로 오류 수정 방향을 변경했다.


손님이 요청한 음식과 탁자에 놓여있는 음식의 종류가 같은지 매칭하는 함수가 FoodPlace 스크립트에 있다.

원래는 이 함수에서 음식이 매칭이 되면 손님이 갖고있는 스크립트(Customer Controller)에게는 이벤트로 알려주지만,

탁자에 놓여있는 음식이 갖고있는 스크립트(CookedFood)에는 알려주지 않았었다.

 

똑같이 이벤트를 구독하도록 변경했다.

 

CookedFood 스크립트에 지금 놓여있는 장소(FoodPlace)의 정보가 들어있는 변수가 있다.

이 변수가 null이 아닌 값으로 set 되면 해당 FoodPlace의 이벤트를 구독하도록 했다.

private FoodPlace _currentFoodPlace;
public FoodPlace CurrentFoodPlace
{
    get { return _currentFoodPlace; }
    set
    {
        if (value == null)
        {
            _currentFoodPlace.OnCustomerGetFood -= SetColliderEnable;
            _currentFoodPlace.CurrentFood = null;
            StopAllCoroutines();
        }
        else if(value.CurrentCustomer != null)
        {
            value.OnCustomerGetFood += SetColliderEnable;
        }
        _currentFoodPlace = value;
    }
}
...
 private void SetColliderEnable()
 {
     StartCoroutine(ColliderControl());
 }

 IEnumerator ColliderControl()
 {
     _collider.enabled = false;
     yield return new WaitForSeconds(10f);
     _collider.enabled = true;
 }

 

해결됐다 !