2014년 11월 7일 금요일

[Unity] Android에서 하드웨어버튼 (메뉴버튼,뒤로가기,홈) 대응 방법

요즘 모바일 프로젝트에서 Unity를 쓰시는분들이 많습니다.
하드웨어버튼, 특히 뒤로가기버튼에 상황에 적절한 행동을 수행하는지가 사용자경험 관점에서 상당히 영향을 미친다고 생각합니다.
하드웨어버튼 대응이 적절한지가 구글 피쳐드 검수기준이라는 말도 이미 알려져있는 상태이기도 합니다.
그래서 다들 Unity에서 하드웨어버튼에 대응하는 방법이 궁금하실텐데, 한국 웹에서는 정보를 찾기가 힘들어서 정리 포스팅 합니다.

void Update()
{
    if (Application.platform == RuntimePlatform.Android)
    {
        if (Input.GetKey(KeyCode.Home))
        {
            //home button
        }
        else if(Input.GetKey(KeyCode.Escape))
        {
            //back button
        }
        else if(Input.GetKey(KeyCode.Menu))
        {
            //menu button
        }
    }
}

간단합니다.

2014년 8월 18일 월요일

[Unity] Coroutine과 yield의 활용방법

Unity Programming에 있어서 Coroutine을 사용하는것은 가장 현실적인 성능 개선 방법입니다.
Unity특성상 Target Platform의 수가 많은만큼, Program의 성능이 높아져야하기때문에 Coroutine은 사실상 필수입니다.
코드의 가독성은 덤입니다.

Coroutine을 사용한 구현과 사용하지 않은 구현을 비교해보겠습니다.

// Coroutine 사용
IEnumerator Function(string a, string b, string c)
{
    yield return new WaitForSecond(2f); // 2초 대기
    Debug.Log(a);
    yield return new WaitForSecond(2f);
    Debug.Log(b);
    yield return new WaitForSecond(2f);
    Debug.Log(c);
}

void Start()
{
    StartCoroutine(Function("FirstAction","SecondAction","ThirdAction"));
}


// Coroutine 사용하지않음
string a;
string b;
string c;
bool isAFinished;
bool isBFinished;
bool isCFinished;
float  runningTime;

void Start()
{
    a = "FirstAction";
    b = "SecondAction";
    c = "ThirdAction";
    isAFinished = false;
    isBFinished = false;
    isCFinished = false;
    runningTime = 0f;
}

void Update()
{
    runningTime = runningTime + Time.deltaTime;
    if( runningTime > 2f && isAFinished == false)
    {
        Debug.Log(a);
        isAFinished = true;
    }

    if( runningTime > 2f+2f && isBFinished == false)
    {
        Debug.Log(b);
        isBFinished = true;
    }

    if( runningTime > 2f+2f+2f && isCFinished == false)
    {
        Debug.Log(c);
        isCFinished = true;
    }
}


같은 기능을 하는 코드입니다.
가장 먼저 느껴지는 차이점은 가독성입니다.
그 다음은 성능인데, Coroutine의 경우 심플합니다.
하지만 Coroutine을 사용하지 않은 경우는 세 문자열을 다 출력하는데 1080번의 if문을 실행합니다.
거기다 정상적으로 작동하고나서도 초당 180번의 if문을 실행하게됩니다.


코드를 더 줄일수있긴 합니다.
Start()를 선언할때 IEnumerator를 붙여주면 유니티에서 Coroutine으로 호출해줍니다.
IEnumerator Start()
{
    yield return new WaitForSecond(2f);
    Debug.Log("FirstAction");
    yield return new WaitForSecond(2f);
    Debug.Log("SecondAction");
}

Coroutine에서는 yield 키워드를 사용해서 기능을 사용하게 되는데, yield 관련 키워드는 다음과 같습니다.

yield return null
다음 Update까지 대기

yield return new WaitForSeconds(float)
지정된 시간만큼 대기

yield return new WaitForFixedUpdate()
다음 FixedUpdate까지 대기

yield return new WaitForEndOfFrame()
렌더링이 끝날 때까지 대기

yield return StartCoroutine(function)
StartCoroutine안에 넣은 코루틴이 끝날 때까지 대기

yield return WWW
WWW 작업이 끝날 때까지 대기

2014년 8월 13일 수요일

[Unity] Prefab을 이용한 Instance 동적으로 생성하기

Prefab은 GameObject를 Asset화 한 타입입니다. GameObject에 포함되어있는 컴포넌트와 그 안의 값들을 있는 그대로 저장할수있습니다.
한 GameObject를 여러 Scene에서 사용하거나, 한 Scene에서 여러번 생성해야할때 Prefab을 이용하면 좋습니다. 예를 들자면 총알같은 물체에 사용하기에 적합하겠네요.

GameObject prefab = Resources.Load ("Prefabs/Bullet") as GameObject;
// Resources/Prefabs/Bullet.prefab 로드
GameObject bullet = MonoBehaviour.Instantiate (prefab) as GameObject;
// 실제 인스턴스 생성. GameObject name의 기본값은 Bullet (clone)
bullet.name = "bullet"; // name을 변경
bullet.transform.parent = player.transform;
// bullet을 player에 입양하는등 초기화작업 수행

Prefab을 수정하면 Prefab으로 생성한 모든 GameObject를 수정할수있습니다. 나름 편리한 기능이라고 생각합니다.

2014년 8월 12일 화요일

[Unity] Awake, Start, Update, LateUpdate, FixedUpdate의 일반적인 사용법

사실 이 함수들은 Unity Script Reference에 잘 설명되어있어서 설명은 링크로 대체합니다.

코딩하면서 알아야하는 위 함수의 차이점은. Awake는 생성자고, Start는 생성자가 아니라는것입니다. Editor상에서 스크립트에 체크가 되어있지않아도 실제로는 인스턴스가 생성되기때문에 Awake는 생성시 한번 호출되지만, Start는 호출이 되지않고 첫 Update직전에만 호출됩니다. Start에 초기화구문을 넣었다면 초기화전에 객체를 사용하게되는 예외상황이 발생할 위험이 있지만, 초기화가 다른 객체에 의존해야할 경우에는 때때로 사용하는 경우도 있습니다.

Update함수는 매 프레임마다 호출됩니다. cocos2d에서는 deltatime을 인자로 전달해주는데, Unity에서는 Time.deltatime을 이용합니다. LateUpdate는 Update가 완료된이후 호출됩니다. 캐릭터의 위치나 애니메이션을 처리하는등 후연산이 필요할때 유용하게 쓰일수있습니다. FixedUpdate는 그렇게 자주 쓰이는 함수는 아닙니다. 물리연산시 이 함수 내에서 처리하는것을 권장하는데, 그 이유는 Update함수에 비해서 호출주기가 일정하기때문입니다. 호출주기는 초당50회로 알려져있습니다.