#Event System (Scriptable Object) with multiplayer
1 messages · Page 1 of 1 (latest)
Bank.cs
public class Bank : MonoBehaviour
{
[Header("Events")]
[SerializeField]
public GameEvent onOpenBankChanged;
void Update() {
if(Input.GetKeyDown(KeyCode.Space)) {
Debug.Log("Player: " + this);
OpenBank(this);
}
}
public void OpenBank(Component sender) {
Debug.Log("Bank opened by: " + sender.gameObject.name);
// THIS SHOWS THE BANK (cube)
if(onOpenBankChanged != null) {
onOpenBankChanged.Raise(sender);
}
}
}
GameEvents.cs
[CreateAssetMenu(fileName = "GameEvent", menuName = "Events/Game Event")]
public class GameEvent : ScriptableObject
{
private readonly List<IGameEventListener> m_eventListeners = new List<IGameEventListener>();
public void Raise(Component sender) {
foreach(var listener in m_eventListeners) {
listener.OnEventRaised(sender);
}
}
public void RegisterListener(IGameEventListener listener) {
if(!m_eventListeners.Contains(listener))
m_eventListeners.Add(listener);
}
public void UnregisterListener(IGameEventListener listener) {
if(m_eventListeners.Contains(listener))
m_eventListeners.Remove(listener);
}
}
And GameEventListener:
public class GameEventListener : MonoBehaviour, IGameEventListener {
[Tooltip("Game event to listen to")]
[SerializeField] private GameEvent @event;
[Tooltip("Response to invoke when Event is raised")]
[SerializeField] private UnityEvent response;
public void OnEnable() {
if(@event != null) @event.RegisterListener(this);
}
public void OnDisable() {
@event.UnregisterListener(this);
}
public void OnEventRaised(Component sender) {
response?.Invoke();
}
}
I instance player when they press play (currently singleplayer, but I will reference the player in a better way later):
PlayerSpawnerController:
public class PlayerSpawnController : MonoBehaviour
{
public GameObject _playerPrefab;
// Start is called before the first frame update
void Start()
{
if (Player.Instance == null && _playerPrefab != null)
{
// If no player instance exists and there's a prefab, instantiate the player
GameObject playerObject = Instantiate(_playerPrefab, new Vector3(0, 1, 0), Quaternion.identity);
}
else
{
// If a player instance already exists or no prefab is set, do nothing
Debug.LogWarning("Player instance already exists or player prefab is not set.");
}
}
// Update is called once per frame
void Update()
{
}
}
And the PlayerController contains a navmesh agent and other stuff that makes input work. It's a null object with a name and a camera that follows the player.
So the question is: When the "Player" presses "Space" it will say that the command has been triggered by "Cube" (which in this case is the bank)
Do I need to change my logic here to make it work or should I use some other kind of event based system to make this... work?
So sender == cube is my understanding. But can I somehow fetch the player that has made the command.. Or do I need to add like some other logic here?
There's a null object that contains the event listener that is "global" in the scene that takes care of all the commands being made.
Event System (Scriptable Object) with multiplayer
Wdym by "player that has made the command"?
The "Client" player prefab in this case.
Well, how is your "bank" gonna know that?
I mean, if it's in networking context, you probably have some way to get the local player, but that would depend on the specific networking framework.
Started reading about Netcode for Unity, maybe that's the best start 🥲