chark/scriptable-events

Different behavior in Editor vs Build

Closed this issue ยท 6 comments

njelly commented

Hello, I was attempting to write my own solution, stumbled upon this project which does exactly what I was trying to make, so am seeing if I can just use this instead. In both my own solution and yours I am noticing different behavior in the editor vs on a build (Android).

I have a MonoBehaviour class, Damageable. This script exists on my enemy prefabs, which I am loading via an Addressable AssetReference and spawning with an ObjectPool. It has a reference to a DamageableScriptableEvent instance that exists in the project. I have a DamageableScriptableEventListener (created with the wizard) that exists in the scene and is loaded with the scene. When a Damageable is instantiated and then enabled, my intention is to Raise the DamageableScriptableEvent and have a listener that spawns health bars on the canvas. All of this is working great in the Editor.

However on a build, I am noticing that while the event is getting raised, my listener (which exists in the scene and is loaded with the scene) simply ignores the event on a build. This is not the same behavior in the editor, where the event is listened to and the health bar is spawned. I've noticed that when an event raiser/listener pair is loaded in the scene, everything works as expected on a build, but if the event raiser is an instance of a loaded prefab, the listener only receives the callback in the editor. Is this expected behavior? Is there a good solution for this situation? Is this just how ScriptableObjects work?

Thanks!

Hello and thank you for reporting the issue!

I'm quite busy at the moment with another project and won't be able to spend a lot of time debug this properly. But in short, the behavior you're describing is not expected. My guess is that it has something to do with the way addressables are setup on your project. The reason for this is that we don't use any preprocessor directives to execute code differently on Editor vs Build. Additionally, I have not used this package in a project that heavily relies on addressables (personally I try avoid addressables ๐Ÿ˜…).

When you mention that you've tried loading in the event raiser/listener in the same scene without using prefab instances, were they also loaded using addressables? Also in your builds, did you notice any exceptions in player.log/logcat?

Finally, you mentioned "I am noticing that while the event is getting raised" - how did you test this? As in, did you have some Game Objects subscribe to this event using one approach and some Game Objects subscribing using the "in the scene" approach? Perhaps the key is this difference?

njelly commented

I understand and appreciate your fast response! I went ahead and put together a Unity project to actually demonstrate the issue I'm describing.

https://github.com/njelly/addressables-scriptableobjects-test

I think this has to do with the way Unity serializes ScriptableObjects, so not necessarily a bug but a user-unfriendly "feature" on Unity's end. Essentially spawning with a direct Prefab reference will maintain the link between raiser/listener but a reference spawned via an AssetReference will only maintain that link in the editor.

There are no exceptions in logcat. I have the ScriptableEvent asset set to isDebug to log when events are subscribed and raised. As far as I can tell and understand, the ScriptableEvent on the AssetReference instance is a separate instance entirely, and so it doesn't have any references to subscribers in the scene.

I think you're right. I did a some snooping around and stumbled upon quite a few threads regarding this issue. Additionally some other packages providing SO event architecture also seem to have encountered this issue (e.g., unity-atoms).

Anyway, looks like this thread has some possible workarounds:
https://forum.unity.com/threads/scriptableobject-references-in-addressables.777155/

njelly commented

That thread is very helpful, thank you!

njelly commented

Addendum: in the repo above I added a workaround for this issue, which is to mark the ScriptableEvent as addressable as well as load the scene via addressables. Hopefully it's useful for whoever might stumble across this problem with your repo!

Thanks for the update after investigating! I've created an issue to document this based on your findings for future travelers :D