• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

슈팅게임만들기2의 마지막강의에서 오류가 발행하는 이유를 잘 모르겠습니다.

21.01.18 21:13 작성 조회수 267

0

좋은 강의 열심히 잘 듣고 있습니다!!

저렇게 Start 함수 안에 내용이 있으면 오류가 발생한다고 하셨는데

만약 현재 "ChrSelect" Prefefs에 저장된 값이 1이라고 한다면

Start함수에 의해 위치가 이동됨 -> itemDistance 값이 처음에 0으로 출력되는 프레임 존재함 -> Update에 의해 순간적으로 contentRect.anchoredPosition이 0으로 이동됨 -> 긴 시간 0이 출력되어 완전히 이동되었다면 minItemNum이 0으로 바뀌면서 menuSelect값도 0으로 바뀌겠지만 다시 itemDistance가 900으로 바뀌면서 정상 위치로 돌아가고 minItemNUM은 그대로 유지됨

지금 제가 이해하고 있는게 맞는지 궁금합니다

그리고 MenuManagerScript가 먼저 실행되도록 설정했는데도 itemDistance가 처음에 0으로 출력되는 이유도 궁금합니다

답변 4

·

답변을 작성해보세요.

1

하나 더 추가하자면 contentRect 를 Start 에서 바꾸지 않아도 아이템의 anchoredPosition 이 0이 나오는 현상이 있는데 사실 이건 유니티의 오류라고 봐도 무방합니다. 잘못된 값이 나와서 막은 것입니다. 나중에 유니티가 업데이트가 되면 어떻게 될지 모르겠습니다만 유니티에서도 죽지는 않으니 그냥 넘어가지 않을까 싶습니다. 

1

사실 그냥 잠시후면 이상없이 동작하기에 그냥 넘어가도 될 문제이기도 합니다. 약간 깜박거리는 것 뿐이니까요. ㅎ

1

안녕하세요. 

슈팅게임만들기 2(캐릭터로딩 및 메인메뉴 스크롤) 에서 오류를 수정하는 코드 말하시는 것 맞다고 생각하고 답변드리겠습니다.

사실 이것은 유니티의 오류라고 생각해도 무리가 없습니다. 

말하신 내용을 우선 적어두고 말씀드리겠습니다.

1 Start함수에 의해 위치가 이동됨 (맞습니다. 이때 minItemNum 이 1이므로 contentRect.anchoredPosition 이 -900이 되어 잘 이동됩니다. 

2. itemDistance 값이 처음에 0으로 출력되는 프레임 존재함(맞습니다. 이게 첫프레임입니다. 첫프레임에서 1번의 스타트 다음에 바로 업데이트가 실행될때 itemDistance 가 0으로 나옵니다. 이것의 이유는 거의 유니티의 오류라고 봐도 될것 같습니다. 아직 UI의 길이정보가 로드되지 않은 상황으로 보이고 item[1] 과 item[0]의 RectTransform 의 anchoredPosition 이 변수로 들어오지 않았습니다. anchoredPostion 이 들어오지 않았으므로 itemDistance 가 0으로 나옵니다.

3. Update에 의해 순간적으로 contentRect.anchoredPosition이 0으로 이동됨 -> 긴 시간 0이 출력되어 완전히 이동되었다면 minItemNum이 0으로 바뀌면서 menuSelect값도 0으로 바뀌겠지만 (이상태가 업데이트가 실행되어도 어느정도 유지됩니다. 강의를 찍은지 좀 시간이 되어서 한 프레임인지 여러프레임인지는 기억나지 않습니다만 이 말씀도 맞습니다.)

4. 다시 itemDistance가 900으로 바뀌면서 정상 위치로 돌아가고 minItemNUM은 그대로 유지됨 (맞습니다. 나중에 item[1] 과 item[0]의 RectTransform 의 anchoredPosition 의 값이 정상적으로 나옵니다. 그때 조금 깜박거리면서 UI 가 변경됩니다.)

현재 변경한 구조를 보시면 item[1] 과 item[0]의 RectTransform 의 anchoredPosition 의 값이 나오지 않을 경우 실행을 하지 않고 대기하다가 값이 정상적으로 나왔을때 Update 가 실행되도록 수정하였기에 0으로 갔다가 다시 900으로 돌아오는 경우가 생기지 않으므로 깜박이지 않는 것입니다.

업데이트 구조를 한번 말씀드리겠습니다.

void Update(){

   //1번 : item[1] 과 item[0]의 RectTransform 의 anchoredPosition 의 값을 읽어와서 0일 경우는 실행하지 않음. 리턴을 해버리므로 아래의 2번 로직 자체가 실행되지 않음

    float itemPos1 = item[1].GetComponent<RectTransform>()......

    ....

   if(itemDistance == 0){

      return;

   }

   // 2번 - 1번이 잘 실행되어 두 아이템의 anchoredPosition  값이 읽어들어와진 경우 2번 로직이 실행됨

   if(firstStart== true){

      ... 초기화로직

     firstStrat = false;

   }

   // 3번 기존 로직

     for(.......

}

설명입니다.

업데이트 구조를 보시면 다음과 같습니다.

Update 가 여러번 실행되면서 1번이 계속 실행되다가 오류가 있을 경우는 2번으로 넘어가지 못합니다. 나중에 2번이 잘 실행될때는 1번이 잘실행되고 2번이 실행되는 경우입니다. 그리고 2번을 실행할때 firstStart 플래그를 true 일때 실행하고 실행이 끝나면 firstStart 를 false로 만듭니다. (한번만 실행 해주기 위해서입니다.) 그리고 현재 업데이트에서 3번 로직이 실행됩니다. 

다음프레임에서 업데이트가 잘 실행되는 경우는 1번이 실행되고 3번이 실행됩니다. firstStart 라는 것을 안넣고 테스트 해보면 어떻게 될지 모르겠습니다. 그냥 이걸 넣은 이유는 초기화하는 로직이라고 생각해서 방어로직으로 넣고 잘 실행되기에 놔둔 것입니다. 

나중에 뒤쪽로직에서 보면 드래그를 하다가 select 의 값이 달라질 경우 menuSelect 를 다시 불러오는 부분이 있습니다. update 안에 있기에 menuSelect 안에서 계속 로드를 해버리면 프리퍼런스에서 계속 로드가 될거 같아서 이렇게 작성한 면도 있습니다. 

이정도 오면 사실 어렵긴 합니다. 이리저리 테스트를 해보다가 현재 로직이 괜찮다고 생각해서 작성하고 설명한 면이 있어서 최적화되거나 완벽한 코드라고 말하긴 어려울 것 같습니다. 프로그래밍이란 게 원래 계속 리팩토링을 하다보면 더 좋은 코드가 나오고 더 좋은 코드가 나오고 하는 것 같아서요. 나중에 다시 짜보면 어떻게 될지는 잘 모르겠습니다만 이것보다 좋은 코드가 나오기는 할 것 같습니다.

결론적으로 이렇게 작성한 이유는 스타트에서 contentRect 의 anchoredPosition 을 바꾸었을때 업데이트에서 바로 아이템들의 anchoredPosition 이 0으로 나오는 경우가 있기에 잠시후에 아이템의 anchoredPosition 이 정확한 값이 나올때 contentRect 의 anchoredPosition 을 변경하기 위해서 이렇게 작성한 것입니다.

유니티가 그렇게 동작하고 있어서 그걸 없애려고 업데이트에서 값이 잘 나올때 초기화로직을 그곳으로 넣은 것입니다. 왜 그런지가 궁금할텐데 설명하다보니 그 현상이 이유가 되어버렸네요. 죄송합니다.

기존 로직의 경우에는 스타트에서 contentRect 를 바꾸려고 했으므로 아이템들의 anchoredPosition 이 아직 나오지 않았는데 업데이트에서 UI 가 업데이트가 되는 모습이 보이는 것입니다. (이동하는 현상) 원래는 이렇게 해도 잘 동작할 것처럼 보이지만 내부적으로 유니티가 UI 업데이트에서 뭔가 더 잡아먹고 있는 것 같습니다. 그러므로 저희의 코드가 스타트에서 먼저 그것을 실행해버리면 죽진 않지만 깜박이는 오류가 나지 않나 예상하고 있습니다.

최대한 설명드리려고 노력했습니다만 설명이 조금 부족하다고 느끼기도 합니다.  UI 프로그래밍에서 이런 경우가 있으면 (잘 동작 하지 않는 경우)이러한 식으로 우회해서 적용하기도 합니다.

부족하지만 그래도 답변이 되었기를 바랍니다. 감사합니다. 

0

우엉앙님의 프로필

우엉앙

질문자

2021.01.19

자세한 답변 감사합니다!!

꽤 오랜 시간 고민했는데 일정 부분은 유니티의 오류라고 하니 다행이기도 하고 조금 허무하기도 하네요

선생님 덕분에 깔끔하게 이해한 것 같습니다

항상 좋은 강의 해 주셔서 감사합니다!