DanielEverland/ScriptableObject-Architecture

Support for AssetReference ?

Moret84 opened this issue · 1 comments

Hi, Thanks for your work on this asset !

My projects make uses of adressable assets. Some scenes are adressables, some are not.
A problem appears when you want to share some ScriptableObjects (in my case, i will focus on Events) between scenes that are built as Addressable and "straight" scenes. Indeed, each one will embed a copy of the scriptable object when "packed". Hence, when an event is raised, GameEventListeners packed in addressables scenes won't respond because they hold a copy of the original game event, and this copy is obviously not raised. The only way to share a variable in this context is to use AddressableAssets.AssetReference. You can then use the referenced object, but you have to "load" it before being able to access it (otherwise you will encounter null reference).

Prior to discovering your asset, I used my own implementation that was basically a copycat of what Ryan Hipple showed in his talk.
But, to fit my needs I had added a basic AssetReference support.

using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;

    public class GameEventListener : MonoBehaviour
    {
        /// <summary>
        /// The associated gamed event.
        /// </summary>
        [SerializeField]
        private GameEvent Event;

        /// <summary>
        /// The associated addressable game event.
        /// </summary>
        [SerializeField]
        private AssetReference AddressableEvent;

        /// <summary>
        /// The response to called when event occurs.
        /// </summary>
        [SerializeField]
        private UnityEvent Response;

        private async void OnEnable()
        {
            // If both addressable event and local event are set then addressable event supersedes local event.
            if (AddressableEvent.RuntimeKeyIsValid())
            {
                await AddressableEvent.LoadAssetAsync<GameEvent>().Task;

                ((GameEvent)AddressableEvent.Asset).RegisterListener(this);
            }
            else
            {
                Event.RegisterListener(this);
            }
        }

        private async void OnDisable()
        {
            if (AddressableEvent.RuntimeKeyIsValid())
            {
                await AddressableEvent.LoadAssetAsync<GameEvent>().Task;

                ((GameEvent)AddressableEvent.Asset).RegisterListener(this);
            }
            else
            {
                Event.UnregisterListener(this);
            }
        }

        /// <summary>
        /// Called when an event is raised.
        /// </summary>
        public void OnEventRaised()
        {
            Response?.Invoke();
        }
    }
}

Is it worth to add support for AssetReference to Event listeners ?
Is somebody interested in ?
Is there a better way than my quick and dirty sample ?

Hello, I'm just giving my take on this problem. If a scriptable object is an Addressable, and you want to have scene object to have the same reference as the one in Addressable, you can "fix" it by having your scene to be an Addressable too. So when Addressable is packing, it will reference the same object.

That means, scriptable object is Addressable, scene is an Addressable too. That solved my problem. However u will have to handle scene loading etc.