안 쓰던 블로그
Transform[] 의 Destroy 및 GetComponentsInChildren의 오브젝트 누적 문제와 해결 (초기화 에러) 본문
Transform[] 의 Destroy 및 GetComponentsInChildren의 오브젝트 누적 문제와 해결 (초기화 에러)
proqk 2021. 8. 3. 22:28원하는 것:
한 번의 게임 라운드가 끝나면, 사용했던 Transform[] 의 게임 오브젝트를 전체 Destroy 한다.
다음 라운드에서 Instantiate로 오브젝트를 생성한다.
생성한 오브젝트들의 Transform[]을 만들어서 행동을 한다.
문제와 실패:
한 번의 게임 라운드가 끝나면, 사용했던 Transform[] 의 게임 오브젝트를 전체 Destroy 한다 -> Hierachy에서 완벽하게 이루어짐을 확인
다음 라운드에서 Instantiate로 생성한다 -> 생성 완료
생성한 오브젝트들의 Transform[]을 만들어서 행동을 한다 -> 문제 발생
외관상 Destroy가 잘 이루어졌는데, 이전 라운드에서 사용한 Transform[]과 다음 라운드에서 Instantiate로 새로 생성된 오브젝트의 Transform[]이 누적되는 현상 발생
즉, Destory가 내부적으로 완벽하게 이루어지지 않은 듯 하다
이 그림에서 3, 3, 3, 3, 버, 스
가 나와야 정상인데
이전 단어인 '배'가 들어있어서 Length는 '배'의 글자수인 1만큼 증가한 상태이다 (3, 4, 4, 4)
또한 transform배열에도 '배'가 들어가서 그 후에 '버스'라는 것은 초기값인 '기'로만 들어가고 갱신이 되지 않은 모습이다 (그 상태로 for문은 버, 스 총 2번 돌아서 초기값인 '기'가 2번 들어갔다. 최종 출력 배, 기, 기)
Destroy문제인지를 먼저 살펴보았다
'버', '스'에 대한 각각 2개씩+부모가 잘 있다
Destroy가 잘 이루어진다고 볼 수 있다
그럼 대체 어디에 저 값은 누적되고 있는 건가??
Destroy 코드는 아래와 같다
for (int i = 1; i <= difficulty; i++) //본인 제외
{
GameObject.Destroy(answerBoxs[i].gameObject);
GameObject.Destroy(answerTexts[i].gameObject);
if (i <= problemText.Length) //문제 길이까지만
{
GameObject.Destroy(probBoxs[i].gameObject);
GameObject.Destroy(problemTexts[i].gameObject);
}
}
(difficulty의 문제는 아니다)
부모인 0번을 제외한 자식들을 삭제한다
아주 간단한 코드다.. 문제가 없어 보인다
이전 라운드의 값이 어디에 누적되고 있는지를 확인해야 한다
Debug.Log(answerTexts.Length);
Transform[] tmp = answerAllBox_text.GetComponentsInChildren<Transform>();
answerTexts = tmp;
Debug.Log(answerTexts.Length);
임시 배열을 생성한 뒤, 자식을 받아온다
그리고 이 임시 배열을 원본 배열에 할당한다
이 코드의 위, 아래에 Length를 출력하였다
1. 배열 초기화의 문제라면, 이번엔 새로 생성한 tmp 배열에 할당받고 넘겼으므로 해결될 것이다
2. 애초에 GetComponentsInChildren의 문제라면, tmp 배열에 할당받을 때부터 잘못된 배열이 올 것이다
결과는.. 2번이었다
answerAllBox_text는 UI Layout Group_ans_text라는 부모 오브젝트에서 자식을 받아온 Transform 배열이다
초기화나 Destroy와 관련없이 애초에 부모에서 받을 때부터 누적된(잘못된) 값이라는 결론을 낼 수 있다
그런데, 실제 Hierachy에서는 누적은 커녕 Destroy 후 생성까지 완벽하게(?) 이루어지고 있다
왜 그런지 이유를 찾고 싶었지만 검색해 봐도 알 수 없었다 ㅜㅜ
일단 의문점으로 놔 두기로 했다
해결 방법:
부모에 값이 누적되는 것이 문제라면, 부모까지 삭제하고 부모도 Instantiate로 생성해 버리는 방법을 떠올렸다
for (int i = difficulty; i >=0; i--) //본인 포함
{
GameObject.Destroy(answerBoxs[i].gameObject);
GameObject.Destroy(answerTexts[i].gameObject);
}
for (int i = problemText.Length; i >= 0; i--)
{
GameObject.Destroy(probBoxs[i].gameObject);
GameObject.Destroy(problemTexts[i].gameObject);
}
Destroy 코드를 수정하여 본인(부모)을 포함한 모든 오브젝트를 삭제한다
GameObject questionAllBox_img = Instantiate(prob_img) as GameObject;
questionAllBox_img.transform.SetParent(canvas.transform);
this.ChangeSize(questionAllBox_img, 0, 0, 0, 0);
부모였던 4가지 오브젝트를 Prefab형태로 만들고, 라운드가 시작될 때 Instantiate로 생성한다.
부모를 Canvas 오브젝트로 지정하였다
그리고 이후 '버', '스'같은 음절 오브젝트가 생성되면, 이 클론 부모에다가 자식으로 붙인다
문제 없이 잘 실행되는 모습!!
바로 이전 글(https://foxtrotin.tistory.com/510)에서 삽질한 만큼을 또 삽질했고, 다행히 해결은 했다
원인은 모른다는 점이 좀 걸리지만 ㅎㅎ.. 알게 된다면 나중에 추가로 글을 작성하겠다
'유니티 > 개발' 카테고리의 다른 글
[유니티] Prefab의 역할에 대한 생각 (0) | 2021.08.04 |
---|---|
Prefab으로 생성한 Button 오브젝트를 클릭할 때마다 효과음 재생하기 (0) | 2021.08.04 |
[유니티] 에러 MissingReferenceException: The object of type 'RectTransform' has been destroyed but you are still trying to access it. (0) | 2021.08.03 |
Button Prefab에 Onclick() 추가하기!!!! (1) | 2021.08.03 |
GridLayoutGroup에 소속된 오브젝트의 position 가져오기 (0) | 2021.08.01 |