Skip to content

Event Aggregator proposal #424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions UOP1_Project/Assets/Prefabs/Characters/PigChef.prefab
Original file line number Diff line number Diff line change
@@ -361,6 +361,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
_inputReader: {fileID: 11400000, guid: 945ec0365077176418488737deed54be, type: 2}
_eventAggregator: {fileID: 11400000, guid: c92bfb91ff27b83459c86d7413b0081a, type: 2}
gameplayCameraTransform: {fileID: 11400000, guid: bc205269957643647a8b5f98f028f9fb,
type: 2}
_openInventoryChannel: {fileID: 11400000, guid: 30f6db2122a30480b996908173e1c7d7,
2 changes: 1 addition & 1 deletion UOP1_Project/Assets/Prefabs/Gameplay/CameraSystem.prefab
Original file line number Diff line number Diff line change
@@ -779,7 +779,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 085156cba0e34b540aeddafe12d1e2f1, type: 3}
m_Name:
m_EditorClassIdentifier:
inputReader: {fileID: 11400000, guid: 945ec0365077176418488737deed54be, type: 2}
eventBus: {fileID: 11400000, guid: b4774447b4f72b8408dbd98248f139ca, type: 2}
mainCamera: {fileID: 8745341642014614481}
freeLookVCam: {fileID: 8745341641394998849}
_speedMultiplier: 0.5
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c3683d4b74c443d4a48ca7b36086f246, type: 3}
m_Name: EventAggregatorSO
m_EditorClassIdentifier:

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions UOP1_Project/Assets/ScriptableObjects/Events/UnityEventBusSO.asset
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c44145970255443c86929d77c7ac2d2a, type: 3}
m_Name: UnityEventBusSO
m_EditorClassIdentifier:

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 15 additions & 14 deletions UOP1_Project/Assets/Scripts/Camera/CameraManager.cs
Original file line number Diff line number Diff line change
@@ -5,13 +5,14 @@

public class CameraManager : MonoBehaviour
{
public InputReader inputReader;
[SerializeField] private UnityEventBusSO eventBus;

public Camera mainCamera;
public CinemachineFreeLook freeLookVCam;
private bool _isRMBPressed;

[SerializeField, Range(.5f, 3f)]
private float _speedMultiplier = 1f; //TODO: make this modifiable in the game settings
private float _speedMultiplier = 1f; //TODO: make this modifiable in the game settings
[SerializeField] private TransformAnchor _cameraTransformAnchor = default;

[Header("Listening on channels")]
@@ -30,9 +31,9 @@ public void SetupProtagonistVirtualCamera(Transform target)

private void OnEnable()
{
inputReader.cameraMoveEvent += OnCameraMove;
inputReader.enableMouseControlCameraEvent += OnEnableMouseControlCamera;
inputReader.disableMouseControlCameraEvent += OnDisableMouseControlCamera;
eventBus.Subscribe<CameraMoveEvent>(OnCameraMove);
eventBus.Subscribe<EnableMouseControlEvent>(OnEnableMouseControlCamera);
eventBus.Subscribe<DisableMouseControlEvent>(OnDisableMouseControlCamera);

if (_frameObjectChannel != null)
_frameObjectChannel.OnEventRaised += OnFrameObjectEvent;
@@ -42,15 +43,15 @@ private void OnEnable()

private void OnDisable()
{
inputReader.cameraMoveEvent -= OnCameraMove;
inputReader.enableMouseControlCameraEvent -= OnEnableMouseControlCamera;
inputReader.disableMouseControlCameraEvent -= OnDisableMouseControlCamera;
eventBus.Unsubscribe<CameraMoveEvent>(OnCameraMove);
eventBus.Unsubscribe<EnableMouseControlEvent>(OnEnableMouseControlCamera);
eventBus.Unsubscribe<DisableMouseControlEvent>(OnDisableMouseControlCamera);

if (_frameObjectChannel != null)
_frameObjectChannel.OnEventRaised -= OnFrameObjectEvent;
}

private void OnEnableMouseControlCamera()
private void OnEnableMouseControlCamera(EnableMouseControlEvent evt)
{
_isRMBPressed = true;

@@ -67,7 +68,7 @@ IEnumerator DisableMouseControlForFrame()
_cameraMovementLock = false;
}

private void OnDisableMouseControlCamera()
private void OnDisableMouseControlCamera(DisableMouseControlEvent evt)
{
_isRMBPressed = false;

@@ -80,16 +81,16 @@ private void OnDisableMouseControlCamera()
freeLookVCam.m_YAxis.m_InputAxisValue = 0;
}

private void OnCameraMove(Vector2 cameraMovement, bool isDeviceMouse)
private void OnCameraMove(CameraMoveEvent moveEvent)
{
if (_cameraMovementLock)
return;

if (isDeviceMouse && !_isRMBPressed)
if (moveEvent.IsDeviceMouse && !_isRMBPressed)
return;

freeLookVCam.m_XAxis.m_InputAxisValue = cameraMovement.x * Time.deltaTime * _speedMultiplier;
freeLookVCam.m_YAxis.m_InputAxisValue = cameraMovement.y * Time.deltaTime * _speedMultiplier;
freeLookVCam.m_XAxis.m_InputAxisValue = moveEvent.Movement.x * Time.deltaTime * _speedMultiplier;
freeLookVCam.m_YAxis.m_InputAxisValue = moveEvent.Movement.y * Time.deltaTime * _speedMultiplier;
}

private void OnFrameObjectEvent(Transform value)
68 changes: 34 additions & 34 deletions UOP1_Project/Assets/Scripts/Characters/Protagonist.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
using System;
using UnityEngine;
using static EventAggregator;

/// <summary>
/// <para>This component consumes input on the InputReader and stores its values. The input is then read, and manipulated, by the StateMachines's Actions.</para>
/// </summary>
public class Protagonist : MonoBehaviour
public class Protagonist : MonoBehaviour,
IHandle<AttackEvent>,
IHandle<JumpEvent>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming here is gorgeous!

IHandle<JumpCancelledEvent>,
IHandle<MoveEvent>,
IHandle<StartedRunningEvent>,
IHandle<StoppedRunningEvent>,
IHandle<OpenInventoryEvent>
{
[SerializeField] private InputReader _inputReader = default;
[SerializeField] private EventAggregatorSO _eventAggregator;

public TransformAnchor gameplayCameraTransform;

[SerializeField] private VoidEventChannelSO _openInventoryChannel = default;
@@ -38,27 +47,13 @@ private void OnControllerColliderHit(ControllerColliderHit hit)
//Adds listeners for events being triggered in the InputReader script
private void OnEnable()
{
_inputReader.jumpEvent += OnJumpInitiated;
_inputReader.jumpCanceledEvent += OnJumpCanceled;
_inputReader.moveEvent += OnMove;
_inputReader.openInventoryEvent += OnOpenInventory;
_inputReader.startedRunning += OnStartedRunning;
_inputReader.stoppedRunning += OnStoppedRunning;
_inputReader.attackEvent += OnStartedAttack;
//...
_eventAggregator.Subscribe(this);
}

//Removes all listeners to the events coming from the InputReader script
private void OnDisable()
{
_inputReader.jumpEvent -= OnJumpInitiated;
_inputReader.jumpCanceledEvent -= OnJumpCanceled;
_inputReader.moveEvent -= OnMove;
_inputReader.openInventoryEvent -= OnOpenInventory;
_inputReader.startedRunning -= OnStartedRunning;
_inputReader.stoppedRunning -= OnStoppedRunning;
_inputReader.attackEvent -= OnStartedAttack;
//...
_eventAggregator.Unsubscribe(this);
}

private void Update()
@@ -107,37 +102,42 @@ private void RecalculateMovement()
_previousSpeed = targetSpeed;
}

//---- EVENT LISTENERS ----
// Triggered from Animation Event
public void ConsumeAttackInput() => attackInput = false;

private void OnMove(Vector2 movement)
public void Handle(AttackEvent msg)
{
_inputVector = movement;
attackInput = true;
}

private void OnJumpInitiated()
public void Handle(JumpEvent msg)
{
jumpInput = true;
}

private void OnJumpCanceled()
public void Handle(JumpCancelledEvent msg)
{
jumpInput = false;
}

private void OnStoppedRunning() => isRunning = false;

private void OnStartedRunning() => isRunning = true;

private void OnOpenInventory()
public void Handle(MoveEvent msg)
{
_openInventoryChannel.RaiseEvent();


_inputVector = msg.Movement;
}

public void Handle(StartedRunningEvent msg)
{
isRunning = true;
}

private void OnStartedAttack() => attackInput = true;
public void Handle(StoppedRunningEvent msg)
{
isRunning = false;
}

// Triggered from Animation Event
public void ConsumeAttackInput() => attackInput = false;
public void Handle(OpenInventoryEvent msg)
{ // Clearly this event should be handled elsewhere and not on the
// protagonist but for now limited changes.
_openInventoryChannel.RaiseEvent();
}
}
142 changes: 142 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/EventAggregator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;


/// <summary>
/// Enables loose coupling of events from publishers to subscribers
///
/// inspired from https://github.com/Caliburn-Micro/Caliburn.Micro/blob/master/src/Caliburn.Micro.Core/IEventAggregator.cs
/// and also https://github.com/google/guava/blob/master/guava/src/com/google/common/eventbus/EventBus.java
///
/// Runs within single threaded unity environment so no need to lock any structures.
/// There is no current requirement to dispatch or consume events asynchronously and sync with unity main thread.
/// </summary>
public interface IEventAggregator
{
void Subscribe(object observer);

void Unsubscribe(object observer);

void Publish(object msg);
}

public class EventAggregator : IEventAggregator
{
private readonly Dictionary<Type, HashSet<Handler>> _handlers = new Dictionary<Type, HashSet<Handler>>();
private readonly Dictionary<object, Subscriptions> _subByObserver = new Dictionary<object, Subscriptions>();
private readonly object[] _paramHolder = {null};

public void Subscribe(object observer)
{
if (observer == null)
{
throw new ArgumentNullException(nameof(observer));
}

if (_subByObserver.ContainsKey(observer))
{
return;
}

var subs = new Subscriptions();

var interfaces = observer.GetType().GetTypeInfo().ImplementedInterfaces
.Where(x => x.GetTypeInfo().IsGenericType && x.GetGenericTypeDefinition() == typeof(IHandle<>));

foreach (var @interface in interfaces)
{
var type = @interface.GetTypeInfo().GenericTypeArguments[0];
var method = @interface.GetRuntimeMethod("Handle", new[] {type});

if (method != null)
{
var handler = new Handler(method, observer);

if (!_handlers.TryGetValue(type, out var handlers))
{
handlers = new HashSet<Handler>();
_handlers[type] = handlers;
}

handlers.Add(handler);
subs.Interested[type] = handler;
}
}

if (subs.Interested.Count > 0)
{
_subByObserver[observer] = subs;
}
}

public void Unsubscribe(object observer)
{
if (observer == null)
{
throw new ArgumentNullException(nameof(observer));
}


if (_subByObserver.TryGetValue(observer, out var subscriptions))
{
_subByObserver.Remove(observer);

foreach (var entry in subscriptions.Interested)
{
if (_handlers.TryGetValue(entry.Key, out var handlers))
{
handlers.Remove(entry.Value);
}
}
}
}

public void Publish(object msg)
{
if (msg == null)
{
throw new ArgumentNullException(nameof(msg));
}

if (_handlers.TryGetValue(msg.GetType(), out var handlers))
{
_paramHolder[0] = msg;

foreach (var handler in handlers)
{
handler.Notify(_paramHolder);
}
}
}

private class Subscriptions
{
private readonly Dictionary<Type, Handler> _interested = new Dictionary<Type, Handler>();

public Dictionary<Type, Handler> Interested => _interested;
}

private class Handler
{
private readonly MethodInfo _method;
private readonly object _observer;

public Handler(MethodInfo method, object observer)
{
_method = method;
_observer = observer;
}

public void Notify(object[] param)
{
_method.Invoke(_observer, param);
}
}

public interface IHandle<T>
{
void Handle(T msg);
}
}
11 changes: 11 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/EventAggregator.cs.meta
3 changes: 3 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/Input.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class AttackCancelledEvent
{
public static readonly AttackCancelledEvent Event = new AttackCancelledEvent();
}
4 changes: 4 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/Input/AttackEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class AttackEvent
{
public static readonly AttackEvent Event = new AttackEvent();
}
3 changes: 3 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/Input/AttackEvent.cs.meta
7 changes: 7 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/Input/CameraMoveEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using UnityEngine;

public class CameraMoveEvent
{
public Vector2 Movement { get; set; }
public bool IsDeviceMouse { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class DisableMouseControlEvent
{
public static readonly DisableMouseControlEvent Event = new DisableMouseControlEvent();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class EnableMouseControlEvent
{
public static readonly EnableMouseControlEvent Event = new EnableMouseControlEvent();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class JumpCancelledEvent
{
public static readonly JumpCancelledEvent Event = new JumpCancelledEvent();
}
4 changes: 4 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/Input/JumpEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class JumpEvent
{
public static readonly JumpEvent Event = new JumpEvent();
}
3 changes: 3 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/Input/JumpEvent.cs.meta
6 changes: 6 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/Input/MoveEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using UnityEngine;

public class MoveEvent
{
public Vector2 Movement { get; set; }
}
3 changes: 3 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/Input/MoveEvent.cs.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class OpenInventoryEvent
{
public static readonly OpenInventoryEvent Event = new OpenInventoryEvent();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class StartedRunningEvent
{
public static readonly StartedRunningEvent Event = new StartedRunningEvent();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class StoppedRunningEvent
{
public static readonly StoppedRunningEvent Event = new StoppedRunningEvent();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using UnityEngine;

[CreateAssetMenu(fileName = "EventAggregatorSO", menuName = "Events/Event Aggregator")]
public class EventAggregatorSO : ScriptableObject, IEventAggregator
{
private readonly EventAggregator _eventAggregator = new EventAggregator();

public void Subscribe(object observer)
{
_eventAggregator.Subscribe(observer);
}

public void Unsubscribe(object observer)
{
_eventAggregator.Unsubscribe(observer);
}

public void Publish(object msg)
{
_eventAggregator.Publish(msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using UnityEngine;
using UnityEngine.Events;

[CreateAssetMenu(fileName = "UnityEventBusSO", menuName = "Events/Unity Event Bus")]
public class UnityEventBusSO : ScriptableObject, IUnityEventBus
{
private readonly UnityEventBus _unityEventBus = new UnityEventBus();

public void Subscribe<T>(UnityAction<T> action)
{
_unityEventBus.Subscribe(action);
}

public void Unsubscribe<T>(UnityAction<T> action)
{
_unityEventBus.Unsubscribe(action);
}

public void Publish<T>(T msg)
{
_unityEventBus.Publish(msg);
}
}
76 changes: 76 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/UnityEventBus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.Events;

/// <summary>
/// Enables loose coupling of events from publishers to subscribers
///
/// A UnityAction based subscription where the T is event type used to find
/// a suitable UnityAction.
///
/// Note the code is typesafe although somewhat ugly with HashSet<object> holder.
///
/// </summary>
public interface IUnityEventBus
{
public void Subscribe<T>(UnityAction<T> action);

public void Unsubscribe<T>(UnityAction<T> action);

public void Publish<T>(T msg);
}

public class UnityEventBus : IUnityEventBus
{
private readonly Dictionary<Type, HashSet<object>> _handlers = new Dictionary<Type, HashSet<object>>();

public void Subscribe<T>(UnityAction<T> action)
{
if (action == null)
{
throw new ArgumentNullException(nameof(action));
}

var type = typeof(T);

if (!_handlers.TryGetValue(type, out var handlers))
{
handlers = new HashSet<object>();
_handlers[type] = handlers;
}

handlers.Add(action);
}

public void Unsubscribe<T>(UnityAction<T> action)
{
if (action == null)
{
throw new ArgumentNullException(nameof(action));
}

var type = typeof(T);

if (_handlers.TryGetValue(type, out var handlers))
{
handlers.Remove(action);
}
}

public void Publish<T>(T msg)
{
if (msg == null)
{
throw new ArgumentNullException(nameof(msg));
}

if (_handlers.TryGetValue(msg.GetType(), out var handlers))
{
foreach (var handler in handlers.Cast<UnityAction<T>>())
{
handler.Invoke(msg);
}
}
}
}
3 changes: 3 additions & 0 deletions UOP1_Project/Assets/Scripts/Events/UnityEventBus.cs.meta
68 changes: 38 additions & 30 deletions UOP1_Project/Assets/Scripts/Input/InputReader.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
using UnityEngine;
using System;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Events;

[CreateAssetMenu(fileName = "InputReader", menuName = "Game/Input Reader")]
public class InputReader : ScriptableObject, GameInput.IGameplayActions, GameInput.IDialoguesActions, GameInput.IMenusActions
{
[SerializeField] private EventAggregatorSO eventAggregator;

[SerializeField] private UnityEventBusSO eventBus;

private readonly MoveEvent _moveEvent = new MoveEvent();
private readonly CameraMoveEvent _cameraMoveEvent = new CameraMoveEvent();

// Assign delegate{} to events to initialise them with an empty delegate
// so we can skip the null check when we use them

// Gameplay
public event UnityAction jumpEvent = delegate { };
public event UnityAction jumpCanceledEvent = delegate { };
public event UnityAction attackEvent = delegate { };
public event UnityAction attackCanceledEvent = delegate { };
public event UnityAction interactEvent = delegate { }; // Used to talk, pickup objects, interact with tools like the cooking cauldron
public event UnityAction openInventoryEvent = delegate { }; // Used to bring up the inventory
public event UnityAction closeInventoryEvent = delegate { };// Used to bring up the inventory
public event UnityAction inventoryActionButtonEvent = delegate { };
public event UnityAction pauseEvent = delegate { };
public event UnityAction<Vector2> moveEvent = delegate { };
public event UnityAction<Vector2, bool> cameraMoveEvent = delegate { };
public event UnityAction enableMouseControlCameraEvent = delegate { };
public event UnityAction disableMouseControlCameraEvent = delegate { };
public event UnityAction startedRunning = delegate { };
public event UnityAction stoppedRunning = delegate { };

// Shared between menus and dialogues
public event UnityAction moveSelectionEvent = delegate { };
@@ -65,18 +62,18 @@ public void OnAttack(InputAction.CallbackContext context)
switch (context.phase)
{
case InputActionPhase.Performed:
attackEvent.Invoke();
eventAggregator.Publish(AttackEvent.Event);
break;
case InputActionPhase.Canceled:
attackCanceledEvent.Invoke();
eventAggregator.Publish(AttackCancelledEvent.Event);
break;
}
}

public void OnOpenInventory(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed)
openInventoryEvent.Invoke();
eventAggregator.Publish(OpenInventoryEvent.Event);
}
public void OnCancel(InputAction.CallbackContext context)
{
@@ -100,27 +97,32 @@ public void OnInteract(InputAction.CallbackContext context)

public void OnJump(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed)
jumpEvent.Invoke();

if (context.phase == InputActionPhase.Canceled)
jumpCanceledEvent.Invoke();
switch (context.phase)
{
case InputActionPhase.Performed:
eventAggregator.Publish(JumpEvent.Event);
break;
case InputActionPhase.Canceled:
eventAggregator.Publish(JumpCancelledEvent.Event);
break;
}
}

public void OnMove(InputAction.CallbackContext context)
{
moveEvent.Invoke(context.ReadValue<Vector2>());
_moveEvent.Movement = context.ReadValue<Vector2>();
eventAggregator.Publish(_moveEvent);
}

public void OnRun(InputAction.CallbackContext context)
{
switch (context.phase)
{
case InputActionPhase.Performed:
startedRunning.Invoke();
eventAggregator.Publish(StartedRunningEvent.Event);
break;
case InputActionPhase.Canceled:
stoppedRunning.Invoke();
eventAggregator.Publish(StoppedRunningEvent.Event);
break;
}
}
@@ -133,16 +135,22 @@ public void OnPause(InputAction.CallbackContext context)

public void OnRotateCamera(InputAction.CallbackContext context)
{
cameraMoveEvent.Invoke(context.ReadValue<Vector2>(), IsDeviceMouse(context));
_cameraMoveEvent.Movement = context.ReadValue<Vector2>();
_cameraMoveEvent.IsDeviceMouse = IsDeviceMouse(context);
eventBus.Publish(_cameraMoveEvent);
}

public void OnMouseControlCamera(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed)
enableMouseControlCameraEvent.Invoke();

if (context.phase == InputActionPhase.Canceled)
disableMouseControlCameraEvent.Invoke();
switch (context.phase)
{
case InputActionPhase.Performed:
eventBus.Publish(EnableMouseControlEvent.Event);
break;
case InputActionPhase.Canceled:
eventBus.Publish(DisableMouseControlEvent.Event);
break;
}
}

private bool IsDeviceMouse(InputAction.CallbackContext context) => context.control.device.name == "Mouse";
@@ -216,7 +224,7 @@ public void DisableAllInput()
public void OnChangeTab(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed)
menuSwitchTab.Invoke(context.ReadValue<float>());
menuSwitchTab.Invoke(context.ReadValue<float>());

}