유니티에서 애플 TV 리모컨 버튼 입력 받아오기.







유니티 에서 애플티비 리모컨 입력을 받으려면 버튼값은 위와 같다.





선택 버튼 : joystick button 14

MENU 버튼 : joystick button 0

Pause 버튼 : joystick button 15


선택 버튼은 공식 이름이 무슨버튼인지 모르겠다.


유니티에서 InputManager에 해당 버튼들을 등록 해주면 된다.




Edit -> Project Settings -> Input에서 InputManager를 열어주자.










그리고 위와같이 버튼을 입력 해준다.






코드에서는 위와 같이 키보드 입력 받는것과 동일하게 입력을 받으면 된다.






그 왜에...리모컨의 터치 영역에서 드래그 입력을 받는건 다음과 같이 코루틴에서 구현했다.

참고로 UI에서 버튼의 포커스를 이동할 때 사용하는 부분이다.



    IEnumerator DPadAxisInputDelayCoroutine(){

        Debug.Log("DPadAxisInputDelayCoroutine Started");

        float lastX = 0;
        float lastY = 0;
        
        while(true){

            float x = Input.GetAxis("Horizontal");
            float y = Input.GetAxis("Vertical");

//            Debug.Log(string.Format("x = {0}, y = {1}", x, y));

            if(x == -1){
                ButtonLeft();
                lastX = x;
                break;
            }
            else if(x == 1){
                ButtonRight();
                lastX = x;
                break;
            }

            if(y == -1){
                ButtonDown();
                lastY = y;
                break;
            }
            else if(y == 1){
                ButtonUp();
                lastY = y;
                break;
            }
                
            yield return null;
        }

        float accumTime = 0;
        float max = 0.3f;
        float min = 0.1f;
        float maxTime = max;

        while(true){

            float x = Input.GetAxis("Horizontal");
            float y = Input.GetAxis("Vertical");
            //            Debug.Log(x);
            accumTime += Time.deltaTime;

            Debug.Log(string.Format("x = {0}, y = {1}", x, y));
            Debug.Log(string.Format("accumTime = {0}", accumTime));

            if(accumTime >= maxTime){

                Debug.Log(0);
                if(x == -1){
                    ButtonLeft();
                    maxTime = min;
                }
                else if(x == 1){
                    ButtonRight();
                    maxTime = min;
                }

                if(y == -1){
                    ButtonDown();
                    maxTime = min;
                }
                else if(y == 1){
                    ButtonUp();
                    maxTime = min;
                }

                if(x == 0 && y == 0){
                    break;
                }

                accumTime = 0;
            }
            else{
                if(x == 0 && y == 0){
                    Debug.Log(1);
                    break;
                }
                if(lastX != 0 && lastX == x * -1){
                    
                    Debug.Log(2);

                    if(x == -1){
                        ButtonLeft();
                        maxTime = max;
                        lastX = x;
                    }
                    else if(x == 1){
                        ButtonRight();
                        maxTime = max;
                        lastX = x;
                    }
                    accumTime = 0;
                }
                if(lastY != 0 && lastY == y * -1){
                    Debug.Log(3);
                    if(y == -1){
                        ButtonDown();
                        maxTime = max;
                        lastY = y;
                    }
                    else if(y == 1){
                        ButtonUp();
                        maxTime = max;
                        lastY = y;
                    }
                    accumTime = 0;
                }
            }

            yield return null;

        }


        System.Func<IEnumerator> func = DPadAxisInputDelayCoroutine;
        StartCoroutine(func.Method.Name);
        yield break;
    }




Input.GetAxis("Horizontal") 에서 x축 값을...

Input.GetAxis("Vertical") 에서 y축 값을 받아온다.


터치 영영에서 터치 입력을 받고 싶다면


                Touch[]    touches =    Input.touches;

                if(touches.Length > 0){
                        keyInput = true;
                }



위처럼 터치의 갯수를 받아서 1개 이상이면 터치가 일어난거로 보면 된다.




참고로 유니티에서 읽어들이는 리모컨의 컨트롤러 이름은


 [basic,wireless] joystick 1 by Remote



이거다.



만약에 입력장치가 여러개가 된다면 이거로 구분할 수 있을듯....


아니면 말고.






유니티 무한루프 돌 때 디버깅 방법.

개발에는 항상 예상치 못한 버그가 따르기 마련이다. 유니티 개발도 마찬가지인데, 유니티의 경우는 디버깅이 참 어렵다는 패널티 또한 가지고 있다. 보통의 버그나 에러같은 경우 Debug.Log() 를 이용해서 (사실 이마저도 노가다다) 일일히 유니티 콘솔에 로그를 찍는 방식으로 디버깅을 하는데, 만약 에러가 코드의 특정 로직에서 무한루프를 도는 경우라면 유니티 자체가 정지해버려서 콘솔조차 확인할 수 없는 경우가 발생을 한다.


보통은 본인이 어디를 수정했는지 잘 알고 있어서 문제가 되는 부분을 금방 찾을 수 있는데, 자신이 어딜 수정했는지 금방 까먹는 나와 같은 경우라면 이경우 엄청난 멘붕이 찾아오기 마련이다.(사실 이 문제 해결하느라 하루를 버렸다)


그렇다면 이렇게 유니티가 무한루프를 도는 경우 디버깅을 어떻게 해야 할까?


뭔가 합리적인 방법이 있으면 참 좋겠지만, 원래 유니티에서 디버그가 노가다를 요구 하는것 처럼 무한루프를 도는 곳을 찾는 방법 역시 노가다를 좀 해야한다.


어떤 방법이냐 하면, 바로 씬에 올려져 있는 계증화된 GameObject들을 하나씩 비 활성화 하면서 문제가 있는 콤포넌트를 순차적으로 찾아가는 방법이다.


아래의 그림을 보면 쉽게 이해가 갈것이다.



문제가 있는 녀석을 찾기 위해 UI Root(2D) 와 UIRoot(3D)중 하나를 비활성화해본다.

UI Root(3D)를 비 활성화 시켰는데 게임이 무한루프를 돌지 않는다.

그렇다면 이 녀석들 중에서 어떤 한 GameObject가 들고있는 콤포넌트에 문제가 있는 것이다.


계속해서 그 아래있는 자식 GameObject중에 하나를 비활성화 시킨다.

만일 실행이 안되고 무한루프가 생기면 유니티를 강제 종료하고 다시 실행하는건 센스.

내경우는 실행이 잘 되었다.


역시 실행이 잘 되면 자식중에 하나를 선택해서 위와 같은 방법으로 반복을 한다.


계속 찾아본다.


왠지 마지막으로 의심되는 _HurdleController 를 마지막으로 비활성화 시키고 실행했더니

무한루프를 돌지 않는다.

문제는 _HurdleController의 특정 콤포넌트가 일으키는 것이다.


다행히도 이녀석은 하나의 다행히도 콤포넌트를 가지고 있어서

HurdleController 라는 녀석의 특정 로직에 문제가 있는 것임을 알 수 있었다.

만일 여러개의 콤포넌트를 가지고 있는 GameObject라면 각 콤포넌트를 비활성화 하는 방식으로 문제가 되는 녀석을 찾아가면 된다.


잡았다 요놈!!!

개발과정에서 임시로 주석처리한 녀석때문에 무한루프를 돌았던것!!




다소 노가다성과 삽질성이 짙은 디버깅 방법이긴 하지만, 무한루프 때문에 디버깅을 할 수 없는경우 유용하게 활용 할 수 있는 방법이기에 초!! 오랜만에 글을 남겨본다.


누군가 도움이 되었음 좋겠다.





사진과 추억

 고등학교때 수학여행이나 기타 다른 활동을 하게 되면 종종 아버지의 카메라를 빌려서 들고 갔었다. 그리고 그런 활동들이 끝나고 나면 사진을 전지에 붙여서 원하는 사진 아래다 번호를 적으면 현상을 해주겠다고 했던적이 있었다. 누구나 자기 얼굴이있는 사진 한장정도는 추억이라는 이름으로 남겨놓고 간직하고 싶어하지 않을까 하는 생각에서 했던 일이었다. 뭐, 얼마나 많이 신청을 해줄까 속으로 생각했는데, 생각보다 많은 친구들이 사진을 현상하겠다고 해서 놀랐던 기억이 있다. 특히 잘 나온 사진이든 잘 못나온 사진이든 자신이 나온 사진 대부분을 신청했던것으로 기억한다.

100여장이 넘는 사진을 찾아 번호별로 정리해서 전지에 붙이고, 신청한 사진을 학번별로, 사진별로 정리하고, 다시 인화를 맡기고 또 찾으러 가야했기 때문에 이 작업은 생각보다 손이 많이 가는 작업이었고, 대략 처음의 사진인화부터 시작해서 마지막 친구들의 손에 사진이 돌아가기 까지는 한달 정도의 시간이 걸렸던것 같다.

  당시 사진관 인화료는 당장 50원~100원 사이였는데, 나는 사진별 장수를 정리하고 인화를 부탁하고 찾아오는 약간의 수고를 감안해서 100원인가 150원인가에 사진을 찾아줬었다. 뭔가 금전적인걸 바란건 아니었지만, 작업을 끝마치고서 만원이 살짝 넘는 금액이 내 손에 들어오게 되니 묘한 느낌이 들었다. 살짝 '노동의 댓가가 이런건가?' 하는 생각도 들었다.

 10여년의 시간이 지난 지금, 나는 아버지의 카메라를 빌리지 않고 나의 카메라를 가지게 되었고, 언제든 사진을 찍을 수 있게 되었다. 그런데 요즘 사진을 찍다보면 사람들이 예전만큼 사진에 대한 소중함을 보이지 않고 있다는걸 종종 느끼게 된다. 그리고 가끔 '자신을 이상하게 찍어놓는다.' 며 이렇게 찍으려먼 차라리 자신은 사진을 찍지 말라는 라는 말을 들을때면 조금 섭섭한 생각도 든다. 나라고 예쁘게 찍고주고 싶지 않을까...

 내 초등학교 졸업앨범을 뒤져보면 나의 사진은 아주 가관이다. 졸업앨범을 촬영하는 날 바깥은 매우 밝았고, 햇빛에 눈부심이 유난히 심했던 나는 이렇게 밝은날, 심지어는 태양을 눈앞에 두고 사진 촬영을 할 때 도저히 눈을 찡그리지 않을 수 없었다. 그래서 졸업 앨범을 촬영할때, 눈물이 나올 정도로 눈을 부릅떠봤지만, 안타깝게도 사진기사 아저씨의 셔터는 나의 눈이 한계를 넘어 도저히 눈꺼풀을 닫지 않을 수 없을 때 내려졌고, 그 사진은 내가 찡그린 그대로 찍혀 졸업앨범에 고스라니 박혀있다. 그리고 아래에는 무려 '따사로운 햇살이 비출때 우린 행복해' 라는 말도 쓰여져 있다. 내 표정은 전혀 행복하지 않은데 말이다. 하필이면 왜 이렇게 나왔을까 싫기도 했는데, 반대로 어쨋든 웃기게 나왔으니 재미있구나 하고 넘어갔었다. 지금 이렇게 회자할 수 있는것도 웃기게 나왔으니 가능한 것이다.

 결론만 본다면 기술이 발달하면서 이렇게 사진의 소중함이 조금 퇴색된건 아닐까 하는 생각이 든다. 요즘은 사진을 찍고 인터넷의 어딘가에 올려놓기만 하면 사진을 복사해서 자신의 하드디스크에 보관할 수 있게 되었다. 예전처럼 사진을 소유하기 위해, 사진관에 인화를 맡기고 기다렸다가 다시 찾으러가는 노력따윈 필요하지 않게된 것이다. 손가락만 몇번 까닥하면 사진은 나의 소유가 되니 이처럼 편한 세상이 또 어디에 있을까? 물론, 지금도 디지털 사진을 인화하려면 사진을 맡기고 기다려야 한다는건 변함이 없긴 하지만 데이터 덩어리로 되어있는 사진파일도 소유의 개념으로 본다면 다름이 없다는 말이다.

 사진촬영 자체를 싫어하는 사람을 부정하려 하는게 아니다. 그냥 예전만큼 사진에 대한 소중함이 사람들에게서 조금 덜 느껴지지 않는게 아쉽다는 것이다. 사람 마음이야 본인이 예쁘게 나온 사진만 남길 바라는게 매한가지겠지만, 조금 덜 예쁘게 나온 사진이든, 예쁘게 나온 사진이든, 시간이 지나면 모두 추억으로 남는다는건 변함이 없다. 그리고 이런 사진들 또한 추억으로 남길 수 있도록 시간은 사람을 관대하게 만들어준다.

 예쁘게 나온 사진에만 집착하지 말자. 시간이 지나면 모두 당신의 뉴런에 강한 자극을 줄 소중한 추억이다.