반응형

Unity로 안드로이드 앱을 개발하다보면 스크롤 안에 버튼이 들어갈 경우가 종종 있다.

PC에서 테스트 할 때는 마우스로 잘 눌리던 버튼이 스마트 폰에 넣어서 테스트 해보면 간혹 잘 눌리지 않는 경우가 있다. 이럴때 EventSystem 설정을 바꿔줘야하는데 다음과 같이 세팅 하면 적당하다.

 

private const float inchToCm = 2.54f; 	 
[SerializeField] private EventSystem eventSystem = null; 	 
[SerializeField] private float dragThresholdCM = 0.5f; //For drag Threshold 

private void SetDragThreshold() { 	
    if (eventSystem != null) 	{ 		
        eventSystem.pixelDragThreshold = (int)(dragThresholdCM * Screen.dpi / inchToCm); 	
    } 
}     

void Awake() { 	
    SetDragThreshold(); 
}

 

반응형
반응형

로컬저장을 하기 위해 찾아보다가 Asset Store에서 “Simple Save”라는 놈을 발견했다. 급할때 그냥 돈주고 사는게 정신건강에 좋다. 지금 테스트 중인데 나름 편리하게 잘 만들어진 것 같다. https://www.assetstore.unity3d.com/kr/#!/content/28799 내가 필요한 건 리스트 형태의 데이터를 저장해야하는데 여러가지 데이터 형태를 컴포넌트 형태로 저장해준다. 하지만 List는 지원되지 않고 ArrayList는 지원이 되더라는… 그래서 찾아보다 보니 hashtable과 arraylist를 사용해야겠다는 결론이 났다. 그럼 어떻게 변환하고 가져다 쓰는가…

//저장할때는 단순하게 요렇게 저장하고 
Hashtable ht = new Hashtable(); 
ht.Add("username", "bamsik"); 
ht.Add("point", 1); 
ht.Add("grak", 1); 
ht.Add("bbak", 2); 
ht.Add("date", 20151007); 
ht.Add("game", 1);   
_gameDataVO.Add(ht);   

//불러올때는 이렇게 불러오고 변환한다. 
string jsonstring = JsonMapper.ToJson(_gameDataVO); 
JsonData JD = JsonMapper.ToObject(jsonstring); 
반응형
반응형

리스트를 사용하다 보면 원하는 요소의 값대로 정렬하고자 할 때가 있다.
그럴 때 적당히 수정해서 사용하면된다.

void swap(int _i, int _j) 	{ 		
    ItemHandler tempItem =  MainList[_i]; 		
    MainList[_i] = MainList[_j]; 		
    MainList[_j] = tempItem; 	
}   	

IEnumerator sorting() 	{ 		
    yield return new WaitForSeconds (0.5f);  		
    // 승점 정렬 		
    for(int i = 0 ; i < MainList.Count; i++ ) { 			
        for(int j = i + 1 ; j < MainList.Count; j++) { 				
            if(MainList[i].Point < MainList[j].Point) { 					
                swap(i, j); 				
            } 				
            else if(MainList[i].Point == MainList[j].Point  				        
            && MainList[i].Gold < MainList[j].Gold) {	// 동률일 경우, gold,  					
                swap(i, j); 				
            } 				
            else if(MainList[i].Point == MainList[j].Point  				        
            && MainList[i].Gold == MainList[j].Gold  				        
            && MainList[i].Silver < MainList[j].Silver){ // 동률에 gold까지 같으면 silver. 					
                swap(i,j); 				
            } 				
            else if(MainList[i].Point == MainList[j].Point  				        
            && MainList[i].Gold == MainList[j].Gold  				        
            && MainList[i].Silver == MainList[j].Silver  				        
            && MainList[i].Bronze < MainList[j].Bronze){ // 동률에 gold, silver까지 같으면 bronze. 					
                swap(i,j); 				
            } 				
            else if(MainList[i].Point == MainList[j].Point  				        
            && MainList[i].Gold == MainList[j].Gold  				        
            && MainList[i].Silver == MainList[j].Silver  				        
            && MainList[i].Bronze == MainList[j].Bronze  				        
            && MainList[i].Garak < MainList[j].Garak){ // 동률에 gold, silver, bronze까지 같으면 garak. 					
                swap(i,j); 				
            } 				
            else if(MainList[i].Point == MainList[j].Point  				        
            && MainList[i].Gold == MainList[j].Gold  				        
            && MainList[i].Silver == MainList[j].Silver  				        
            && MainList[i].Bronze == MainList[j].Bronze  				        
            && MainList[i].Garak == MainList[j].Garak  				        
            && MainList[i].Bbak > MainList[j].Bbak){ // 동률에 gold, silver, bronze, garak까지 같으면 bbak. 					
                swap(i,j); 				
            } 			
        } 		
    }   		
    
    for(int t = 0 ; t < MainList.Count; t++ ) { 			
        MainList[t].gameObject.transform.SetSiblingIndex(t+1); 		
    }   	
}
반응형
반응형
출처 : http://www.wolfpack.pe.kr/123?category=2
1. Threading 사용하기
using UnityEngine; 
using System; 
using System.Threading;  

//쓰레드를 쓰겠다고 선언.  
public class ThreadOne : MonoBehaviour {      
    void Start(){         
        Debug.Log("카운트 0부터 49까지 세기!");         
        ThreadStart th = new ThreadStart(work); //1.work메소드를 위임.         
        Thread t = new Thread(th); //2.쓰레드생성.         
        t.Start(); //3.시작         
        Debug.Log("끝!");     
    }      
    
    public static void work(){         
        for (int i = 0; i<50; i++){             
            Debug.Log("Conut : " + i);         
        }     
    } 
} 
2. Threading 중지하기

쓰레드를 중지하기 위한방법은 2가지가 있음. Abort() : 강제 종료이며 어디에서 끝날지 모름. Join() : 쓰레드가 다 실행 될 때 까지 기다렸다가 종료.

using UnityEngine; 
using System; 
using System.Threading;  

public class ThreadOne : MonoBehaviour {      
    void Start(){         
        Debug.Log("카운트 0부터 1만까지 세기!");         
        ThreadStart th = new ThreadStart(work);         
        Thread t = new Thread(th);         
        t.Start(); //시작         
        t.Abort(); //강제종료         
        Debug.Log("끝!");     
    }      
    
    public static void work(){         
        for (int i = 0; i<10000; i++){             
            Debug.Log("Conut : " + i);         
        }     
    } 
} 

위 코드를 실행 시켰을 때 다음과 같은 출력을 보여준다.

 

Abort()로 종료 시키면 '0'까지 세고 끝이 날 때도 있고 '8'까지 세고 끝날 때도 있다.

 

반면 Join()으로 종료 시키면 다음과 같이 9999까지 출력 후 종료한다.

 

 

3.Threading 쉬게 하기

using UnityEngine; 
using System; 
using System.Threading;  

public class ThreadOne : MonoBehaviour {      
    void Start(){         
        Debug.Log("Start");         
        ThreadStart th = new ThreadStart(work);         
        Thread t = new Thread(th);         
        t.Start(); //시작         
        Debug.Log("end!");     
    }      
    
    public static void work(){         
        Thread.Sleep (100);         
        Debug.Log ("Sleep");     
    } 
} 

다시 살리는 명령어는 Thread.Resume()으로 하면 된다.

 

타원의 안은 상태 값, 화살표는 메소드를 나타낸다.

 
 
4.Multi Threading
using UnityEngine; 
using System.Collections; 
using System; 
using System.Threading;  

public class MultiThread : MonoBehaviour {          
    class Work{         
        int a;          
        
        public Work(int a){             
            a = a;         
        }          
        
        public void runit(){                          
            for(int i=0; i<10; i++){                 
                Debug.Log("Thread " + a + " Running : " + i);                 
                Thread.Sleep(100);             
            }         
        }
    }               
    
    void Start(){         
        Debug.Log ("start");         
        Work wk1 = new Work (1);         
        Work wk2 = new Work (2);         
        ThreadStart td1 = new ThreadStart (wk1.runit);         
        ThreadStart td2 = new ThreadStart (wk2.runit);         
        Thread t1 = new Thread (td1);         
        Thread t2 = new Thread (td2);         
        t1.Start ();         
        t2.Start ();      
    } 
} 

1번과 2번이 동시에 실행된다.

둘 중에 우선순위를 정하고자 할 때는 ThreadPriority 를 사용한다.

 
t1.Priority = ThreadPriority.Lowest; //1번 쓰레드 우선 순위 최하 
t2.Priority = ThreadPriority.Highest; //2번 쓰레드 우선 순위 최고 

 

멀티로 작업을 하다 보면 공통 변수로 작업해야 할 때가 있다. 이때 여러개의 쓰레드가 1개의 값을 건드리다 보면 값이 예상과 다르게 나올 수 가 있는데 이럴 땐 "lock"으로 묶어주거나 "Monitor.Enter()”와 "Monitor.Exit()”로 잡아줄 수 있다.

public void runit(){      	
    lock (this) { //또는 Monitor.Enter()        	
        for(int i=0; i<10; i++){       	
            Debug.Log("Thread " + a + " Running : " + i);            	
            Thread.Sleep(100);      	
        } 
    }//또는 Monitor.Exit(10); 
}  

 

반응형
반응형

 GameObject NotiBtn = new GameObject (); 
 NotiBtn.transform.SetParent(GameObject.Find ("Guest1/Home/Notification/NotiMask").transform); 
 NotiBtn.name = "NotiBtn---"; 
 NotiBtn.AddComponent (); 
 NotiBtn.GetComponent ().anchorMin = new Vector2 (0f,1f); 
 NotiBtn.GetComponent ().anchorMax = new Vector2 (0f,1f); 
 NotiBtn.GetComponent ().pivot = new Vector2 (0f,1f); 
 NotiBtn.transform.localPosition = new Vector3 (0f,0f,0f); 
 NotiBtn.AddComponent (); 
반응형
반응형

Sublime Text 2 는 확실히 가볍고 괜찮은 툴인듯하다.

유니티를 접한지 얼마 되지 않았지만 유니티에서 기본으로 제공하는 MonoDevelop은 상당히 무겁고 기능도 뭔가 불편하다는 느낌이다. 한글지원도 되지 않아 한글 타이핑이 되지 않는 현상도 있다.

계속 써오다가 오늘 구글링한 내용을 정리해 본다.

 

http://www.sublimetext.com/2

 

먼저 서브라임을 설치한 후, 

패키지 컨트롤 플러그인을 설치해야하는데 설치하는방법은 다음과같다.

 

https://packagecontrol.io/installation#st2

 

위 주소로 접속해서,

 

 

표기되어있는 부분의 스크립을 복사한다.

 

 

다시 서브라임으로 돌아와서 위 사진에 보이는 Show Console을 열어

복사해온 스크립을 붙여넣기 한 후 실행 시킨다.

 

 

 

그런 후 tools/Command Palette를 열어서

Package Control: Install Package 선택,

 

 

다음과 같은 화면이나오는데 검색창에 unity라고 치면

 

 

리스트가 나오는데 모두 설치해 주면 된다.

 

그리고 나서 유니티에 기본에디터인 Mono Develop 대신 Sublime으로 바꿔주도록 한다.

Unity / Preference / External Tools 에 있다.

 

 

 

이렇게 해주면 기존에 모노디벨롭으로 연결되던 게 Sublime으로 연결되어 열리게 된다.

 

- 서브라임에서 유니티 프로젝트를 관리 및 빌드를 수행하는 방법
 
- 콘솔 뷰 에러 메시지 더블 클릭의 연동 및 키워드 레퍼런스 페이지 연동
 
- 코멘트 토글 단축키 설정 ( 5번 참고 )
 
 

 

반응형
반응형

JsonData를 사용하기 위해서는 먼저 에셋폴더에 플러그인 폴더에 LitJson파일을 복사해 넣어줘야 한다.

 

 

아래와같이 해주면 사용할 수 있다.

using LitJson;      

//////////////////////////////////////
//// Resources.load 사용해서 불러올때. ////
//////////////////////////////////////

private JsonData JsonList;

IEnumerator Start () 
{
	TextAsset t = (TextAsset) Resources.Load("listData", typeof(TextAsset));
	JsonList = JsonMapper.ToObject( t ); // TextAsset사용시에는 .json 형태의 파일을 .txt확장명으로 바꿔줘야함.
	Debug.Log ("text data - " + t.text);

	yield return t;

	ProcessList(t.text);
}

private void ProcessList(string jsonString)
{
	JsonList = JsonMapper.ToObject(jsonString);
}

///////////////////////////
//// WWW 사용해서 불러올때. ////
///////////////////////////

//로컬파일 불러올때.
string url = "file:System OSX/Users/beom-seokjang/Documents/unity/24_MSC_Memento_prototype/Assets/Resources/listData.json";

//웹에 있는 파일 불러올때.
string url = "http://bamsiki.com/listData.json";

WWW www = new WWW(url);

//Load the data and yield (wait) till it's ready before we continue executing the rest of this method.

yield return www;    

if (www.error == null)
{
	//Sucessfully loaded the JSON string
	Debug.Log("Loaded following JSON string" + www.data);

	//Process books found in JSON file
	ProcessList(www.data);
}
else
{
	Debug.Log("ERROR: " + www.error);
}
반응형
반응형
출처: http://www.unitystudy.net/bbs/board.php?bo_table=writings&wr_id=43
 

 

코루틴(Coroutine)이 뭔가요?
 
C 언어등에서 일반적으로 사용하는 함수는 시작할 때 진입하는 지점이 하나 존재하고 함수가 모두 실행되거나, return 구문에 의해서 종료되는 지점을 설정할 수 있습니다. 이러한 함수를 서브루틴(Subroutine)이라 부르는데, 코루틴은 이를 더 일반화한 개념으로 진입하는 지점까지 여러 개를 가질 수 있는 함수를 의미합니다. 개념적으로만 본다면 서브루틴도 코루틴의 한 종류라고 볼 수 있겠지요.
 
코루틴이 왜 필요한가요?
 
코루틴이 없어도 게임을 만드는데 지장은 없습니다. 하지만 유니티에서 코루틴을 잘 활용하면 높은 성능을 내는 스크립팅의 제작이 가능해지고, 읽기 쉬운 코드를 만들 수 있게 됩니다.
 
코루틴은 어떻게 사용하나요?
 
C# 언어를 기준으로, 코루틴은 언제나 아래와 같은 구문을 통해서 선언되어야 합니다.
 
IEnumerator 함수이름 (인자)
 
IEnumorator 는 우리말로 열거자라고 하는데, 데이터의 목록을 하나씩 넘겨줄 때 사용되는 인터페이스입니다. 이 열거자와 코루틴이 무슨 관계이길래 이를 활용하는지 설명드리면, 코루틴은 호출한 함수와 서로 상호작용하면서 진행하도록 설계되어 있습니다. ( 어느 분께서는 협동루틴이라고 번역하셨는데, 정말 적절한 번역입니다! ) 아래 그림과 같이 코루틴은 자신을 호출한 함수에 데이터를 하나 넘겨주고 쉽니다. 받은 측에서는 데이터를 받고 나서 처리한 후에 코루틴에게 다음 데이터를 달라고 깨웁니다. 쉬고 있던 코루틴은 일어나서 다시 데이터를 전달하고.. 이를 계속 반복하는 구조로 동작합니다. 이러한 작업에 적절한 인터페이스가 IEnumerator 이며, C#에서 코루틴을 사용할 때는 이를 사용하여야 합니다.

 

 
일반적으로 호출한 함수에게 데이터를 전달할 때, return 구문을 사용하게 되면 데이터를 전달하고 함수는 종료됩니다. 코루틴은 이와 다르게 데이터를 전달한 후에 자신은 대기하고 있어야 하는데, 이를 위해 C#에서는 yield return이라는 키워드를 제공하고 있으며 이를 사용하면 됩니다. 
 
yield return ... ;
 
유니티에서 코루틴과 상호작용하는 주체는 엔진입니다. 코루틴을 사용할 때는 C#의 언어적인 기능을 익혀서 모든 것을 해결한다라는 개념보다 스크립트에서 엔진이 가지는 기능을 활용하는 또 한가지의 방법이라는 관점으로 생각해주시면 더 잘 이해되지 않을까.. 생각해봅니다.  
아래 그림과 같이 스크립트에서 StartCoroutine 함수를 통해 코루틴을 구동하면 코루틴은 첫 번째 데이터를 엔진에 전달하고 이 데이터를 분석한 엔진은 내부 루프를 돌면서 필요한 때가 되면 다음 데이터를 전달하도록 코루틴을 다시 호출해줍니다.

 

 
이 때 엔진에 전달할 데이터가 정말 중요한데, 데이터들은 코루틴이 유니티 엔진에게 보내는 일종의 명령으로 생각하시면 조금 더 이해가 쉽습니다.  
엔진에게 전달하는 명령들의 공통된 성격은 “나는 쉬고 있을 테니, 유니티 너가 내 명령을 보고 알아서 처리하고 끝나면 나를 깨워달라.” 입니다. ( 스크립트가 완전 갑이 됬습니다...  ) 
엔진이 제공하는 데이터들과 이들이 수행하는 명령들은 다음과 같습니다. 
( 참고로 아래 표 이외의 데이터들은 엔진이 처리하지 않습니다. )
 

코루틴용 데이터

엔진이 수행하는 기능

yield return null

다음 프레임까지 대기

yield return new WaitForSeconds(float)

지정된 초 만큼 대기

yield return new WaitForFixedUpdate()

다음 물리 프레임까지 대기

yield return new WaitForEndOfFrame()

모든 렌더링작업이 끝날 때까지 대기

yield return StartCoRoutine(string)

다른 코루틴이 끝날 때까지 대기

yield return new WWW(string)

웹 통신 작업이 끝날 때까지 대기

yield return new AsyncOperation

비동기 작업이 끝날 때까지 대기 ( 씬로딩 )

 
 
코루틴은 왜 좋은가요?
 
첫 번째로 좋은 점은 성능입니다.
예를 들어 코루틴에서 yield return new WaitForSeconds(10)이라는 명령을 수행하면 코루틴은 유니티 엔진에게 WaitForSeconds(10)이라는 데이터를 보내고 쉬기 시작합니다. 유니티 엔진은 이를 받고 기록해두었다가 묵묵하게 자기 할 일을 진행 하면서 10초가 지나면 쉬고 있는 코루틴을 깨웁니다. 
코루틴이 없이 일반적으로 이를 구현 한다면 Update 구문에서 Time.deltaTime을 사용하여 매 프레임마다 시간을 더해서 10초가 지났는지 감지해야 하는데, 프레임의 평균 소요 시간이 0.01초라고 한다면, 아이러니하게 10초 동안 대기하기 위해 스크립트는 Update 함수를 1000번 호출해야 합니다. 코루틴을 사용하면 10초 동안 스크립트가 쉬는데 말이지요~ 
이러한 점 때문에 특히 모바일 기기에서 코루틴의 활용은 성능 향상에 큰 영향을 미칩니다.
 
두 번째로 좋은 점은 가독성입니다. 
코루틴을 사용하면 읽기 좋은 코드가 만들어집니다. 아래 예를 보면 1초를 대기한 후에 2초를 대기하는 작업을 수행하는 두 코드의 가독성에서 확연한 차이를 볼 수 있습니다.
( 참고로 Start 함수를 IEnumerator로 선언해주면 엔진이 자동으로 코루틴으로 실행해줍니다. )
 

public class UpdateTimer : MonoBehaviour {

    float accumulator = 0.0f;

    bool wait1Finished = false;

    bool wait2Finished = false;

    float waitTime1 = 1.0f;

    float waitTime2 = 2.0f;

    void Start() {

        Debug.Log ("Action Start!");

    }

    void Update () {

        accumulator += Time.deltaTime;

        if(!wait1Finished && !wait2Finished) {

            if(accumulator >= waitTime1) {

                Debug.Log ("Action1 End");

                wait1Finished = true;

                accumulator = 0.0f;   

            }

        } else if(wait1Finished) {

            if(accumulator >= waitTime2) {

                Debug.Log ("Action2 End");

                wait2Finished = true;

                accumulator = 0.0f;   

            }

        }

    }

}

public class CoRoutineTimer : MonoBehaviour {

    float waitTime1 = 1.0f;

    float waitTime2 = 2.0f;

    

    IEnumerator Start () {

        Debug.Log ("Action Start");

        yield return new WaitForSeconds(waitTime1);

        Debug.Log ("Action1 End");

        yield return new WaitForSeconds(waitTime2);

        Debug.Log ("Action2 End");

    }     

}

 

 
 
코루틴의 특징 및 활용
 
코루틴의 활용 방법은 아주 다양할 수 있지만, 저는 세 가지로 구분해봤습니다. 
가장 많이 사용되는 빈도 순으로 정리해봤습니다.
 
첫 번째로 코루틴에서 가장 많이 사용되는 데이터는 WaitForSeconds 명령 입니다. 
앞서서 살펴본 예제처럼 마치 멀티 쓰레드 프로그래밍의 Thread.Sleep 함수 처럼 원하는 시간만큼 잠들어 있을 수 있습니다. 하지만 더욱 좋은 점은 엔진과 동일한 싱글 쓰레드로 돌아가기 때문에, 멀티 쓰레드 프로그래밍의 여러운 부분인 자원 관리 및 컨텍스트 스위칭(Context Switching)과 같은 다양한 고려 사항들을 신경쓸 필요가 없습니다.
 
두 번째로 많이 사용하는 부분은 비동기 작업인데, 웹에서의 데이터 수신, 씬 로딩과 같은 오래 걸리는 작업을 엔진에게 넘기고, 자신은 진행상황을 점검하면서 UI 처리만 수행하는 형태로 사용합니다. 
아래와 같은 WWW 클래스가 대표적인 비동기 작업인데, 웹에서 데이터를 다운로드 받기 위해 스크립트는 엔진에게 www 클래스를 만들어 데이터를 받아올 URL과 함께 넘기고 자신은 쉽니다. 
이를 받은 엔진은 비동기 처리를 위한 쓰레드를 생성하고 네이티브 라이브러리를 사용하여 웹에 접속한 후 데이터를 다운로드하면서 스크립트로부터 넘겨 받은 www 객체에 직장 상사에게 보고하듯 현재 진행상황을 저장해둡니다. ( 이 때 클래스의 레퍼런스를 넘겼기 때문에 다른 스크립트에서 진행상황을 읽어들이는 것이 가능합니다. )
엔진에서 다운로드가 끝나면 www 객체에는 완료 상황보고와 함께 받은 데이터가 저장되며, 엔진은 스크립트를 깨웁니다. 스크립트에서는 곤히 자고 일어나 눈비비면서 이를 사용하면 됩니다. 
아래는 코루틴이 쉬는 동안 엔진은 열심히 다운로드 받고, Update 함수는 이를 보면서 열심히 진행상황을 로그로 남기는 예제입니다. 
 

public class WebBasic : MonoBehaviour {

 

    public string url;

    WWW www;

    

    bool isDownloading = false;

    

    IEnumerator Start()

    {

        www = new WWW(url);

        isDownloading = true;

        yield return www;

        isDownloading = false;

        Debug.Log ("Download Completed!");

    }

    

    void Update()

    {

        if(isDownloading)

            Debug.Log (www.progress); 

    }

 

}

 
매 프레임마다 진행상황을 그리거나, Update 함수 자체를 쓰는게 부담스러우면 아래와 같이 UI만을 그리는 코루틴을 하나 더 발생시키는 것도 좋은 방법이 되겠지요. 
 

public class WebAdvanced : MonoBehaviour {

    

    public string url;

    WWW www;

    

    IEnumerator Start()

    {

        www = new WWW(url);

        StartCoroutine("CheckProgress");

        yield return www;

        Debug.Log ("Download Completed!");

    }

    

    IEnumerator CheckProgress()

    {

        Debug.Log (www.progress);

        while(!www.isDone)

        {

            yield return new WaitForSeconds(0.5f);

            Debug.Log (www.progress);

        }

    }

        

}

 
마지막으로 코루틴을 사용하여 작업을 원하는대로 순차적으로 수행할 수 있습니다. 
이 기능은 C#과 같은 고급 언어(Hight Level Language)에서 지원하는 리플렉션(Reflection)기능과 코루틴 기능이 혼합된 활용성에 있어서 백미(白眉)라고 할 수 있겠습니다. 
이의 활용 예를 위해, RPG 게임등에서 흔히 보이는 패턴인 A와 B와 중 하나를 선택하게 하는 다이얼로그를 띄운 후, 사용자의 결정에 따라 A를 선택하면 ActionA를 수행하고 B를 선택하면 ActionB를 수행하는 구문을 프로그래밍 한다고 가정해봅시다. 이의 순서도는 아래와 같겠지요. 

 



이를 코루틴으로 구현하기 위해, 먼저 모든 행동을 각각 코루틴으로 정의해줍시다. 
그리고 각 행동들의 순서를 제어하는 코루틴을 만들어주고, 코루틴 안에서 행동들이 순차적으로 실행되도록 yield return new StartCoroutine 구문으로 차례대로 지정해줍니다. 첫 번째 코루틴의 결과에 따라 다음 행동이 A가 될지 B가 될지 결정되므로, 첫 번째 결과값을 string 변수로 지정하고, 변수 값을 StartCoRoutine에 넣으면 실시간으로 결과에 따른 해당 코루틴이 실시간으로 실행됩니다. 
아래는 이를 구현한 예제 입니다. 
 

public class DialogExample : MonoBehaviour {

    

    bool showDialog = false;

    string answer = "";

    

    IEnumerator Start()

    {

        yield return StartCoroutine("ShowDialog");

        yield return StartCoroutine(answer);

    }

    

    IEnumerator ShowDialog()

    {

        showDialog = true;

        do

        {

            yield return null;

        } while(answer == "");

        

        showDialog = false;

    }

    

    IEnumerator ActionA()

    {

        Debug.Log ("Action A");

        yield return new WaitForSeconds(1f);

    }

 

    IEnumerator ActionB()

    {

        Debug.Log ("Action B");

        yield return new WaitForSeconds(2f);

    }

    

    void OnGUI()

    {

        if(showDialog)

        {

            if(GUI.Button(new Rect(10f, 10f, 100f, 20f), "A"))

            {

                answer = "ActionA";   

            } else if(GUI.Button(new Rect(10f, 50f, 100f, 20f), "B")) {

                answer = "ActionB";

            }

        }

    }

    

}

 
결과 값의 유효성을 강화하고 싶다면 아래와 같이 enum을 보조적으로 사용하는 것도 좋은 방법이 될 수 있습니다.
 

using UnityEngine;

using System.Collections;

 

public class DialogExampleEnum : MonoBehaviour {

 

    enum DialogActions {

        ShowDialog,

        ActionA,

        ActionB

    };

    

    bool showDialog = false;

    DialogActions action = DialogActions.ShowDialog;

    

    IEnumerator Start()

    {

        yield return StartCoroutine(action.ToString());

        yield return StartCoroutine(action.ToString());

    }

    

    IEnumerator ShowDialog()

    {

        showDialog = true;

        do

        {

            yield return null;

        } while(action == DialogActions.ShowDialog);

        

        showDialog = false;

    }

    

    IEnumerator ActionA()

    {

        Debug.Log ("Action A");

        yield return new WaitForSeconds(1f);

    }

 

    IEnumerator ActionB()

    {

        Debug.Log ("Action B");

        yield return new WaitForSeconds(2f);

    }

    

    void OnGUI()

    {

        if(showDialog)

        {

            if(GUI.Button(new Rect(10f, 10f, 100f, 20f), "A"))

            {

                action = DialogActions.ActionA;         

            } else if(GUI.Button(new Rect(10f, 50f, 100f, 20f), "B")) {

                action = DialogActions.ActionB;

            }

        }

    }

 

}

 
이러한 특징을 잘 활용하면 AI를 위한 유한상태기계(Finite State Machine)를 구현할 때에도 별도의 클래스를 만들지 않고 쉽게 코딩이 가능해집니다.
 
출처: http://www.unitystudy.net/bbs/board.php?bo_table=writings&wr_id=43
 
 
 

 

반응형

+ Recent posts