상세 컨텐츠

본문 제목

[Unity] 유니티 URL(UnityWebRequest) Get, Post 로드 관련

게임엔진관련/유니티 엔진

by AlrepondTech 2019. 12. 20. 21:38

본문

반응형

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

 

 

 

GET 방식

        string url = "http://test1.com/login.asp?uid=playpsj1&pwd=qwe123&lv=1&step=1";

        IEnumerator WebRequest()
        {
            UnityWebRequest request = new UnityWebRequest();
            using (request = UnityWebRequest.Get(url))
            {
                yield return request.SendWebRequest();

                if (request.isNetworkError)
                {
                    Debug.Log(request.error);
                }
                else
                {
                     Debug.Log("<get>"+request.downloadHandler.text+"</get>"); 
                  // Byte[] results = request.downloadHandler.data; 

                }
            }
        }
        StartCoroutine(WebRequest()); 
 

 

 

POST 방식

        string url = "http://test1.com/login.asp";
        IEnumerator WebRequest()
        {
            UnityWebRequest request = new UnityWebRequest();


            WWWForm form = new WWWForm();
            form.AddField("uid", "playpsj1");
            form.AddField("pwd", "qwe123");
            form.AddField("lv", "1");
            form.AddField("step", "1");

            using (request = UnityWebRequest.Post(url, form))
            {
                yield return request.SendWebRequest();

                if (request.isNetworkError)
                {
                    Debug.Log(request.error);
                }
                else
                {

                  Debug.Log("<post>"+request.downloadHandler.text+"</post>"); 
                  // Byte[] results = request.downloadHandler.data;

                }
            }
        }
        StartCoroutine(WebRequest());
 
 

 

 

 

 

=================================

=================================

=================================

 

 

 

출처: https://syudal.tistory.com/entry/Unity-UnityWebRequest-POST-%ED%97%A4%EB%8D%94%EC%99%80-%EA%B0%92-%EB%84%A3%EA%B8%B0

 

Unity는 문서화가 잘 되어 있는 언어중 하나이지만, 가끔 설명이 빠진 경우도 있다.

UnityWebRequest에 POST 헤더를 넣어 전송하는 경우인데, 문서에는 값을 넣어서 전송하는 경우만 알려주고 있다.

 

https://docs.unity3d.com/kr/current/Manual/UnityWebRequest-SendingForm.html


의외로 해결하는 방법은 간단하다.

using System.Collections;

using UnityEngine;

using UnityEngine.Networking;

 

public class MyBehavior : public MonoBehaviour {

    void Start() {

        StartCoroutine(Upload());

    }

 

    IEnumerator Upload() {

        WWWForm form = new WWWForm();

        form.AddField("파라메타""데이터");

 

        UnityWebRequest www = UnityWebRequest.Post("http://www.my-server.com/myform", form);

        www.SetRequestHeader("헤더""헤더 값");

        yield return www.SendWebRequest();

 

        if(www.isNetworkError || www.isHttpError) {

            Debug.Log(www.error);

        }

        else {

            Debug.Log("성공!");

        }

    }

}

 

혹시 '기본 연결이 닫혔습니다. 보내기에서 예기치 않은 오류가 발생했습니다.'와 같은 오류가 나온다면 아래의 게시글처럼 하면된다.

 

https://syudal.tistory.com/entry/%EA%B8%B0%EB%B3%B8-%EC%97%B0%EA%B2%B0%EC%9D%B4-%EB%8B%AB%ED%98%94%EC%8A%B5%EB%8B%88%EB%8B%A4-%EB%B3%B4%EB%82%B4%EA%B8%B0%EC%97%90%EC%84%9C-%EC%98%88%EA%B8%B0%EC%B9%98-%EC%95%8A%EC%9D%80-%EC%98%A4%EB%A5%98%EA%B0%80-%EB%B0%9C%EC%83%9D%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4

 

 

 

=================================

=================================

=================================

 

 

 

반응형

 

 

728x90

 

 

 

출처: https://wergia.tistory.com/36

 

UnityWebRequest를 이용해서 원격 서버에서 받아온 에셋 번들을 로컬 저장소에 저장하는 방법

유니티 5.6 문서에서는 알려주지 않는 로컬 저장소 저장 방법

유니티 5.6 문서에서는 웹 서버에서 에셋 번들을 받아올 때 WWW.LoadFromCacheOrDownload 대신에 UnityWebRequest와 DownloadHandlerAssetBundle을 사용할 것을 권장하고 있다. 아래의 코드가 유니티 5.6 문서에서 보여주는 웹 서버에서 에셋 번들을 받아와서 메모리에 로드하는 예제이다.

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}

출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}

출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}

출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}

출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]

using UnityEngine;
using UnityEngine.Networking;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}

출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]

서버에서 받아온 에셋 번들을 메모리에 넣어두고 사용하고자 하는 목적이 아니라 받아온 에셋 번들을 클라이언트의 로컬 저장소에 저장하고 패치하는 시스템을 만들고자할 때에는 부적절한 예제이며, 로컬 저장소에 저장하는 방법은 유니티 5.6의 문서에서는 알려주지 않는다.

 

 

에셋 번들을 로컬 저장소에 저장하는 방법

서버에서 받아온 에셋 번들을 로컬 저장소에 저장하려면 받아온 데이터를 파일 입출력을 해야했는데, 그러기 위해서는 우선 받아온 에셋 번들의 데이터, byte[] data를 찾아내고 거기에 엑세스할 수 있어야 했다. 그래서 첫 번째로 시도한 방법이 위의 예제에서 UnitWebRequest.GetAssetBundle()로 받아온  UnityWebRequest request에서 request.downloadHandler.data를 통해서 접근하는 것이었다.

using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class AssetLoader : MonoBehaviour
{
public string[] assetBundleNames;

IEnumerator AccessFailMethod()
{

string uri = "http://127.0.0.1/character";


UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri);

yield return request.Send();
string assetBundleDirectory = "Assets/AssetBundles";

if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}

FileStream fs = new FileStream(assetBundleDirectory + "/" + "character.unity3d", System.IO.FileMode.Create);
fs.Write(request.downloadHandler.data, 0, (int)request.downloadedBytes);
fs.Close();
}
}

하지만 위의 방법은 에셋 번들에 대한 원시 데이터 접근은 지원하지 않는다는 예외를 발생시키고 실패한다. 즉, GetAssetBundle로 웹 서버에서 불러온 데이터는 데이터에 대한 직접 접근을 허용하지 않으니 파일 입출력을 통해서 로컬 저장소에 저장할 수 없다는 것이다.

 

그렇기 때문에 로컬 저장소에 저장하기 위해서는 웹 서버에서 에셋 번들을 받아올 때 다른 방법을 취해야 했다. 아래의 예제가 다른 방식으로 웹 서버에서 에셋 번들을 받아와서 로컬 저장소에 저장하는 예제이다 :

using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class AssetLoader : MonoBehaviour
{

// 서버에서 받아오고자 하는 에셋 번들의 이름 목록

// 지금은 간단한 배열 형태를 사용하고 있지만 이후에는

// xml이나 json을 사용하여 현재 가지고 있는 에셋 번들의 버전을 함께 넣어주고

// 서버의 에셋 번들 버전 정보를 비교해서 받아오는 것이 좋다.
public string[] assetBundleNames;

IEnumerator SaveAssetBundleOnDisk()
{

// 에셋 번들을 받아오고자하는 서버의 주소

// 지금은 주소와 에셋 번들 이름을 함께 묶어 두었지만

// 주소 + 에셋 번들 이름 형태를 띄는 것이 좋다.
string uri = "http://127.0.0.1/character";

 

// 웹 서버에 요청을 생성한다.
UnityWebRequest request = UnityWebRequest.Get(uri);
yield return request.Send();

 

// 에셋 번들을 저장할 경로

string assetBundleDirectory = "Assets/AssetBundles";
// 에셋 번들을 저장할 경로의 폴더가 존재하지 않는다면 생성시킨다.
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}

 

// 파일 입출력을 통해 받아온 에셋을 저장하는 과정
FileStream fs = new FileStream(assetBundleDirectory + "/" + "character.unity3d", System.IO.FileMode.Create);
fs.Write(request.downloadHandler.data, 0, (int)request.downloadedBytes);
fs.Close();
}
}

위 예제에서 보다시피 UnityWebRequest.Get() API를 사용했을 경우 받아온 에셋 번들의 원시 데이터에 대한 접근이 가능해진다. 이로 인해서 파일 입출력을 통한 원격 서버에서 받아온 에셋 번들의 로컬 저장소 저장에 성공하게 되었다.

 

 

파일 입출력을 통한 저장 방법

받아온 에셋 번들을 파일 입출력을 통해 로컬 저장소에 저장하는 방법은 여러가지가 있다. 적당하다고 생각되는 방법을 골라서 사용하면 될 것이다.

// 파일 저장 방법 1
FileStream fs = new FileStream(assetBundleDirectory + "/" + "character.unity3d", System.IO.FileMode.Create);
fs.Write(request.downloadHandler.data, 0, (int)request.downloadedBytes);
fs.Close();

// 파일 저장 방법 2
File.WriteAllBytes(assetBundleDirectory + "/" + "character.unity3d", request.downloadHandler.data);
 

// 파일 저장 방법 3
for (ulong i = 0; i < request.downloadedBytes; i++)
{
fs.WriteByte(request.downloadHandler.data[i]);
// 저장 진척도 표시

}

 

 

로컬 저장소에 저장한 에셋 번들을 불러와서 사용하는 방법

위의 과정을 통해 원격 서버에서 받아온 에셋 번들을 로컬 저장소에 저장하는데 성공했다. 이 다음에 해야할 작업은 저장한 에셋 번들을 불러와서 사용하는 것이다. 그 작업은 유니티 5.6 문서에 나오는 기본 예제를 구현하는 것으로 충분히 가능하다.

using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class AssetLoader : MonoBehaviour
{
IEnumerator LoadAssetFromLocalDisk()
{
string assetBundleDirectory = "Assets/AssetBundles";
// 저장한 에셋 번들로부터 에셋 불러오기
var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(assetBundleDirectory + "/", "character.unity3d"));
if (myLoadedAssetBundle == null)
{
Debug.Log("Failed to load AssetBundle!");
yield break;
}
else
Debug.Log("Successed to load AssetBundle!");

var prefab = myLoadedAssetBundle.LoadAsset<GameObject>("P_C0001");
Instantiate(prefab, Vector3.zero, Quaternion.identity);
}
}



출처: https://wergia.tistory.com/36 [베르의 프로그래밍 노트]

 

 

 

=================================

=================================

=================================

 

 

 

출처: https://unitytip.tistory.com/45

 

안녕하세요. 유니티에서 WebText 긁어오기 두 번째 포스팅입니다. 이번에는 UnityWebRequest시스템을 활용해서 긁어와 보겠습니다. 사실 활용 자체를 웹 텍스트를 긁어오는데 사용하고 있지만,  다른 용도로도 활용 가능합니다. 일반적으로 통신이나 정보를 받아오는데 쓰겠죠. 저도 다른 내용으로 활용해본 적은 많지 않기 때문에 예시를 이렇게 활용하지만 기본적인 통신에는 WWW나 UnityWebRequest모두 다 활용할 수 있다고 생각합니다. 쓰기 편한 걸 쓰는 게 좋을 것 같습니다. 

 

 UnityWebRequest에 대한 메뉴얼을 보면 이렇게 적혀있습니다. "UnityWebRequest는 HTTP 요청을 구성하고 HTTP 리스폰스를 처리하기 위한 모듈식 시스템을 제공합니다. UnityWebRequest 시스템의 주요 목표는 Unity 게임이 최신 웹 브라우저 백 엔드와 상호작용할 수 있도록 하는 것입니다. 또한 대량의 HTTP 요청, POST/PUT 스트리밍 작업, HTTP 헤더 및 동사의 완벽 제어 등 수요가 높은 기능을 지원합니다." 서버와 데이터 주고 받고 하는데 쓰기 위해 만든다 머 그런거 같군요. 활용 보겠습니다. 

 

 IEnumerator WebRequest()

    {

        UnityWebRequest request = new UnityWebRequest();

        using (request = UnityWebRequest.Get("http://unitytip.tistory.com/"))

        {

            yield return request.SendWebRequest();

            if (request.isNetworkError)

            {

                Debug.Log(request.error);

            }

            else

            {

                Debug.Log(request.downloadHandler.text);

                Byte[] results = request.downloadHandler.data;

            }

        }

    }

저는 using을 썼지만 유니티 메뉴얼에는 using을 쓰지 않았습니다. 편한 거 쓰시면 됩니다. UnityWebRequest 메소드 중에 Get과 Post가 있는데 웹 개발해보신 분이면 알 수 있는 이름입니다. Post 활용은 다음 시간에 해보도록 하겠습니다. 관련해서 폼생성도 같이 알아보고 조금 덧붙일 내용이 있는데 다 쓰면 너무 길어지니까요. Get을 통해서 url에 있는 내용을 downloadHandler에 담고 이 친구를 통해서 얻어온 정보를 가공할 수 있습니다. 예시대로 하면 웹 텍스트와 바이너리 데이터를 모두 얻어오게 됩니다. 필요에 따라서 가공해서 쓰시면 되겠습니다. 정말 지식이 얕아서 함부로 말할 수 없기 때문에 깊은 설명은 할 수가 없네요. 눈물이 앞을 가립니다.  다음에는 WWW 클래스의  Post와 UnityWebRequest의 Post에 대해서 포스팅해보겠습니다. 그리고 그와 관련되서 애를 먹었던 부분도 설명하고 어떻게 해결했는지도 남기겠습니다.

출처: https://unitytip.tistory.com/45 [Unity Tip 모음 by dnrkckzk]

 

 

=================================

=================================

=================================

 

 

반응형


관련글 더보기

댓글 영역