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값으로 변경해야 원자성을 보장할 수 있겠다.


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
[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;
}


prev 1 2 3 4 5 ··· 95 next