• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

MissingReferenceException 에러 문제입니다 ㅜㅜ

21.08.05 12:33 작성 조회수 5.75k

0

행성을 맞추면 아래와 같은 에러가 계속나네요. 지워졌는데, 그걸 다시 참조하려해서 그런다는 메시지것 같은데, 어디서 참조하려고 하는지를 모르겠습니다. 어떻게 해야 할까요? ㅜㅜ

MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.

Your script should either check if it is null or you should not destroy the object.

ObjectPoolManager+ObjectPool.Create () (at Assets/ObjectPoolManager.cs:24)

GameManager.Update () (at Assets/02_Scripts/GameManager.cs:68)

답변 4

·

답변을 작성해보세요.

0

 바쁘실텐데 정성껏 답을 해주셔서 진심으로 감사드립니다. 사실 선생님께 질문을 올린뒤 오류가 있지만 계속 진행을 했습니다. 그런데 어느 순간 골치 아팠던 오류가 사라졌고, 선생님이 지금 답변을 주셨습니다.

그래도 선생님이 답변을 주신데로 모두 수정을 했구요.. 계속진행하는 중에 다른 오류(NullReferenceException...) 가 나왔지만, 이건 일단 제가 더 고민을 해보고 정안되면 말씀을 드려야 할 것 같습니다. (올려두신 소스와 비교를 해보면서요)  ps. 물론 강의에서 조치하신 프로젝트 셋팅에서 스크립트의 실행 순서도 바꿨지만 오류가 계속되고 있습니다...

좋은 강의 감사하구요. 포기하지 않고 계속해 보겠습니다!!

비교해볼 소스를 최대한 빨리 올리도록 하겠습니다

제가 빼먹은게 있을수 있으니 한번 더 메일로 보내주실수 있으실까요?

수정을 했는데 말씀을 안드린 부분이 있지 않을까 싶습니다.

보내주시는 상태에서 디버깅을 하는 법을 텍스트로 올려드릴께요 

안녕하세요. 메일로 파일 두개 보내드렸습니다. 

아래 보시면 변수에는 위에서 말씀드린 [SerializedField] 가 있고요. 

클래스에는 [System.Serializable] 이 있습니다. 

자세히 보시면 ObjectFool 안의 list 변수에서 [SerializedField]  있고요. 

이 프로그램은 beyond compare 라는 프로그램인데 주신 코드하고 수정한 코드를 비교해보았습니다. 

이렇게 하고 나서 디버그를 하면 좀 더 쉽게 오류를 찾을수 있습니다. 

한줄씩 가기 안으로 들어가기, 계속 실행들을 해보면서 변수를 마우스로 호버해보면 변수의 값이 보입니다. 

제일 마지막의 한줄에서 실행해보면 죽는데요.

제일 마지막의 빨간 줄에서 죽는 첫번째 이유는 오브젝트풀에 asteroids 가 선언이 안되어 있어서 그렇습니다. 

그리고 prefabs 에 적의 항목들이 연결이 안되어서도 그렇고요. 

현재 Wave 가 있고 프리펩이 3개 있고 적들을 하나씩 Wave 에서 가져와서 프리펩에 적용합니다.

이 원리를 이해하고 코드를 짜고 있었다면 코드 타이핑이 의미가 없습니다. 

작업을 하면서 오타가 나는 것을 막을 수는 없습니다.

하지만 원리가 혹시라도 이해가 안되시고 오류처리가 안되시면 앞으로 돌아가셔서 가셔서 다시 공부를 하면서 다시 돌아와 보시기를 추천드립니다.

지금 상태에서 C# Part2 의 마지막 부분에 있는 리스트나 part2 의 초기 부분에 있는 객체지향 부분을 보시는 것도 추천드립니다. 디버깅도요.

많은 분들에게 공부하실때 말씀드리지만 처음부터 다시 보는 것이 그렇게 나쁘지만은 않습니다.

다시 보시면 안 보이던 것들이 보이실 겁니다.

코드는 첨부가 안되네요. 메일로 드리고 카페에 올려보겠습니다. 감사합니다.

아 그리고 beyond compare 라고 비교 툴이 있는데요. 

folder compare 로 놓고 폴더를 각각 드래그 해보시면 위의 내용처럼 보여집니다.

코드 최대한 빨리 올리겠습니다. 감사합니다.

0

우선 유니티의 인스펙터에서 디버그를 하는 방법입니다.

나중에 강의에서 말씀드릴텐데 [System.Serializable] 이라는 것이 있고 [SerializeField] 라는 것이 있습니다. 인스펙터에서 있는 내용을 유니티에서 볼수 있게 해주는 기능인데요. 

[System.Serializable]을 구조체나 클래스의 상단에 올립니다. (이 뜻은 다음 구조체나 클래스를 직렬화 가능한 구조체나 클래스로 만들겠다라는 뜻입니다.) 

그리고 변수에는 [SerializeField]를 올립니다.  (이 뜻은 이 변수를 유니티의 직렬화를 해서 에디터에서 보겠다는 뜻이고요)

둘다 해야 유니티에서 볼수 있습니다.

public class ObjectPoolManager : MonoBehaviour
{
    public static ObjectPoolManager instance;
    public GameObject PlayerShotPrefab;
    public GameObject asteroidPrefab;
    public List<GameObject> enemyPrefab;
    public GameObject coinPrefab;
    public GameObject shotEffectPrefab;

    [SerializeField]
    public ObjectPool playerShot;
    [SerializeField]
    public ObjectPool asteroid;
    [SerializeField]
    public List<ObjectPool> enemies;
    [SerializeField]
    public ObjectPool coin;
    [SerializeField]
    public ObjectPool shotEffect;

    [System.Serializable]
    public class ObjectPool {
        public List<GameObject> list;
        public GameObject prefab;
        public ObjectPool(GameObject prefab) {
            this.prefab = prefab;
            list = new List<GameObject>();
        }

위에 보시면 변수에는 [SerializeField] 가 있고요. ObjectPool 의 클래스에는 [System.Serializable] 이 있습니다. 이렇게 실행하면 실제 게임을 실행할때 풀 안의 내용들이 보여집니다.

여러개 샷을 발사하고 

잠시후에 보면 풀의 인스펙터에서 샷들이 올라온것을 볼 수 있고요.

계층뷰에서는 숨겨진 항목을 볼 수 있습니다.(PlayerShot 이 숨겨짐)

이런식으로 처음 실행될때는 PlayerShot 이 계층뷰에 나타나고 파괴될때는 계층뷰에서 숨겨진후에 pool 에 들어가는 것들을 확인해야 합니다. 

주의할 점이 앞의 것들이 완벽하게 진행되지 않은 상태에서 뒤로 들어가면 오류들이 복합적으로 동작하기 때문에 현재 상태에서 오류를 해결하고 다음으로 진행해야 한다는 것입니다. 

2. 두번째 디버깅 방법입니다.

이것만 가지고서도 오류를 잡기 쉽지 않습니다. 그래서 1번을 통해서 확인했을때 중간중간에 브레이크 포인트를 잡고 그것을 하나씩 실행해보면서 오류가 어디서 발생하는지를 확인해야 합니다. 예를 들어서 위의 답변에 보시면 태그가 Player로 되어 있는 오류를 찾기 위해서는 OnTriggerEnter 에서 실제로 태그가 들어오는지를 따라가 봐와 발견할 수 있는 확률이 높습니다.

아시겠지만 실행만 계속 해보는 상태에서는 이 오류를 발견하기가 대단히 어렵습니다. 

그래서 C# 기초 부분에 있는 디버깅을 하는 방법이 중요해지는 것입니다. 

혹시 이 상태의 디버깅을 하는 것을 알고 싶으시면 한번 보여드리겠습니다. 010-8627-5022 로 문자 주시면 약속 잡아서 줌으로 한번 보여드리도록 하겠습니다.  감사합니다.

0

안녕하세요. 코드 살펴보았는데 Pool 의 Create 와 Destroy 가 정확히 맞아야만 이게 동작하고 아닐경우 에러를 내보내고 종료되게 됩니다. 

사실 이걸 잡는 일이 정말로 쉽지 않은 일인데요. 

오타하나만 나도 오류가 생기거든요. 디버그에 대한 것은 그냥 넣지 않았는데

우선 조금 말씀드리겠습니다. 

우선 앞의 내용이 되지 않으면 뒤로 넘어가면 안됩니다. 

이 태그가 Player 가 아니라 PlayerShot 이 되어야 하고요. 

플레이어샷에서 제일 아래에 Destroy 가 있으면 안됩니다. 

그런데 이렇게 되면 해결 방법을 모르게 되니 결과만 알려드리는건 의미가 없고요. 

아래에서 디버그를 해서 볼수 있는 방법을 알려드리겠습니다.

 

0

안녕하세요. 

보통 오타가 나서 그럴것 같은데요.

코드가 없으므로 확인이 안될것 같으네요.

코드를 압축해서 보내주시면 확인해 보도록 하겠습니다. 

sun5022@naver.com 으로 보내주세요 

감사합니다.