I have not found anything related to this issue so I have encouraged to create a thread.
Following Ryan Hipple’s talk on event-driven architecture and scriptableObjects, as long as scriptableObjects are not attached to one scene, I am trying to broadcast events to listen them in another additive scene.
What I have so far is this:
The trigger:
using UnityEngine;
public class SoundTrigger : MonoBehaviour
{
public GameEvent ServiceSound;
public void Start()
{
ServiceSound.Raise();
}
}
The GameEvent scriptableObject:
// ----------------------------------------------------------------------------
// Unite 2017 - Game Architecture with Scriptable Objects
//
// Author: Ryan Hipple
// Date: 10/04/17
// ----------------------------------------------------------------------------
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class GameEvent : ScriptableObject
{
private readonly List<GameEventListener> eventListeners = new List<GameEventListener>();
public void Raise()
{
Debug.Log("eventListener: " + eventListeners.Count);
for (int i = eventListeners.Count -1; i >= 0; i--)
eventListeners[i].OnEventRaised();
}
public void RegisterListener(GameEventListener listener)
{
if (!eventListeners.Contains(listener))
eventListeners.Add(listener);
}
public void UnregisterListener(GameEventListener listener)
{
if (eventListeners.Contains(listener))
eventListeners.Remove(listener);
}
}
… and the GameEventListener:
// ----------------------------------------------------------------------------
// Unite 2017 - Game Architecture with Scriptable Objects
//
// Author: Ryan Hipple
// Date: 10/04/17
// ----------------------------------------------------------------------------
using UnityEngine;
using UnityEngine.Events;
public class GameEventListener : MonoBehaviour
{
[Tooltip("Event to register with.")]
public GameEvent Event;
[Tooltip("Response to invoke when Event is raised.")]
public UnityEvent Response;
private void OnEnable()
{
Event.RegisterListener(this);
}
private void OnDisable()
{
Event.UnregisterListener(this);
}
public void OnEventRaised()
{
Response.Invoke();
}
}
It works perfectly as long as the whole cycle is kept in the same scene but, if I move the trigger to a different scene, the event is not added to the list and the GameEvent is not activated:
Couple things you can check. Make sure that your scriptable object reference is the same in both objects. Make sure that you are subscribing before invoking the event. Your code has nothing wrong, just tested it and it is working as expected here Test2 is an additive scene:
Test1 invoked the event (After a delay to make sure Test2 was loaded) and both received it
Thanks for reply.
Yes, scriptableObjects references are the same.
How can I asure registry the event by code before call it?
I’ve gotten it to work by calling the Raise function from a button.OnClick event, but I can’t get it to work by calling Raise() from code.
How is it possible? From the button, the event is registered. From the code, no. Same code(GameEvent.Raise())
I have put all kinds of delays but neither.
Probably the weirdest thing I’ve seen so far.
Any idea?
Well, since you load the other scene additively, when exactly do you load that scene and when is the event actually raised? I would start adding some Debug.Logs in the OnEnable / OnDisable callbacks so you know when a receiver register / unregister itself. So you should see the order in the console. Maybe your receiver was not loaded or enabled at the time the event was raised? Keep in mind that Debug.Log has a second argument where you can pass a context object that is linked to the log message. When you click on the message in the console, the Unity editor will highlight / ping that context object. This makes it much easier to track down who is actually referencing whom.
It’s hard to tell from your code. As @Rotary-Heart has tested your code and it works, there has to be something different on your side that you haven’t shared.
Yes I solved but don’t remember how. It was something about the instance of the scriptable object. When you create and event in a different scene, you are not calling the scriptable object but a new instance of the scriptable object. Somehow you have to manage to call the original SO. I don’t remember how.
Sorry not been more helpful.
Thanks for the reply, I finally debugged the issue and resolved it. I was using scriptable objects as event system along with addressables, and I was not marking SO as addressables which was causing the issue. After marking it as addressable it resolved the issue.