페이지

2017년 3월 13일 월요일

[Unty3D]난수 발생기 상태 저장하기 / 불러오기

동기


최근 개발중인 프로젝트에서 확인되는 버그들 중에는 쉽게 재현하기 힘든 것들이 꽤 있다.
테스트중에 훅~ 하고 버그가 지나가는데 버그 발생 전, 어플리케이션 상태가 어땠는지 쉽게 확인이 힘들다.
그래서 어플리케이션 라이프사이클 동안 버그 발생 가능성이 높은 지점의 상태를 주기적으로 저장해서,
나중에 문제가 발생되면 해당 버그를 쉽게 재현할 수 있도록 하였다.
어플리케이션에 스냅샷을 남기고 다시 불러오는 기능을 추가한 것이다.

이를 위해서는 난수 발생기의 Seed값도 복원이 필요해서
Unity3D가 제공하는 Random클래스에 해당 기능이 있는지 확인을 해보게 되었다.

How to???


Unity5.3에서 5.4로 넘어갈 때 Random.seed가 사라지고,
대신해서 Random.state가 제공되고 있음을 확인 하였다.
https://docs.unity3d.com/ScriptReference/Random-state.html

단순히 시드값만을 복원하는 것이 아니고 난수 발생기 상태 자체를 저장하고 불러오면,
스냅샷을 저장하고 불러올 때, 보다 손쉽게 버그를 재현할 수 있을 것이다.
이를 위해서는 난수 발생기의 상태를 파일에 저장하고, 다시 불러올 수 있어야 한다.

하지만 유니티 공식 문서에 난수 상태를 파일에 저장하고 불러오는 방법에 대해서는 언급이 없다.
구글링을 좀 해보니 아래 유니티 커뮤니티 링크에서 단서가 될만한 내용을 얻을 수 있었다.
https://forum.unity3d.com/threads/saving-and-loading-random-state-unity-5-4.423109/

JsonUtility라고 이것도 Unity5.4부터 지원되기 시작한 기능인데,
특정 object의 public필드를 json형태로 추출하고, 이렇게 추출한 json을 가지고 데이터 복원도 가능해 보인다.
그래서 아래 소스 코드와 같이 JsonUtility와 MiniJson을 사용해서 난수 발생기 상태를 저장/복원해 보았다.

소스 코드


난수발생기 상태 json으로 저장하기
        // 현재 상태를 딕셔너리에 담기.
        Dictionary<string, object> snapShotInfo = SomeDictionaryFunction( true );

        // 난수 발생기 상태 딕셔너리에 담기.
        string randomJsonString = JsonUtility.ToJson( UnityEngine.Random.state );
        Dictionary<string, object> randomStateDictionary = 
            MiniJSON.Json.Deserialize( randomJsonString ) as Dictionary<string, object>;

        // 그 외에 필요한 정보 딕셔너리에 담기.
        snapShotInfo[ "random_state" ] = randomStateDictionary;

        // 딕셔너리 json으로 쓰기.
        string snapShotJson = MiniJSON.Json.Serialize( snapShotInfo );

        // 파일 쓰기 완료.
        System.IO.File.WriteAllText( finalFolderPath, snapShotJson );

json에 저장된 난수발생기 상태 불러오기
        string snapShotJson = System.IO.File.ReadAllText( snapShotPath );
        Dictionary<string, object> snapShotInfo = 
            MiniJSON.Json.Deserialize( snapShotJson ) as Dictionary<string, object>;

        // 난수 발생기 상태 복원.
        Dictionary<string, object> randomStateInfo = 
            snapShotInfo[ "random_state" ] as Dictionary<string, object>;
        string loadedRandomStateJson = MiniJSON.Json.Serialize( randomStateInfo );
        Random.state = JsonUtility.FromJson<Random.State>( loadedRandomStateJson );

결론


의도한 대로 난수 발생기 상태 복원은 잘 되는 것 같다.
하지만 아쉬운 점은 때로 난수 발생 횟수가 어플리케이션 분기 흐름에 따라 교묘히 바뀔때가 있어서
가끔씩 어플리케이션이 스냅샷을 뜬 이후의 움직임과 다르게 동작할 때가 있었다.
그래도 수차례 시도하면 만족할만한 확률로 스냅샷 뜬 이후의 움직임과 동일한 상태로 동작하는 어플리케이션을 확인할 수 있었다.

완벽한 스냅샷을 위해서는 난수 발생기 상태 저장 시점을 좀 더 고민해 봐야 할 것 같다.

2017년 3월 5일 일요일

1984년

8페이지
빅브라더는 당신을 감시하고 있다.

10페이지
윈스턴이 보고 있는 전면에는 당의 세 가지 슬로건이 멋진 글씨로 붙어 있었다.
전쟁은 평화, 자유는 예속, 무지는 힘

32페이지
알립니다. 알립니다. 우리 군대는 남인도에서 영광의 승리를 거두었습니다.
지금 전해 드리는 이 작전으로 전쟁의 종식은 머지 않았다고 합니다. 긴급 뉴스를 말씀드렸습니다.

'나쁜 뉴스가 나오겠군'

윈스턴은 생각했다. 아니나다를까, 유라시아 군대를 전멸했다는 자세한 소식과 함께 엄청난 사살자와 포로의 숫자를 늘어놓고 난 뒤,
다음 주부터 초콜릿 배급을 30그램에서 20그램으로 줄이겠다는 발표가 있었다.

42페이지 
과거를 지배하는 자는 미래를 지배한다. 현재를 지배하는 자는 과거를 지배한다.

75 ~ 76페이지
희망이 있다면 그건 반드시 노동자층뿐이다. 왜냐하면 오세아니아 인구의 85퍼센트를 차지하는
이 우글거리는 피압박 대중만이 당을 분쇄할 힘을 낼 수 있게 때문이다.

그들은 의식이 들기까지 반란을 일으키지 않을 것이다.
그러나 반란이 일어나기까지 그들은 의식을 가질 수 없을 것이다.

99페이지
쓸데없이 자잘한 것들만 잔뜩 기억할 뿐, 중요한 사건은 조금도 생각나지 않는다.
그들은 조그만 물건은 볼 수 있지만 커다란 것은 못 보는 개미와 같은 존재다.
그리하여 기억은 없어지고 기록된 자료마저 날조되면 인간의 생활조건이 개선되었다는
당의 주장은 검증해 볼 기준이 없어지고, 또 앞으로도 결코 있을 수 없기 때문에 사실로 인정되고야 말 것이다.

161페이지
어떤 점에서 그녀는 윈스턴보다 훨씬 예민하고 당의 선전에 넘어가지 않는 편이다.
한번은 그가 우연히 유라시아와의 전쟁에 관해서 말을 꺼내자 그녀는 자신이 보기에 전쟁은 현재 없다고 말해서 그를 놀라게 했다.
런던에 매일 떨어지는 로켓탄도 오세아니아 정부가 '국민들을 공포 속에서 헤어나지 못하도록' 폭팔 시키는 것이라 했다.

206페이지
늘 전쟁이 계속되고 있기 때문에 실은 전쟁이 없다는 말이 정확한 표현일 것이다.
신석기시대로부터 20세기 초에 이르기까지 전쟁이 인간에게 가한 압력이 사라지고 전혀 다른 것으로 대치되었다.
세 초국가가 서로 전쟁을 하는 대신 영구적인 평화에 동의하고 타국의 땅을 침범하지 않는다 하더라도 결과는 마찬가지일 것이다.
그럴 경우 외적 위험으로부터 오는 영향은 영원히 없어질망정 그 자체 내의 문제는 여전히 남아 있기 때문이다.
그러므로 진실로 영원한 평화는 영원한 전쟁과 똑같다.

208페이지
이런 세 집단의 목표는 결코 화해할 수 없는 것이다.
상층 계급의 목표는 현재의 상태를 유지하는 것이고, 중층 계급의 목표는 상층의 지위에 오르는 것이다.
하층 계급이 목표를 가졌다면( 이들은 너무 고생하기 때문에 일상생활 외에 다른 것을 거의 생각할 수 없는 것이 그들의 본성이다 )
그것은 모든 차별을 폐지하고 모든 인간이 평등한 사회를 건설하는 것이다.

270페이지
그 책이 내놓은 계획은 넌센스야.
비밀리에 지식을 축적하고 점차적으로 계몽되어 궁극적으로 노동자의 반란이 일어나 당이 전복된다는 계획 말야.
그게 무얼 말하려는지 자네도 예측했겠지만 넌센스야. 노동자는 결코, 몇천만년이 지나도 반란을 일으키지 않네. 할 수가 없지.
당의 지배는 영원해.

287페이지
이 모두가 얼마나 쉬운가! 항복하기만 하라. 그러면 다른 모든 것은 저절로 해결된다.