Unity3d HttpWebRequest 비동기 형식 사용하기

간단한 GET 형식으로 사용할 때는 WWW가 편하고 좋다.

하지만 일부 사이트는 User-Agent 값을 읽어 막는 곳이 있었다.

그래서 User-Agent값을 수정하려고 했지만, 지원하지 않았다.


아래 코드는 User-Agent값 수정이 자유롭고, 

동기모드 사용시, 유니티 메인쓰레드가 멈춰 게임 화면이 멈추게 되는데,

Coroutine과 HttpWebResponse 비동기 모드를 사용하면 멈춤 현상을 해결할 수 있다.


비동기 모드 사용시 주의 점은 메인쓰레드가 아닌 곳에서 유니티 오브젝트 또는 함수를 사용하면 

get_isActiveAndEnabled can only be called from the main thread. 같은 오류가 발생한다.

제대로 하려면 쓰레드간 통신을 위한 큐를 만들고 

메인쓰레드가 그 큐를 읽어 처리를 하면 되겠지만, 

간단히 웹에 대한 결과만 얻어오면 되니, 그냥 간단하게 만들었다.


코루틴 비동기 함수가 끝났는지를 체크할 수 있는 로컬 변수 isDone을 정의해 사용했다.

비동기 함수 완료 콜백함수(타 쓰레드)에서 가져올 데이터가 있다면 로컬 변수에 저장 시켜야 한다.

여기서는 text에 저장시켰다.

text에 저장시킨 후, 즉 사용할 모든 데이터를 저장시킨 후, 

맨 마지막에 isDone을 true값으로 변경해야 원자성을 보장할 수 있겠다.


아래 코드를 참고해 적절히 수정해서 쓰면 좋을 것 같다.

[SerializeField] Text m_text; IEnumerator TestWWW(string url) { bool isDone = false; string text = null; /* using (WWW www = new WWW(url)) { yield return www; m_text.text = string.IsNullOrEmpty(www.error) ? "no error" : www.error; m_text.text = www.text; }*/ // for https ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; /* // sync HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); httpWebRequest.UserAgent = ""; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { m_text.text = reader.ReadToEnd(); } */ // async HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url); httpWebRequest.BeginGetResponse(new AsyncCallback((IAsyncResult iarres) => { try { using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(iarres)) { using (StreamReader streamReader = new StreamReader(response.GetResponseStream())) { // can only be called from the main thread //m_text.text = streamReader.ReadToEnd(); text = streamReader.ReadToEnd(); isDone = true; } response.Close(); } } catch (Exception e) { } }), null); while(!isDone) yield return null; m_text.text = text; }