기술 자료

Unity Engine

Unity Engine

Unity Web Request Creating Download Handlers

Choose and create the right DownloadHandler to store data, files, textures, audio, or AssetBundles.
읽는 시간 6분최근 업데이트: 한 달 전

다음과 같은 몇 가지
DownloadHandlers
유형이 있습니다.
  • DownloadHandlerBuffer
    는 간단한 데이터 저장에 사용됩니다.
  • DownloadHandlerFile
    은 메모리를 적게 사용하면서 파일을 다운로드하고 디스크에 저장하는 데 사용됩니다.
  • DownloadHandlerTexture
    는 이미지 다운로드에 사용됩니다.
  • DownloadHandlerAssetBundle
    은 에셋 번들을 가져오는 데 사용됩니다.
  • DownloadHandlerAudioClip
    은 오디오 파일을 다운로드하는 데 사용됩니다.
  • DownloadHandlerMovieTexture
    는 동영상 파일을 다운로드하는 데 사용됩니다. MovieTexture는 지원이 중단되었으므로 동영상 다운로드 및 재생에는 VideoPlayer를 사용하는 것이 좋습니다.
  • DownloadHandlerScript
    는 특수 클래스입니다. 자체적으로 아무것도 하지 않습니다 하지만 이 클래스는 사용자 정의 클래스로 상속받을 수 있습니다. 이 클래스는 UnityWebRequest 시스템에서 콜백을 수신한 후 네트워크에서 수신되는 데이터를 완전히 커스텀 처리하는 데 사용할 수 있습니다.
API는
DownloadHandlerTexture
의 인터페이스와 유사합니다.
UnityWebRequest
에는 기본값이 true인
disposeDownloadHandlerOnDispose
프로퍼티가 있습니다. 이 프로퍼티가 true일 경우 UnityWebRequest 오브젝트가 제거되면 연결된 다운로드 핸들러에서도 Dispose()가 호출되어 쓸모가 없습니다. UnityWebRequest에 대한 레퍼런스보다 다운로드 핸들러에 대한 레퍼런스를 더 오래 유지하는 경우 disposeDownloadHandlerOnDispose를 false로 설정해야 합니다.

DownloadHandlerBuffer 이 다운로드 핸들러는 가장 간단하며 대부분의 사용 사례를 처리합니다. 이는 수신된 데이터를 네이티브 코드 버퍼에 저장합니다. 다운로드가 완료되면 버퍼링된 데이터에 바이트 배열 또는 텍스트 문자열로 액세스할 수 있습니다.

예제

using UnityEngine;using UnityEngine.Networking;using System.Collections;public class MyBehaviour : MonoBehaviour { void Start() { StartCoroutine(GetText()); } IEnumerator GetText() { UnityWebRequest www = new UnityWebRequest("https://www.my-server.com"); www.downloadHandler = new DownloadHandlerBuffer(); yield return www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { Debug.Log(www.error); } else { // Show results as text Debug.Log(www.downloadHandler.text); // Or retrieve results as binary data byte[] results = www.downloadHandler.data; } }}

DownloadHandlerFile 큰 파일을 위한 특수 다운로드 핸들러입니다. 다운로드한 바이트를 파일에 직접 작성하므로 다운로드되는 파일의 크기에 관계없이 메모리 사용량이 적습니다. 다른 다운로드 핸들러와 다른 점은 이 핸들러에서 데이터를 가져올 수 없고 모든 데이터는 파일에 저장된다는 점입니다.

예제

using System.Collections;using System.IO;using UnityEngine;using UnityEngine.Networking;public class FileDownloader : MonoBehaviour { void Start () { StartCoroutine(DownloadFile()); } IEnumerator DownloadFile() { var uwr = new UnityWebRequest("https://unity3d.com/", UnityWebRequest.kHttpVerbGET); string path = Path.Combine(Application.persistentDataPath, "unity3d.html"); uwr.downloadHandler = new DownloadHandlerFile(path); yield return uwr.SendWebRequest(); if (uwr.result != UnityWebRequest.Result.Success) Debug.LogError(uwr.error); else Debug.Log("File successfully downloaded and saved to " + path); }}

DownloadHandlerTexture
DownloadHandlerBuffer
를 사용하여 이미지 파일을 다운로드한 후
Texture.LoadImage
를 사용하여 원시 바이트에서 텍스처를 생성하는 대신,
DownloadHandlerTexture
를 사용하는 것이 더 효율적입니다.

이 다운로드 핸들러는 수신한 데이터를
UnityEngine.Texture
에 저장합니다. 다운로드가 완료되면 JPEG 및 PNG를 유효한
UnityEngine.Texture objects
로 디코딩합니다.
DownloadHandlerTexture
오브젝트당 하나의
UnityEngine.Texture
사본만 생성됩니다. 이렇게 하면 가비지 컬렉션의 성능 저하가 감소합니다. 이 핸들러는 네이티브 코드로 버퍼링, 압축 풀기, 텍스처 생성을 수행합니다. 또한 압축 풀기 및 텍스처 생성은 메인 스레드 대신 워커 스레드에서 수행되므로 대형 텍스처를 로드할 때 프레임 시간을 향상시킬 수 있습니다.
마지막으로,
DownloadHandlerTexture
는 텍스처 자체를 최종적으로 생성할 때만 관리되는 메모리를 할당하므로 스크립트에서 바이트를 텍스처로 전환하는 것과 관련된 가비지 컬렉션 오버헤드가 제거됩니다.

예제

다음 예시에서는 인터넷에서 PNG를 다운로드하여 스프라이트로 전환하고 이미지에 할당합니다.
using UnityEngine;using UnityEngine.UI;using UnityEngine.Networking;using System.Collections;[RequireComponent(typeof(Image))]public class ImageDownloader : MonoBehaviour { Image _img; void Start () { _img = GetComponent<UnityEngine.UI.Image>(); Download("https://www.mysite.com/myimage.png"); } public void Download(string url) { StartCoroutine(LoadFromWeb(url)); } IEnumerator LoadFromWeb(string url) { UnityWebRequest wr = new UnityWebRequest(url); DownloadHandlerTexture texDl = new DownloadHandlerTexture(true); wr.downloadHandler = texDl; yield return wr.SendWebRequest(); if (wr.result == UnityWebRequest.Result.Success) { Texture2D t = texDl.texture; Sprite s = Sprite.Create(t, new Rect(0, 0, t.width, t.height), Vector2.zero, 1f); _img.sprite = s; } }}

DownloadHandlerAssetBundle

이 특수 다운로드 핸들러의 장점은 Unity 에셋 번들 시스템으로 데이터를 스트리밍할 수 있다는 점입니다. 에셋 번들 시스템이 충분한 데이터를 수신하면 에셋 번들은
UnityEngine.AssetBundle
오브젝트로 사용할 수 있습니다.
UnityEngine.AssetBundle
오브젝트의 사본은 하나만 생성됩니다. 이렇게 하면 런타임 메모리 할당과 에셋 번들 로드의 메모리 영향이 크게 줄어듭니다. 또한 에셋 번들을 완전히 다운로드하지 않고 부분적으로 사용할 수 있으므로 에셋을 스트리밍할 수 있습니다.
모든 다운로드와 압축 풀기는 워커 스레드에서 수행됩니다.
에셋 번들을 검색해서 가져오는 특수
assetBundle
프로퍼티가 있는
DownloadHandlerAssetBundle
오브젝트를 통해 에셋 번들이 다운로드됩니다.
에셋 번들 시스템의 작동 방식으로 인해 모든 에셋 번들에는 연결된 주소가 있어야 합니다. 일반적으로 에셋 번들이 위치한 명목상의 URL입니다(리디렉션되기 전의 URL을 의미함). 거의 모든 경우에는 UnityWebRequest에 전달한 것과 동일한 URL로 전달해야 합니다. HLAPI(고수준 API)를 사용하는 경우 이 작업이 자동으로 수행됩니다.

예제

using UnityEngine;using UnityEngine.Networking;using System.Collections;public class MyBehaviour : MonoBehaviour { void Start() { StartCoroutine(GetAssetBundle()); } IEnumerator GetAssetBundle() { UnityWebRequest www = new UnityWebRequest("https://www.my-server.com"); DownloadHandlerAssetBundle handler = new DownloadHandlerAssetBundle(www.url, uint.MaxValue); www.downloadHandler = handler; yield return www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { Debug.Log(www.error); } else { // Extracts AssetBundle AssetBundle bundle = handler.assetBundle; } }}

DownloadHandlerAudioClip

이 다운로드 핸들러는 오디오 파일 다운로드에 최적화되어 있습니다.
DownloadHandlerBuffer
를 사용하여 원시 바이트를 다운로드한 후
AudioClip
을 생성하는 대신 이 다운로드 핸들러를 사용하여 보다 편리한 방법으로 다운로드할 수 있습니다.

예제

using System.Collections;using UnityEngine;using UnityEngine.Networking;public class AudioDownloader : MonoBehaviour { void Start () { StartCoroutine(GetAudioClip()); } IEnumerator GetAudioClip() { using (var uwr = UnityWebRequestMultimedia.GetAudioClip("https://myserver.com/mysound.ogg", AudioType.OGGVORBIS)) { yield return uwr.SendWebRequest(); if (uwr.result != UnityWebRequest.Result.Success) { Debug.LogError(uwr.error); yield break; } AudioClip clip = DownloadHandlerAudioClip.GetContent(uwr); // use audio clip } }}

DownloadHandlerScript

다운로드된 데이터의 처리를 완전히 관리해야 하는 사용자를 위해, Unity 에디터는
DownloadHandlerScript
클래스를 제공합니다.
기본적으로 이 클래스의 인스턴스는 아무것도 하지 않습니다. 하지만
DownloadHandlerScript
에서 자체 클래스를 가져오는 경우 특정 함수를 오버라이드하고 이를 사용하여 데이터가 네트워크에서 도착할 때 콜백을 수신할 수 있습니다.
참고: 실제 다운로드는 워커 스레드에서 발생하지만 모든
DownloadHandlerScript
콜백은 메인 스레드에서 작동합니다. 이러한 콜백 중에 계산량이 많은 연산 작업을 수행하지 마십시오.

오버라이드할 함수

ReceiveContentLength()

protected void ReceiveContentLength(long contentLength);
이 함수는 Content-Length 헤더를 수신할 때 호출됩니다. UnityWebRequest를 처리하는 과정 중에 서버에서 하나 이상의 리디렉션 응답을 전송하는 경우 이 콜백이 여러 번 발생할 수 있습니다.

OnContentComplete()

protected void OnContentComplete();
이 함수는 UnityWebRequest가 서버에서 모든 데이터를 완전히 다운로드한 후 수신된 모든 데이터를 ReceiveData 콜백에 전달했을 때 호출됩니다.

ReceiveData()

protected bool ReceiveData(byte[] data, long dataLength);
이 함수는 원격 서버에서 데이터가 도착한 후 호출되며 프레임당 한 번 호출됩니다.
data
인자에는 원격 서버에서 수신한 원시 바이트가 포함되고,
dataLength
는 데이터 배열의 새 데이터의 길이를 나타냅니다.
사전 할당된 데이터 버퍼를 사용하지 않을 때 시스템은 이 콜백을 호출할 때마다 새 바이트 배열을 생성하며,
dataLength
는 항상
data.Length
와 같습니다. 사전 할당된 데이터 버퍼를 사용하는 경우 데이터 버퍼가 재사용되며, 업데이트된 바이트 수를 찾으려면
dataLength
를 사용해야 합니다.
이 함수는 true 또는 false 값을 반환해야 합니다. false 를 반환하면 시스템이 UnityWebRequest를 즉시 중단합니다. true 를 반환하면 처리가 정상적으로 진행됩니다.

가비지 컬렉션 오버헤드 방지 Unity의 숙련된 사용자들은 대부분 가비지 컬렉션으로 인한 CPU 스파이크를 줄이는 데 관심을 가지고 있습니다. 이러한 사용자를 위해 UnityWebRequest 시스템은 다운로드한 데이터를 DownloadHandlerScript의
ReceiveData
콜백에 전달하는 데 사용되는 관리되는 코드 바이트 배열의 사전 할당을 허용합니다.

이 함수를 사용하면 다운로드한 데이터를 캡처하기 위해 DownloadHandlerScript에서 파생된 클래스를 사용할 때 관리되는 코드 메모리 할당을 완전히 제거할 수 있습니다.
DownloadHandlerScript
를 사전 할당된 관리 버퍼와 함께 사용하려면 바이트 배열을
DownloadHandlerScript
의 생성자에 제공해야 합니다.
참고: 바이트 배열의 크기는 매 프레임마다 ReceiveData 콜백에 전달되는 데이터의 양을 제한합니다. 데이터가 많은 프레임에 느리게 도착하면 바이트 배열을 너무 작게 제공했을 수 있습니다.

예제

using UnityEngine;using UnityEngine.Networking;public class LoggingDownloadHandler : DownloadHandlerScript { // Standard scripted download handler - allocates memory on each ReceiveData callback public LoggingDownloadHandler(): base() { } // Pre-allocated scripted download handler // reuses the supplied byte array to deliver data. // Eliminates memory allocation. public LoggingDownloadHandler(byte[] buffer): base(buffer) { } // Required by DownloadHandler base class. Called when you address the 'bytes' property. protected override byte[] GetData() { return null; } // Called once per frame when data has been received from the network. protected override bool ReceiveData(byte[] data, int dataLength) { if(data == null || data.Length < 1) { Debug.Log("LoggingDownloadHandler :: ReceiveData - received a null/empty buffer"); return false; } Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveData - received {0} bytes", dataLength)); return true; } // Called when all data has been received from the server and delivered via ReceiveData. protected override void CompleteContent() { Debug.Log("LoggingDownloadHandler :: CompleteContent - DOWNLOAD COMPLETE!"); } // Called when a Content-Length header is received from the server. protected override void ReceiveContentLengthHeader(ulong contentLength) { Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveContentLength - length {0}", contentLength)); }}