씬 로드 & 언로드
씬의 로드와 언로드를 구현해보자.
어드레서블 Key로 로드하기
![](https://blog.kakaocdn.net/dn/k7unP/btqE7AVVdVz/hRDY77KPwvtnMnN3bNB5bk/img.png)
Addressable Name이 'BouncyBall'인 씬 에셋이 있다.
'BouncyBall'은 어드레서블 네임임과 동시에 'key'에 해당한다. (Label도 key가 될 수 있다)
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
public class AddressSceneLoader: MonoBehaviour
{
public string addressSceneKey = "BouncyBall";
private SceneInstance _sceneInstance;
public void LoadSceneAsync()
{
Addressables.LoadSceneAsync(addressSceneKey, LoadSceneMode.Additive).Completed +=
(handle) =>
{
if (handle.Status == AsyncOperationStatus.Succeeded)
{
_sceneInstance = handle.Result;
}
};
}
public void UnloadSceneAsync()
{
Addressables.UnloadSceneAsync(_sceneInstance).Completed +=
(handle) =>
{
Resources.UnloadUnusedAssets();
};
}
}
|
어드레서블을 string타입인 key로 참조하기 때문에 번거로울 수 있다.
에셋 레퍼런스로 로드하기
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
public class AddressSceneLoader: MonoBehaviour
{
public AssetReference addressScene;
private AsyncOperationHandle<SceneInstance> _handle;
public void LoadSceneAsync()
{
addressScene.LoadSceneAsync(LoadSceneMode.Additive).Completed +=
(handle) =>
{
if (handle.Status == AsyncOperationStatus.Succeeded)
{
_handle = handle;
}
};
}
public void UnloadSceneAysnc()
{
Addressables.UnloadSceneAsync(_handle).Completed +=
(handle) =>
{
Resources.UnloadUnusedAssets();
};
}
}
|
AssetReferece 타입으로 직접 참조하기 때문에 오타에 대한 걱정은 안해도 된다.
Scene을 언로드하는 함수는 여러가지로 오버로드되어있는데 위 예시에는 AsyncOperationHandle과 SceneInstance를 사용했다.
Resources.UnloadUnusedAsset
![](https://blog.kakaocdn.net/dn/bHoLaa/btqE7Q5lkol/qqhxT0QKN3BnMhrj6crBhk/img.png)
씬을 언로드한 후의 메모리 상태이다. Cubemap은 해당 씬이 참조한 것들이다.
씬 메모리의 리소스들은 자동으로 해제되는데, Cubemap 에셋은 Unload를 해도 Ref Count가 0인데도 불구하고 그대로 존재한다.
("버그라고 생각되지만...")
Resources.UnloadUnsedAsset 함수를 호출해서 메모리상 할당을 해제해주자.
SpaceShooter 디버깅 - NullReferenceException
![](https://blog.kakaocdn.net/dn/qimmA/btqFeNBb2HS/ff6Bm060lOghtMfFW4q2T0/img.png)
씬을 로드할 때마다 해당 널참조 에러가 발생한다.
Behaviour.get_isActiveAndEnabled(UnityEngine.Behaviour)로부터 발생한 걸 보아 씬이 새로 로드 됐는데도 해당 개체가 참조되고 있어서 그런듯하다.
![](https://blog.kakaocdn.net/dn/P1mep/btqFftWBVqi/ePQkOWiJKSKH68cTkRE6N1/img.png)
마우스 왼쪽 클릭을 하면 발사체가 생성된다.
![](https://blog.kakaocdn.net/dn/bOAcTR/btqFfugQN0n/dff5Ppgu5biJzf4vuGjx11/img.png)
프리팹을 생성 중에 씬이 사라지니 널참조 에러가 발생한듯하다. 중복된 키를 주석처리하자.
Component AssetReference
Material, ScriptableObject, Sprite 등의 Object는 단독으로 Addressable이 될 수 있다.
반면 스크립트는 Addressable이 될 수 없으므로 AssetReference로 필터링 할 수 없다.
GameObject를 통해서 특정 Component를 필터링하는 ComponentReference를 구현해보자.
[Serializable]
public class ComponentReferenceColorChanger : ComponentReference<ColorChanger>
{
public ComponentReferenceColorChanger(string guid) : base(guid) { }
}
|
Filtered AssetReference과 동일하게 작성해주면 된다.
이제 해당 필드는 'ColorChanger'가 붙은 GameObject 외에는 할당할 수 없다.
GameObject가 생성되면서 Result로 'ColorChanger' 컴포넌트를 반환한다.
"생성된 GameObject는 어떻게 참조하지?"
![](https://blog.kakaocdn.net/dn/cZiIhp/btqE8xEAyu5/nAKGokiaQmUlNhUeGAYti1/img.png)
ComponentReference<TComponent>
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class ComponentReference<TComponent> : AssetReference
{
public ComponentReference(string guid) : base(guid)
{
}
/*
Addressables.ResourceManager.CreateChainOperation를 통해서
GameObject와 TComponent를 연결하는 작업을 수행한다.
*/
public new AsyncOperationHandle<TComponent> InstantiateAsync(Vector3 position, Quaternion rotation, Transform parent = null)
{
return Addressables.ResourceManager.CreateChainOperation<TComponent, GameObject>(base.InstantiateAsync(position, Quaternion.identity, parent), GameObjectReady);
}
public new AsyncOperationHandle<TComponent> InstantiateAsync(Transform parent = null, bool instantiateInWorldSpace = false)
{
return Addressables.ResourceManager.CreateChainOperation<TComponent, GameObject>(base.InstantiateAsync(parent, instantiateInWorldSpace), GameObjectReady);
}
public AsyncOperationHandle<TComponent> LoadAssetAsync()
{
return Addressables.ResourceManager.CreateChainOperation<TComponent, GameObject>(base.LoadAssetAsync<GameObject>(), GameObjectReady);
}
AsyncOperationHandle<TComponent> GameObjectReady(AsyncOperationHandle<GameObject> arg)
{
var comp = arg.Result.GetComponent<TComponent>();
return Addressables.ResourceManager.CreateCompletedOperation<TComponent>(comp, string.Empty);
}
public override bool ValidateAsset(Object obj)
{
var go = obj as GameObject;
return go != null && go.GetComponent<TComponent>() != null;
}
// 에셋을 해당 필드위로 Drag해놓으면 호출되는 함수다. 에셋 타입 체크 로직.
public override bool ValidateAsset(string path)
{
#if UNITY_EDITOR
var go = AssetDatabase.LoadAssetAtPath<GameObject>(path);
return go != null && go.GetComponent<TComponent>() != null;
#else
return false;
#endif
}
public void ReleaseInstance(AsyncOperationHandle<TComponent> op)
{
// Release the instance
var component = op.Result as Component;
if (component != null)
{
Addressables.ReleaseInstance(component.gameObject);
}
// Release the handle
Addressables.Release(op);
}
}
|
이 소스는 어드레서블이 기본 제공하지 않는 소스다.
GameObject에 대한 AssetReference가 GetComponent<TComponent>로 'TComponent'라는 스크립트 컴포넌트를 체크하는 식으로 구현해놓은 것 같다.
사용하기엔 아직 불안정하다.
![](https://blog.kakaocdn.net/dn/mDfQS/btqE7nwa8qc/AuESbOPshA2ICyvCBdJox1/img.png)
해당 필드의 프리팹에서 'ColorChanger'를 제거했는데도 할당(초기화) 값이 유지됐다.
![](https://blog.kakaocdn.net/dn/bHeeuU/btqE6xMNb3O/ImlJk5Nm9pxlAUC6RozARk/img.png)
원레라면 Missing이 뜨면서 비워져야 정상이다. 보완 코드가 필요해보인다.
"Filtered AssetReference도 이것도 너무 번거로운데 그냥 Label 사용하는게 더 낫지 않을까?...."
"단순하게 Drag&Drop 시 타입을 필터링 한다는 기능 빼고는 크게 효용을 못느끼겠다."
'Unity > 어드레서블 에셋 시스템' 카테고리의 다른 글
어드레서블 에셋 시스템 - 개념: Label로 로드하기 (0) | 2020.06.26 |
---|---|
어드레서블 에셋 시스템 - 디버깅: 에셋 빌드 에러 DirectoryNotFoundException (0) | 2020.06.26 |
어드레서블 에셋 시스템 - 개념: 에셋 로드와 생성 및 해제 (2) | 2020.06.24 |
어드레서블 에셋 시스템 - 개념: 어드레서블 에셋, Filtered AssetReference (1) | 2020.06.16 |
어드레서블 에셋 시스템 - 개념: 어드레서블 윈도우, 시스템 동작 플로우 (0) | 2020.06.16 |
댓글