본문 바로가기

무제_LR

Addressable로 SpriteAtlas->Sprite 불러오기, Addressable Release

 

암튼뭐라도계속만들고있는중,,,,,,

 

빌드 테스트를 하려는 김에 미뤄뒀던 SpriteAtlas를 만드려는 김에 미뤄뒀던 Addressable 에셋 언로드(Release) 코드를 넣었습니다.

 

우선 기존 스프라이트 이름 혹은 key를 사용해 Addressable.LoadAssetAsync<Sprite>(key)로 불러오던 것들을

 

    private SpriteAtlas atlas;
//atlas 저장해두기


	private async UniTask LoadAtlasAsync()//대충 코드 생명추가 극초반에 Atlas를 로드
    {
      atlas = await model.resourceManager.LoadAssetAsync<SpriteAtlas>(
        model.addressableKeySO.Path.SpriteAtlas +
        model.addressableKeySO.AtlasName.GetStatePortrait(model.playerType));
    }

    private void ChangePortrait(Portrait portrait)//아틀라스에서 이름 기반으로 떼어오기
    {
      view.PortraitImage.sprite = atlas.GetSprite(portrait.ToString());
      prevPortrait = portrait;
    }

  public enum Portrait
  {
    Idle,
    Low,
    Exhausted,

    Stun,
    Clear,
    Inputting,
    Freeze,
  }
//그래서 이미지 Enum 이름을 파일명과 동일하게 했음

Enum 이름에 맞춘 파일 이름들

어느 정도 한 장면에서 여러번 같이 불려올만한 놈들끼리 묶어놓은 아틀라스

 

기존 Addressable에서 Sprite 그룹을 SpriteAtlas 그룹으로 바꿨습니다.

 

딱히 위화감이나 오류는 느껴지는 것이 없습니다.

 

그리고 Addressable 언로드:

    private async UniTask LoadAtlasAsync()
    {
      atlas = await model.resourceManager.LoadAssetAsync<SpriteAtlas>(
        model.addressableKeySO.Path.SpriteAtlas +
        model.addressableKeySO.AtlasName.GetStatePortrait(model.playerType));
    }//위에도 올렸던 아틀라스 Load 코드

    private void ReleaseAtlas()
    {
      model.resourceManager.ReleaseAsset(
        model.addressableKeySO.Path.SpriteAtlas +
        model.addressableKeySO.AtlasName.GetStatePortrait(model.playerType));
    }//사용했던 key 그대로 Release
    
    
    //resourceManager의 ReleaseAsset
      public void ReleaseAsset(string key)
  {
    if (!assetHandles.TryGetValue(key, out var handle))
      return;//미리 캐시해둔 handle을 기준으로 릴리즈합니다.

    Addressables.Release(handle);
    assetHandles.Remove(key);
    //key에 맞는 handle이 저장되어 있다면 릴리즈
  }

Addressable로 로드한 handle은 버리지 말고 잘 모아둡시다.

저는 handle을 로드할 때마다 Dictionary<string,handle>로 저장해둬서 릴리즈 코드를 쉽게 만들 수 있었습니다.

 

그럼 Release는 언제 호출하냐?

Monobehaviour같은 경우는 뭔가 해당 오브젝트를 종료하는 메소드, 혹은 Ondestroy에서 릴리즈시키면 되겠죠.

그러나 Mono가 아닌 일반 클래스는?

    public void Dispose()
    {
      ReleaseAtlas();	//IDisposable 붙은 클래스의 Dispose에서 호출
      damagedCTS.Dispose();
      viewUpdateDisposable.Dispose();
      model.energySubscriber.UnsubscribeValueEvent(IPlayerEnergySubscriber.ValueEvent.Damaged, OnDamaged);
      if (view)
        view.DestroySelf();
    }

클래스에 IDisposable을 붙여 Dispose에서 호출하게 했습니다.

 

  private readonly CompositeDisposable disposables = new();

대충 생성 메소드()
{
	    effectService = new(
      model.resourceManager, 
      model.table.AddressableKeySO, 
      model.table.EffectTableSO,
      model.defaultEffectRoot);
    effectService.AddTo(disposables);//CompositeDisposable에 연결
}

대충 파괴 호출 메소드나 IDisposable의 Dispose()
{
	disposables.Dispose();
}

그럼 그 클래스 객체를 가지고 있는 상위 클래스에서 직접 Dispose를 시키던지, 자신의 Dispose에서 같이 Dispose시키던지 합시다.

 

다음에 할거:

스테이지 더 만들어놓기