Resources
Unity의 리소스 폴더는 'Resources.Load' 메서드를 사용하여 런타임에 자산을 로드할 수 있는 특수 폴더이다.
Resources 폴더(또는 하위 폴더)에 배치된 모든 자산은 게임 빌드에 포함되며
해당 파일 이름이나 경로를 사용하여 액세스할 수 있다.
Resources 폴더는 주로 리소스를 동적으로 로드하는 것이 아니라,
초기화나 초기 설정에서 사용되는 리소스들을 포함하는 데 사용된다.
즉, 게임이나 앱이 실행될 때 미리 로드해야 할 리소스들을
Resources 폴더에 넣어서 빌드 파일에 포함하게 되는 것이다.
이러한 사용 방식은 특정 리소스들을 미리 로드하여 앱의 실행 속도를 향상시키는데 유용하지만
모든 리소스들을 빌드 파일에 포함하므로 빌드 파일의 크기에 주의해야 한다.
실제 게임 개발에서는 Addressable Assets 등의 기능을 활용하여 더 유연하고 효율적인 리소스 관리를 할 수 있다. Resources 폴더를 사용하는 대신 Addressable Assets를 활용하면
메모리 사용량을 최적화하고 게임의 크기를 줄일 수 있다.
using UnityEngine;
public class LoadPrefabFromResources : MonoBehaviour
{
void Start()
{
// Resources 폴더의 "Prefabs" 폴더에서 "CubePrefab" 프리팹을 로드합니다.
GameObject cubePrefab = Resources.Load<GameObject>("Prefabs/CubePrefab");
if (cubePrefab != null)
{
// 로드된 프리팹을 씬에 생성합니다.
Instantiate(cubePrefab, Vector3.zero, Quaternion.identity);
}
else
{
Debug.LogError("CubePrefab을 찾을 수 없습니다.");
}
}
}
StreamingAssets
스트리밍에 필요한 파일들은 StreamingAssets 폴더에 넣어서 로드할 수 있다.
StreamingAssets 폴더에 있는 파일은
대상 컴퓨터에서 유니티가 지정한 특정 폴더로 복사되므로 리소스에 접근할 수 있다.
Application.streamingAssetsPath를 사용해서 액세스 할 수있다.
Application.streamingAssetsPath이 반환하는 폴더위치는 플랫폼별로 다르다.
(유니티 공식 메뉴얼 참고)
에셋을 빌드 패키지에 포함하지 않고 필요할 때 동적으로 로드하여 빌드 크기를 더 작게 유지할 수 있다.
즉, 처음부터 로드할 필요가 없는 비디오 또는 고해상도 텍스처와 같은 큰 자산에 특히 유용할 수 있다.
using UnityEngine;
using UnityEngine.Video;
public class LoadAsset : MonoBehaviour
{
public VideoPlayer videoPlayer;
void Start()
{
string videoPath = Path.Combine(Application.streamingAssetsPath, "myVideo.mp4");
videoPlayer.url = videoPath;
videoPlayer.Play();
}
}
Resources와 StreamingAssets의 차이점
Resources는
에셋을 임포트 한 후 타겟 플랫폼에 맞는 내부의 포맷으로 변환된다.
예를 들어 PNG파일이 변환된다면, 프로젝트가 빌드될 때 압축된다.
StreamingAssets은
에셋을 임포트 한 후 타겟 플랫폼에 맞는 내부의 포맷으로 변환되지 않는다.
예를 들어 PNG파일이 변환된다면, 프로젝트가 빌드될 때 압축되지 않는다.
AssetBundles
AssetBundles은 기본 게임 빌드와 별도로 에셋을 구성하고 패키징하는 방법이다.
이를 통해 런타임에 에셋을 동적으로 로드 및 언로드할 수 있다.
AssetBundles은 빌드 시 포함되지 않는다. 즉 빌드 용량을 줄일 수 있다.
AssetBundles은 일반적으로 특정 에셋을
원격으로 다운로드 또는 업데이트하거나 자산 변형 또는 모듈성을 효율적으로 관리하려는 경우에 사용된다.
AssetBundles과 관련된 기초 영상은 오늘코딩님 유튜브 영상에 매우 잘 설명되어있다.
예제 코드 1: 에셋번들 만들기
using UnityEditor;
using System.IO;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles";
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
}
}
예제 코드 2: 프로그램 시작 시 에셋다운로드
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class DownloadAndSaveAssetBundle : MonoBehaviour
{
public string assetBundleURL;
public string bundleFileName;
void Start()
{
StartCoroutine(DownloadAndSave());
}
IEnumerator DownloadAndSave()
{
UnityWebRequest request = UnityWebRequest.Get(assetBundleURL);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
byte[] bundleData = request.downloadHandler.data;
string bundlePath = Path.Combine(Application.persistentDataPath, bundleFileName);
File.WriteAllBytes(bundlePath, bundleData);
Debug.Log("애셋 번들 다운로드 및 저장 완료: " + bundlePath);
// 다운로드된 애셋 번들을 로드하거나 사용할 수 있습니다.
// 예를 들어, AssetBundle.LoadFromFile() 또는 AssetBundle.LoadFromMemory() 등을 사용합니다.
}
else
{
Debug.LogError("애셋 번들 다운로드 실패: " + request.error);
}
}
}
예제 코드 3: 에셋번들 로드
using UnityEngine;
public class ObstacleSpawner : MonoBehaviour
{
// 로드할 AssetBundle의 파일 이름
public string bundleFileName;
void Start()
{
// 저장된 AssetBundle을 로드합니다.
AssetBundle obstacleBundle = AssetBundle.LoadFromFile(Path.Combine(Application.persistentDataPath, bundleFileName));
if (obstacleBundle == null)
{
Debug.LogError("장애물 AssetBundle 로드 실패");
return;
}
// AssetBundle에 포함된 Prefab을 로드하여 장애물을 생성합니다.
GameObject obstaclePrefab = obstacleBundle.LoadAsset<GameObject>("ObstaclePrefab");
if (obstaclePrefab != null)
{
// 장애물을 생성하거나 필요에 맞게 위치, 회전 등을 설정합니다.
Instantiate(obstaclePrefab, transform.position, Quaternion.identity);
}
else
{
Debug.LogError("장애물 Prefab 로드 실패");
}
// 필요가 없어진다면 아래의 코드를 사용하여 AssetBundle을 해제합니다.
obstacleBundle.Unload(false);
}
}