├── .gitignore ├── Assets ├── Plugins.meta ├── Plugins │ └── Editor.meta ├── UnityEvents.meta └── UnityEvents │ ├── Examples.meta │ ├── Examples │ ├── Advance.meta │ ├── Advance │ │ ├── ExampleCustomEventSystem.cs │ │ ├── ExampleCustomEventSystem.cs.meta │ │ ├── ExampleCustomTickEventSystem.cs │ │ ├── ExampleCustomTickEventSystem.cs.meta │ │ ├── ExampleEntityTargetReservations.cs │ │ ├── ExampleEntityTargetReservations.cs.meta │ │ ├── ExampleHandlers.cs │ │ └── ExampleHandlers.cs.meta │ ├── Simple.meta │ ├── Simple │ │ ├── ExampleSimple.cs │ │ ├── ExampleSimple.cs.meta │ │ ├── ExampleSimpleJob.cs │ │ └── ExampleSimpleJob.cs.meta │ ├── UnityEvents.Example.asmdef │ └── UnityEvents.Example.asmdef.meta │ ├── Scripts.meta │ ├── Scripts │ ├── EventHandlerJob.cs │ ├── EventHandlerJob.cs.meta │ ├── EventHandlerStandard.cs │ ├── EventHandlerStandard.cs.meta │ ├── EventManager.cs │ ├── EventManager.cs.meta │ ├── EventTarget.cs │ ├── EventTarget.cs.meta │ ├── GameObjectEventSystem.cs │ ├── GameObjectEventSystem.cs.meta │ ├── GlobalEventSystem.cs │ ├── GlobalEventSystem.cs.meta │ ├── Internal.meta │ ├── Internal │ │ ├── UnityEventsExceptions.cs │ │ ├── UnityEventsExceptions.cs.meta │ │ ├── UnityEventsInterfaces.cs │ │ ├── UnityEventsInterfaces.cs.meta │ │ ├── UnityEventsMisc.cs │ │ └── UnityEventsMisc.cs.meta │ ├── TickEventSystem.cs │ ├── TickEventSystem.cs.meta │ ├── UnityEventSystem.cs │ ├── UnityEventSystem.cs.meta │ ├── UnityEvents.asmdef │ └── UnityEvents.asmdef.meta │ ├── Tests.meta │ └── Tests │ ├── TestEventManager.cs │ ├── TestEventManager.cs.meta │ ├── TestEventTarget.cs │ ├── TestEventTarget.cs.meta │ ├── TestGameObjectEventSystemJob.cs │ ├── TestGameObjectEventSystemJob.cs.meta │ ├── TestGameObjectEventSystemStandard.cs │ ├── TestGameObjectEventSystemStandard.cs.meta │ ├── TestGameObjectUIEventSystemJob.cs │ ├── TestGameObjectUIEventSystemJob.cs.meta │ ├── TestGameObjectUIEventSystemStandard.cs │ ├── TestGameObjectUIEventSystemStandard.cs.meta │ ├── TestGlobalEventSystemJob.cs │ ├── TestGlobalEventSystemJob.cs.meta │ ├── TestGlobalEventSystemStandard.cs │ ├── TestGlobalEventSystemStandard.cs.meta │ ├── TestGlobalUIEventSystemJob.cs │ ├── TestGlobalUIEventSystemJob.cs.meta │ ├── TestGlobalUIEventSystemStandard.cs │ ├── TestGlobalUIEventSystemStandard.cs.meta │ ├── TestUnityEventJobSystem.cs │ ├── TestUnityEventJobSystem.cs.meta │ ├── TestUnityEventStandardSystem.cs │ ├── TestUnityEventStandardSystem.cs.meta │ ├── TestUnityEventsMisc.cs │ ├── TestUnityEventsMisc.cs.meta │ ├── UnityEvents.Test.asmdef │ └── UnityEvents.Test.asmdef.meta ├── LICENSE ├── Packages └── manifest.json ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── PresetManager.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset ├── UnityConnectSettings.asset └── VFXManager.asset └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # =============== # 2 | # Unity generated # 3 | # =============== # 4 | [Tt]emp/ 5 | [Oo]bj/ 6 | [Bb]uild/ 7 | [Ll]ibrary/ 8 | sysinfo.txt 9 | .app 10 | 11 | # ===================================== # 12 | # Visual Studio / MonoDevelop generated # 13 | # ===================================== # 14 | [Ee]xported[Oo]bj/ 15 | *.userprefs 16 | *.csproj 17 | *.csproj.meta 18 | *.pidb 19 | *.suo 20 | *.sln* 21 | *.user 22 | *.unityproj 23 | *.booproj 24 | .vscode/ 25 | VSCode* 26 | VSCode/ 27 | .vs/ 28 | 29 | # ============ # 30 | # OS generated # 31 | # ============ # 32 | .DS_Store* 33 | ._* 34 | .Spotlight-V100 35 | .Trashes 36 | *Icon? 37 | *Icon?.meta 38 | ehthumbs.db 39 | [Tt]humbs.db 40 | 41 | # ========== # 42 | # Plugins # 43 | # ========== # 44 | UnityVS/ 45 | *UnityVS.meta 46 | BIU/ 47 | BIU.meta 48 | AutoSaver/ 49 | AutoSaver.meta 50 | GeneratedOdinEditors.dll* 51 | Assets/External/Sirenix/Assemblies/Editor/ 52 | Assets/External/Sirenix/Assemblies/Editor.meta 53 | 54 | # ======= # 55 | # FMOD # 56 | # ======= # 57 | /Assets/FMODStudioCache.asset 58 | /Assets/FMODStudioCache.asset.meta 59 | fmod.log 60 | fmod_editor.log 61 | !Assets/FMOD/StreamingAssets/fmod_audio/Build 62 | 63 | # ======= # 64 | # Other # 65 | # ======= # 66 | out/ 67 | logs/ 68 | build-process/ 69 | sdks/steamworks_sdk_142/tools/ContentBuilder/content/ 70 | sdks/build_loader/ 71 | 72 | .* 73 | !/.gitignore 74 | !/Assets/PlayFabEditorExtensions/Editor/Resources/.CloudScript.js 75 | Assets/Plugins/Editor/JetBrains/ 76 | Assets/Plugins/Editor/JetBrains.meta 77 | -------------------------------------------------------------------------------- /Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec540725aa24fff43b68bf5d4c17b0d1 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82fd2ede500ba7c49be58b4680b82750 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/UnityEvents.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d982b2eb55bf6a344b31e48da429d742 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d7b7b88763a933443aa8dfb2b3c031bf 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Advance.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3f451b97248702849bb0dd9f13c11730 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Advance/ExampleCustomEventSystem.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace UnityEvents.Example 4 | { 5 | /// 6 | /// Example of using an event system that isn't controlled by any of the update ticks. Events will only be processed 7 | /// when told to be processed. 8 | /// 9 | /// IF YOU ARE OK WITH EVENTS BEING PROCESSED IN FIXED UPDATE, UPDATE, OR LATE UPDATE then use TickEventSystem 10 | /// (example in ExampleCustomTickEventSystem.cs) as it will allow better subscription/event batching and will be more 11 | /// performant. ONLY IF you literally want to control when a system has it's events processed is when you would use 12 | /// the example in this file. 13 | /// 14 | public class ExampleCustomEventSystem 15 | { 16 | // This system will allow subscribers and events to be queued. Events have to be told when to process isntead 17 | // of happening automatically in a tick. The example will only show regular events but this can handle both. 18 | // See ExampleSimpleJob.cs for a job example. 19 | private UnityEventSystem _system = new UnityEventSystem(); 20 | 21 | // I have to be an unmanaged type! Need references? Use an id and have a lookup database system. 22 | private struct EvExampleEvent 23 | { 24 | public int exampleValue; 25 | 26 | public EvExampleEvent(int exampleValue) 27 | { 28 | this.exampleValue = exampleValue; 29 | } 30 | } 31 | 32 | public void UseCustomSystem() 33 | { 34 | // Event systems are associated with an EventTarget, this is how an event system can know who to send 35 | // an event to but keep all events together for performance. 36 | // 37 | // For example the global sim event system is its own EventTarget. As is the Global UI system and each 38 | // GameObject is converted to an EventTarget. 39 | // 40 | // It is better to use a single UnityEventSystem with multiple entities than an UnityEventSystem for each 41 | // target. For example if there are multiple 'global' systems that all get processed at the same time then 42 | // it is more performant to have a single UnityEventSystem and an EventTarget for each 'global system' that 43 | // talk to the same UnityEventSystem. 44 | // 45 | // GlobalEventSystem, GameObject systems, and TickEventSystem all use EventManager which uses one UnityEventSystem 46 | // for each update tick. 47 | EventTarget target1 = EventTarget.CreateTarget(); 48 | EventTarget target2 = EventTarget.CreateTarget(); 49 | 50 | // Can subscribe a listener to both entities 51 | _system.Subscribe(target1, OnExampleEvent); 52 | _system.Subscribe(target2, OnExampleEventDoublePrint); 53 | 54 | // We queue up events, avoided the 'send' verb here since we have to manually process the events. 55 | _system.QueueEvent(target1, new EvExampleEvent(1)); 56 | 57 | // Now we process the queued events. Since we only sent an event to the entity1 system, the listener to entity2 58 | // will NOT invoke. 59 | _system.ProcessEvents(); 60 | 61 | // Each listener needs to unsubscribe from the appropriate event entity 62 | _system.Unsubscribe(target1, OnExampleEvent); 63 | _system.Unsubscribe(target2, OnExampleEventDoublePrint); 64 | 65 | // To have a global system that you control just store an EventEntity and use that. 66 | } 67 | 68 | private void OnExampleEvent(EvExampleEvent ev) 69 | { 70 | Debug.Log("Event received! Value: " + ev.exampleValue); 71 | } 72 | 73 | private void OnExampleEventDoublePrint(EvExampleEvent ev) 74 | { 75 | Debug.Log("Event received! Value: " + ev.exampleValue); 76 | Debug.Log("Event received! Value: " + ev.exampleValue); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Advance/ExampleCustomEventSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1cfdaae08c2e5c845b40fdcc6fa1ed3a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Advance/ExampleCustomTickEventSystem.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace UnityEvents.Example 4 | { 5 | /// 6 | /// Example of using a custom event system that send events on an update tick. This could be used to create custom 7 | /// local event system and custom global event system. GlobalEventSystem is a static class that holds a tick 8 | /// based event system for simulation and ui and passes subscriptions/events through it. 9 | /// 10 | public class ExampleCustomTickEventSystem 11 | { 12 | // This system will process events in the Update tick. The example will only show regular events but this can 13 | // handle both. See ExampleSimpleJob.cs for a job example. 14 | private TickEventSystem _system = new TickEventSystem(EventUpdateTick.Update); 15 | 16 | // I have to be an unmanaged type! Need references? Use an id and have a lookup database system. 17 | private struct EvExampleEvent 18 | { 19 | public int exampleValue; 20 | 21 | public EvExampleEvent(int exampleValue) 22 | { 23 | this.exampleValue = exampleValue; 24 | } 25 | } 26 | 27 | public void UseCustomSystem() 28 | { 29 | // Subscribe to the custom event system 30 | _system.Subscribe(OnExampleEvent); 31 | 32 | // Can send an event to it. This will be processed in the Update loop. 33 | _system.SendEvent(new EvExampleEvent(10)); 34 | 35 | // And unsubscribe from it 36 | _system.Unsubscribe(OnExampleEvent); 37 | } 38 | 39 | private void OnExampleEvent(EvExampleEvent ev) 40 | { 41 | Debug.Log("Event received! Value: " + ev.exampleValue); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Advance/ExampleCustomTickEventSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ee112101c292c8242800ff1209fd6d08 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Advance/ExampleEntityTargetReservations.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace UnityEvents.Example 6 | { 7 | public class ExampleEntityTargetReservations 8 | { 9 | public void ReserveEntityTargets() 10 | { 11 | // See ExampleCustomEventSystem for a description of what EventTarget are and how they could be 12 | // used. Also see EventTarget.cs 13 | 14 | // Reservations allow us to reserve a block of event targets for us to use however way we see fit. Will 15 | // prevent EventTarget from giving out targets within that reservation on EventTarget creation or other' 16 | // reservations. 17 | EventTargetReservation reservation = EventTarget.ReserveTargets(100); 18 | 19 | // Grabs an EventTarget by index 20 | EventTarget target0 = reservation.GetEntityTarget(0); 21 | EventTarget target50 = reservation.GetEntityTarget(50); 22 | 23 | // Throws an error if outside the reservation (if checks are enabled) 24 | EventTarget target200 = reservation.GetEntityTarget(200); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Advance/ExampleEntityTargetReservations.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eff85f34ce9a5fd4088b1e17e2e041b9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Advance/ExampleHandlers.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEvents.Internal; 3 | 4 | namespace UnityEvents.Example 5 | { 6 | /// 7 | /// Example of using event handlers directly. Similar to UnityEventSystem but only works for a specific event. 8 | /// Can be used to only allow a single event. 9 | /// 10 | public class ExampleHandlers 11 | { 12 | private EventHandlerStandard _standardHandler = new EventHandlerStandard(); 13 | private EventHandlerJob _jobHandler = new EventHandlerJob(); 14 | 15 | // I have to be an unmanaged type! Need references? Use an id and have a lookup database system. 16 | private struct EvExampleEvent 17 | { 18 | public int exampleValue; 19 | 20 | public EvExampleEvent(int exampleValue) 21 | { 22 | this.exampleValue = exampleValue; 23 | } 24 | } 25 | 26 | private struct ExampleJob : IJobForEvent 27 | { 28 | // This result is stored across jobs, wipe it out at the beginning of each job if this isn't wanted! 29 | public int result; 30 | 31 | public void ExecuteEvent(EvExampleEvent ev) 32 | { 33 | result += ev.exampleValue; 34 | } 35 | } 36 | 37 | public void StandardHandlerExample() 38 | { 39 | // Handlers ultimately are what store the subscriptions and process events. Ideally they shouldn't need 40 | // to be used directly and TickEventSystem and UnityEventSystem would be sufficient in most cases. 41 | 42 | // See ExampleControlledEventSystem.cs for a description on EventEntities. 43 | EventTarget target = EventTarget.CreateTarget(); 44 | 45 | // Subscribe, Unsubscribe, and Events will seem familiar but can ONLY use EvExampleEvent. Doesn't work for 46 | // all events. 47 | _standardHandler.Subscribe(target, OnExampleEvent); 48 | 49 | // Handlers have to be told to process events so we queue an event and process it later. 50 | _standardHandler.QueueEvent(target, new EvExampleEvent(7777)); 51 | _standardHandler.ProcessEvents(); 52 | 53 | _standardHandler.Unsubscribe(target, OnExampleEvent); 54 | 55 | // There's a job handler as well, they are separate and won't fire on the same events 56 | _jobHandler.Subscribe(target, new ExampleJob(), OnJobFinished); 57 | _jobHandler.QueueEvent(target, new EvExampleEvent(111)); 58 | _jobHandler.ProcessEvents(); 59 | _jobHandler.Unsubscribe(target, OnJobFinished); 60 | 61 | } 62 | 63 | private void OnExampleEvent(EvExampleEvent ev) 64 | { 65 | Debug.Log("Event received! Value: " + ev.exampleValue); 66 | } 67 | 68 | private void OnJobFinished(ExampleJob ev) 69 | { 70 | Debug.Log("Job finished! Value: " + ev.result); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Advance/ExampleHandlers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d1c5fd7ff58a51947b92284c95ba58cc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Simple.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5810ca7e6d141a049bb4d349ccc3b759 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Simple/ExampleSimple.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEvents.Internal; 3 | 4 | namespace UnityEvents.Example 5 | { 6 | /// 7 | /// Simple example of using the global and GameObject event systems 8 | /// 9 | public class ExampleSimple : MonoBehaviour 10 | { 11 | // I have to be an unmanaged type! Need references? Use an id and have a lookup database system. 12 | private struct EvExampleEvent 13 | { 14 | public int exampleValue; 15 | 16 | public EvExampleEvent(int exampleValue) 17 | { 18 | this.exampleValue = exampleValue; 19 | } 20 | } 21 | 22 | private void OnEnable() 23 | { 24 | // Subscribes to the global event system, handles events in FixedUpdate 25 | GlobalEventSystem.Subscribe(OnExampleEvent); 26 | 27 | // Subscribes to THIS GameObject's event system! Also Fixed Update 28 | gameObject.Subscribe(OnExampleEvent); 29 | 30 | // Is the game paused but still need events for UI? There's a global UI system. Handles events in 31 | // LateUpdate 32 | GlobalEventSystem.SubscribeUI(OnExampleEvent); 33 | 34 | // There's also local event system for each GameObject that run in LateUpdate. 35 | gameObject.SubscribeUI(OnExampleEvent); 36 | } 37 | 38 | private void OnDisable() 39 | { 40 | // Should always unsubscribe 41 | 42 | // Unsubscribe from the global system 43 | GlobalEventSystem.Unsubscribe(OnExampleEvent); 44 | gameObject.Unsubscribe(OnExampleEvent); 45 | 46 | GlobalEventSystem.UnsubscribeUI(OnExampleEvent); 47 | gameObject.UnsubscribeUI(OnExampleEvent); 48 | } 49 | 50 | public void SendEvents() 51 | { 52 | // Send an event to the global event system, will be processed in the next FixedUpdate 53 | GlobalEventSystem.SendEvent(new EvExampleEvent(10)); 54 | 55 | // Send an event to a specific GameObject, only listeners subscribed to that gameobject will get 56 | // this event. Also will be processed in the next FixedUpdate 57 | gameObject.SendEvent(new EvExampleEvent(99)); 58 | 59 | // Can send events to the global UI event system. These will be processed in LateUpdate which allows the 60 | // game to paused. 61 | GlobalEventSystem.SendEventUI(new EvExampleEvent(-1)); 62 | 63 | // Similarly can send to a specific GameObject to be processed in LateUpdate 64 | gameObject.SendEventUI(new EvExampleEvent(999999)); 65 | } 66 | 67 | private void OnExampleEvent(EvExampleEvent ev) 68 | { 69 | Debug.Log("Event received! Value: " + ev.exampleValue); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Simple/ExampleSimple.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 02f30ee5572dba9409e6c62a404fb9df 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Simple/ExampleSimpleJob.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEvents.Internal; 3 | 4 | namespace UnityEvents.Example 5 | { 6 | /// 7 | /// Simple example of using jobs with the event system 8 | /// 9 | public class ExampleSimpleJob : MonoBehaviour 10 | { 11 | // I have to be an unmanaged type! Need references? Use an id and have a lookup database system. 12 | private struct EvExampleEvent 13 | { 14 | public int exampleValue; 15 | 16 | public EvExampleEvent(int exampleValue) 17 | { 18 | this.exampleValue = exampleValue; 19 | } 20 | } 21 | 22 | private struct ExampleJob : IJobForEvent 23 | { 24 | // This result is stored across jobs, wipe it out at the beginning of each job if this isn't wanted! 25 | public int result; 26 | 27 | public void ExecuteEvent(EvExampleEvent ev) 28 | { 29 | result += ev.exampleValue; 30 | } 31 | } 32 | 33 | private void OnEnable() 34 | { 35 | // Jobs work with the global simulation and global UI event systems as well as the GameObject system. This 36 | // will just show examples with the global simulation system. 37 | // 38 | // When an event is fired jobs will processed in parallel using the burst compiler. Can make otherwise 39 | // long tasks very short. Afterwards the callback functions are invoked so the listener can use the results 40 | // of the job. 41 | GlobalEventSystem.SubscribeWithJob(new ExampleJob(), OnJobFinished); 42 | } 43 | 44 | private void OnDisable() 45 | { 46 | GlobalEventSystem.UnsubscribeWithJob(OnJobFinished); 47 | } 48 | 49 | public void SendEvents() 50 | { 51 | // Job listeners trigger on events like anything else. You can have job listeners and regular listeners to 52 | // a single event. 53 | GlobalEventSystem.SendEvent(new EvExampleEvent(10)); 54 | } 55 | 56 | private void OnJobFinished(ExampleJob ev) 57 | { 58 | Debug.Log("Job finished! Value: " + ev.result); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/Simple/ExampleSimpleJob.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 49b20d95465d66c49a3748a972bf6d31 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/UnityEvents.Example.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "UnityEvents.Example", 3 | "references": [ 4 | "UnityEvents" 5 | ], 6 | "optionalUnityReferences": [], 7 | "includePlatforms": [ 8 | "Editor" 9 | ], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [] 16 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Examples/UnityEvents.Example.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 197aa132777a36a4bbe5bcf49d007183 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 264256832277bb04fbe0e953b6fe70d6 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/EventHandlerJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Unity.Burst; 4 | using Unity.Collections; 5 | using Unity.Collections.LowLevel.Unsafe; 6 | using Unity.Jobs; 7 | using UnityEngine; 8 | using UnityEvents.Internal; 9 | 10 | namespace UnityEvents 11 | { 12 | /// 13 | /// Event system that processes jobs for events. 14 | /// 15 | /// The job the system is responsible for. 16 | /// The event the system is responsible for. 17 | public class EventHandlerJob : 18 | IJobEventSystem, 19 | IDisposable 20 | where T_Job : struct, IJobForEvent 21 | where T_Event : struct 22 | { 23 | private NativeList> _queuedEvents; 24 | private NativeList _subscribers; 25 | 26 | private List> _subscriberCallbacks; 27 | private Dictionary, int> _entityCallbackToIndex; 28 | 29 | private Dictionary, int> _cachedCurEvents; 30 | 31 | private bool _disposed; 32 | private readonly int _batchCount; 33 | 34 | private const int DEFAULT_EVENTS_TO_PROCESS_CAPACITY = 10; 35 | private const int DEFAULT_SUBSCRIBER_CAPACITY = 100; 36 | private const int DEFAULT_PARALLEL_BATCH_COUNT = 32; 37 | 38 | private struct UnityEventJob 39 | { 40 | public readonly T_Event ev; 41 | public readonly int subscriberIndex; 42 | 43 | public UnityEventJob(T_Event ev, int subscriberIndex) 44 | { 45 | this.ev = ev; 46 | this.subscriberIndex = subscriberIndex; 47 | } 48 | } 49 | 50 | private struct Subscription 51 | { 52 | public EventTarget target; 53 | public T_Job job; 54 | 55 | public Subscription(EventTarget target, T_Job job) 56 | { 57 | this.target = target; 58 | this.job = job; 59 | } 60 | } 61 | 62 | public EventHandlerJob() : this( 63 | DEFAULT_SUBSCRIBER_CAPACITY, 64 | DEFAULT_EVENTS_TO_PROCESS_CAPACITY, 65 | DEFAULT_PARALLEL_BATCH_COUNT) 66 | { 67 | } 68 | 69 | /// 70 | /// Create a system with some custom settings. 71 | /// 72 | /// The starting capacity of subscriber containers. 73 | /// The starting capacity of queued events containers. 74 | /// The batch count allowed per thread for parallel processing. 75 | public EventHandlerJob( 76 | int subscriberStartingCapacity, 77 | int queuedEventsStartingCapacity, 78 | int parallelBatchCount) 79 | { 80 | #if !DISABLE_EVENT_SAFETY_CHKS 81 | if (!UnsafeUtility.IsBlittable()) 82 | { 83 | throw new JobTypeNotBlittableException(typeof(T_Job)); 84 | } 85 | 86 | if (!UnsafeUtility.IsBlittable()) 87 | { 88 | throw new EventTypeNotBlittableException(typeof(T_Event)); 89 | } 90 | #endif 91 | _batchCount = parallelBatchCount; 92 | 93 | _subscribers = new NativeList(subscriberStartingCapacity, Allocator.Persistent); 94 | _subscriberCallbacks = new List>(subscriberStartingCapacity); 95 | _entityCallbackToIndex = new Dictionary, int>(subscriberStartingCapacity); 96 | 97 | _queuedEvents = new NativeList>(queuedEventsStartingCapacity, Allocator.Persistent); 98 | 99 | #if !DISABLE_EVENT_SAFETY_CHKS 100 | _cachedCurEvents = new Dictionary, int>(subscriberStartingCapacity); 101 | #endif 102 | } 103 | 104 | /// 105 | /// Disposes of some internally held state. 106 | /// 107 | public void Dispose() 108 | { 109 | #if !DISABLE_EVENT_SAFETY_CHKS 110 | if (_disposed) 111 | { 112 | _disposed = true; 113 | return; 114 | } 115 | #endif 116 | _queuedEvents.Dispose(); 117 | _subscribers.Dispose(); 118 | } 119 | 120 | /// 121 | /// Subscribe a job to the system. 122 | /// 123 | /// The entity to subscribe to. 124 | /// The job, and initial job state, to process when an event fires. 125 | /// The callback to invoke when a job finishes. 126 | public void Subscribe(EventTarget target, T_Job job, Action onComplete) 127 | { 128 | #if !DISABLE_EVENT_SAFETY_CHKS 129 | if (_entityCallbackToIndex.ContainsKey(new EntityCallbackId(target, onComplete))) 130 | { 131 | throw new MultipleSubscriptionsException(onComplete); 132 | } 133 | #endif 134 | 135 | _entityCallbackToIndex.Add(new EntityCallbackId(target, onComplete), _subscribers.Length); 136 | _subscribers.Add(new Subscription(target, job)); 137 | _subscriberCallbacks.Add(onComplete); 138 | } 139 | 140 | /// 141 | /// Unsubscribe a job from the system. 142 | /// 143 | /// The entity to unsubscribe from. 144 | /// The callback that was invoked when a job finished. 145 | public void Unsubscribe(EventTarget target, Action onComplete) 146 | { 147 | EntityCallbackId callbackId = new EntityCallbackId(target, onComplete); 148 | 149 | if (_entityCallbackToIndex.TryGetValue(callbackId, out int index)) 150 | { 151 | _entityCallbackToIndex.Remove(callbackId); 152 | 153 | _subscribers.RemoveAtSwapBack(index); 154 | 155 | _subscriberCallbacks[index] = _subscriberCallbacks[_subscriberCallbacks.Count - 1]; 156 | _subscriberCallbacks.RemoveAt(_subscriberCallbacks.Count - 1); 157 | 158 | if (index != _subscribers.Length) 159 | { 160 | EntityCallbackId otherCallbackId = new EntityCallbackId( 161 | _subscribers[index].target, 162 | _subscriberCallbacks[index]); 163 | 164 | _entityCallbackToIndex[otherCallbackId] = index; 165 | } 166 | } 167 | } 168 | 169 | /// 170 | /// Queue an event to be processed later. 171 | /// 172 | /// The entity the event is for. 173 | /// The event to queue. 174 | public void QueueEvent(EventTarget target, T_Event ev) 175 | { 176 | QueuedEvent newEv = new QueuedEvent(target, ev); 177 | 178 | #if !DISABLE_EVENT_SAFETY_CHKS 179 | if (_cachedCurEvents.TryGetValue(newEv, out int index)) 180 | { 181 | // If avoiding this warning is too annoying then make this the default behaviour and have this be a message sent 182 | // when in verbose mode or something 183 | Debug.LogWarning( 184 | $"To prevent parallel corruption, event {ev.GetType().Name} cannot be sent to the same entity multiple times between processing. This event will replace the previous one!"); 185 | 186 | _queuedEvents[index] = newEv; 187 | } 188 | else 189 | { 190 | _cachedCurEvents[newEv] = _queuedEvents.Length; 191 | _queuedEvents.Add(newEv); 192 | } 193 | #else 194 | _queuedEvents.Add(newEv); 195 | #endif 196 | } 197 | 198 | /// 199 | /// Process all queued events. 200 | /// 201 | public void ProcessEvents() 202 | { 203 | // Early bail to avoid setting up job stuff unnecessarily 204 | if (_queuedEvents.Length == 0) 205 | { 206 | return; 207 | } 208 | 209 | NativeQueue eventsToProcessQueue = new NativeQueue(Allocator.TempJob); 210 | 211 | BuildEventQueueJob job = new BuildEventQueueJob(); 212 | job.queuedEvents = _queuedEvents; 213 | job.subscribers = _subscribers; 214 | job.eventsToProcess = eventsToProcessQueue.ToConcurrent(); 215 | 216 | job.Schedule(_queuedEvents.Length, 32).Complete(); 217 | 218 | int eventCount = eventsToProcessQueue.Count; 219 | 220 | NativeArray eventsToProcess = new NativeArray(eventCount, Allocator.TempJob); 221 | 222 | EventQueueToEventArrayJob setJob = new EventQueueToEventArrayJob(); 223 | setJob.eventsInQueue = eventsToProcessQueue; 224 | setJob.events = eventsToProcess; 225 | 226 | JobHandle setArrayHandle = setJob.Schedule(); 227 | 228 | NativeArray jobsArray = new NativeArray(eventCount, Allocator.TempJob); 229 | 230 | CreateJobsArrayJob createJobArrayJob = new CreateJobsArrayJob(); 231 | createJobArrayJob.events = eventsToProcess; 232 | createJobArrayJob.subscribers = _subscribers; 233 | createJobArrayJob.jobs = jobsArray; 234 | 235 | JobHandle createJobArrayHandle = createJobArrayJob.Schedule( 236 | eventCount, 237 | _batchCount, 238 | setArrayHandle); 239 | 240 | ExecuteEventJobsJob executeJob = new ExecuteEventJobsJob(); 241 | executeJob.jobsResult = jobsArray; 242 | executeJob.evs = eventsToProcess; 243 | 244 | JobHandle executeHandle = executeJob.Schedule( 245 | eventCount, 246 | _batchCount, 247 | createJobArrayHandle); 248 | 249 | WriteBackToSubscribersJob writeBackJob = new WriteBackToSubscribersJob(); 250 | writeBackJob.subscribers = _subscribers; 251 | writeBackJob.evs = eventsToProcess; 252 | writeBackJob.jobsResult = jobsArray; 253 | 254 | JobHandle writeBackHandle = writeBackJob.Schedule( 255 | eventCount, 256 | _batchCount, 257 | executeHandle); 258 | 259 | writeBackHandle.Complete(); 260 | 261 | int count = eventsToProcess.Length; 262 | 263 | for (int i = 0; i < count; i++) 264 | { 265 | UnityEventJob ev = eventsToProcess[i]; 266 | Subscription sub = _subscribers[ev.subscriberIndex]; 267 | 268 | try 269 | { 270 | _subscriberCallbacks[ev.subscriberIndex](sub.job); 271 | } 272 | catch (Exception e) 273 | { 274 | Debug.LogException(e); 275 | } 276 | } 277 | 278 | eventsToProcessQueue.Dispose(); 279 | eventsToProcess.Dispose(); 280 | jobsArray.Dispose(); 281 | 282 | _queuedEvents.Clear(); 283 | 284 | #if !DISABLE_EVENT_SAFETY_CHKS 285 | _cachedCurEvents.Clear(); 286 | #endif 287 | } 288 | 289 | /// 290 | /// Reset the system. Removes all listeners and queued events. 291 | /// 292 | public void Reset() 293 | { 294 | _queuedEvents.Clear(); 295 | _subscribers.Clear(); 296 | _subscriberCallbacks.Clear(); 297 | _entityCallbackToIndex.Clear(); 298 | 299 | #if !DISABLE_EVENT_SAFETY_CHKS 300 | _cachedCurEvents.Clear(); 301 | #endif 302 | } 303 | 304 | /// 305 | /// Debug log an error for each subscriber that is still listening. 306 | /// 307 | public void VerifyNoSubscribers() 308 | { 309 | if (_subscribers.Length > 0) 310 | { 311 | // Just throw the first one, it'll get resolved 312 | throw new SubscriberStillListeningException(_subscriberCallbacks); 313 | } 314 | } 315 | 316 | [BurstCompile] 317 | private struct BuildEventQueueJob : IJobParallelFor 318 | { 319 | [ReadOnly] 320 | public NativeList> queuedEvents; 321 | 322 | [ReadOnly] 323 | public NativeList subscribers; 324 | 325 | public NativeQueue.Concurrent eventsToProcess; 326 | 327 | public void Execute(int index) 328 | { 329 | int count = subscribers.Length; 330 | QueuedEvent ev = queuedEvents[index]; 331 | 332 | for (int i = 0; i < count; i++) 333 | { 334 | if (subscribers[i].target.Equals(ev.target)) 335 | { 336 | eventsToProcess.Enqueue(new UnityEventJob(ev.ev, i)); 337 | } 338 | } 339 | } 340 | } 341 | 342 | [BurstCompile] 343 | private struct EventQueueToEventArrayJob : IJob 344 | { 345 | public NativeQueue eventsInQueue; 346 | 347 | [WriteOnly] 348 | public NativeArray events; 349 | 350 | public void Execute() 351 | { 352 | int count = eventsInQueue.Count; 353 | 354 | for (int i = 0; i < count; i++) 355 | { 356 | events[i] = eventsInQueue.Dequeue(); 357 | } 358 | } 359 | } 360 | 361 | [BurstCompile] 362 | private struct CreateJobsArrayJob : IJobParallelFor 363 | { 364 | [ReadOnly] 365 | public NativeArray events; 366 | 367 | [ReadOnly] 368 | public NativeList subscribers; 369 | 370 | [WriteOnly] 371 | public NativeArray jobs; 372 | 373 | public void Execute(int index) 374 | { 375 | jobs[index] = subscribers[events[index].subscriberIndex].job; 376 | } 377 | } 378 | 379 | [BurstCompile] 380 | private struct ExecuteEventJobsJob : IJobParallelFor 381 | { 382 | [ReadOnly] 383 | public NativeArray evs; 384 | 385 | public NativeArray jobsResult; 386 | 387 | public void Execute(int index) 388 | { 389 | T_Job job = jobsResult[index]; 390 | job.ExecuteEvent(evs[index].ev); 391 | jobsResult[index] = job; 392 | } 393 | } 394 | 395 | [BurstCompile] 396 | private struct WriteBackToSubscribersJob : IJobParallelFor 397 | { 398 | [WriteOnly] 399 | [NativeDisableContainerSafetyRestriction] 400 | public NativeList subscribers; 401 | 402 | [ReadOnly] 403 | public NativeArray evs; 404 | 405 | [ReadOnly] 406 | public NativeArray jobsResult; 407 | 408 | public void Execute(int index) 409 | { 410 | Subscription sub = subscribers[evs[index].subscriberIndex]; 411 | sub.job = jobsResult[index]; 412 | subscribers[evs[index].subscriberIndex] = sub; 413 | } 414 | } 415 | } 416 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/EventHandlerJob.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d83953d5e9722343991a56abfc56e02 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/EventHandlerStandard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Unity.Burst; 4 | using Unity.Collections; 5 | using Unity.Collections.LowLevel.Unsafe; 6 | using Unity.Jobs; 7 | using UnityEngine; 8 | using UnityEvents.Internal; 9 | 10 | namespace UnityEvents 11 | { 12 | /// 13 | /// Event system that processes regular events. 14 | /// 15 | /// The event the system is responsible for. 16 | public class EventHandlerStandard : IEventSystem, IDisposable where T_Event : struct 17 | { 18 | private NativeList> _queuedEvents; 19 | private NativeList _subscribers; 20 | 21 | private List> _subscriberCallbacks; 22 | private Dictionary, int> _entityCallbackToIndex; 23 | 24 | private bool _disposed; 25 | 26 | private readonly int _batchCount; 27 | 28 | private const int DEFAULT_EVENTS_TO_PROCESS_CAPACITY = 10; 29 | private const int DEFAULT_SUBSCRIBER_CAPACITY = 100; 30 | private const int DEFAULT_PARALLEL_BATCH_COUNT = 32; 31 | 32 | public EventHandlerStandard() : this( 33 | DEFAULT_SUBSCRIBER_CAPACITY, 34 | DEFAULT_EVENTS_TO_PROCESS_CAPACITY, 35 | DEFAULT_PARALLEL_BATCH_COUNT) 36 | { 37 | } 38 | 39 | /// 40 | /// Create a system with some custom settings. 41 | /// 42 | /// The starting capacity of subscriber containers. 43 | /// The starting capacity of queued events containers. 44 | /// The batch count allowed per thread for parallel processing. 45 | public EventHandlerStandard( 46 | int subscriberStartingCapacity, 47 | int queuedEventsStartingCapacity, 48 | int parallelBatchCount) 49 | { 50 | #if !DISABLE_EVENT_SAFETY_CHKS 51 | if (!UnsafeUtility.IsBlittable()) 52 | { 53 | throw new EventTypeNotBlittableException(typeof(T_Event)); 54 | } 55 | #endif 56 | _batchCount = parallelBatchCount; 57 | 58 | _subscribers = new NativeList(subscriberStartingCapacity, Allocator.Persistent); 59 | _subscriberCallbacks = new List>(subscriberStartingCapacity); 60 | _entityCallbackToIndex = new Dictionary, int>(subscriberStartingCapacity); 61 | 62 | _queuedEvents = new NativeList>(queuedEventsStartingCapacity, Allocator.Persistent); 63 | } 64 | 65 | /// 66 | /// Disposes of some internally held state. 67 | /// 68 | public void Dispose() 69 | { 70 | #if !DISABLE_EVENT_SAFETY_CHKS 71 | if (_disposed) 72 | { 73 | _disposed = true; 74 | return; 75 | } 76 | #endif 77 | _queuedEvents.Dispose(); 78 | _subscribers.Dispose(); 79 | } 80 | 81 | /// 82 | /// Subscribe a listener to the system. 83 | /// 84 | /// The target to subscribe to. 85 | /// The callback that is invoked when an event fires. 86 | public void Subscribe(EventTarget target, Action callback) 87 | { 88 | #if !DISABLE_EVENT_SAFETY_CHKS 89 | if (_entityCallbackToIndex.ContainsKey(new EntityCallbackId(target, callback))) 90 | { 91 | throw new MultipleSubscriptionsException(callback); 92 | } 93 | #endif 94 | 95 | _entityCallbackToIndex.Add(new EntityCallbackId(target, callback), _subscribers.Length); 96 | _subscribers.Add(target); 97 | _subscriberCallbacks.Add(callback); 98 | } 99 | 100 | /// 101 | /// Unsubscribe a listener from the system. 102 | /// 103 | /// The target to unsubscribe from. 104 | /// The callback that was invoked during events. 105 | public void Unsubscribe(EventTarget target, Action callback) 106 | { 107 | EntityCallbackId callbackId = new EntityCallbackId(target, callback); 108 | 109 | if (_entityCallbackToIndex.TryGetValue(callbackId, out int index)) 110 | { 111 | _entityCallbackToIndex.Remove(callbackId); 112 | 113 | _subscribers.RemoveAtSwapBack(index); 114 | 115 | _subscriberCallbacks[index] = _subscriberCallbacks[_subscriberCallbacks.Count - 1]; 116 | _subscriberCallbacks.RemoveAt(_subscriberCallbacks.Count - 1); 117 | 118 | if (index != _subscribers.Length) 119 | { 120 | EntityCallbackId otherCallbackId = new EntityCallbackId( 121 | _subscribers[index], 122 | _subscriberCallbacks[index]); 123 | 124 | _entityCallbackToIndex[otherCallbackId] = index; 125 | } 126 | } 127 | } 128 | 129 | /// 130 | /// Queue an event to be processed later. 131 | /// 132 | /// The target the event is for. 133 | /// The event to queue. 134 | public void QueueEvent(EventTarget target, T_Event ev) 135 | { 136 | _queuedEvents.Add(new QueuedEvent(target, ev)); 137 | } 138 | 139 | /// 140 | /// Process all queued events. 141 | /// 142 | public void ProcessEvents() 143 | { 144 | // Early bail to avoid setting up job stuff unnecessarily 145 | if (_queuedEvents.Length == 0) 146 | { 147 | return; 148 | } 149 | 150 | NativeQueue> eventsToProcessQueue = 151 | new NativeQueue>(Allocator.TempJob); 152 | 153 | BuildEventQueueJob job = new BuildEventQueueJob(); 154 | job.queuedEvents = _queuedEvents; 155 | job.subscribers = _subscribers; 156 | job.eventsToProcess = eventsToProcessQueue.ToConcurrent(); 157 | 158 | job.Schedule(_queuedEvents.Length, _batchCount).Complete(); 159 | 160 | while (eventsToProcessQueue.TryDequeue(out UnityEvent ev)) 161 | { 162 | try 163 | { 164 | _subscriberCallbacks[ev.subscriberIndex](ev.ev); 165 | } 166 | catch (Exception e) 167 | { 168 | Debug.LogException(e); 169 | } 170 | } 171 | 172 | eventsToProcessQueue.Dispose(); 173 | _queuedEvents.Clear(); 174 | } 175 | 176 | /// 177 | /// Reset the system. Removes all listeners and queued events. 178 | /// 179 | public void Reset() 180 | { 181 | _queuedEvents.Clear(); 182 | _subscribers.Clear(); 183 | _subscriberCallbacks.Clear(); 184 | _entityCallbackToIndex.Clear(); 185 | } 186 | 187 | /// 188 | /// Debug log an error for each subscriber that is still listening. 189 | /// 190 | public void VerifyNoSubscribers() 191 | { 192 | if (_subscribers.Length > 0) 193 | { 194 | // Just throw the first one, it'll get resolved 195 | throw new SubscriberStillListeningException(_subscriberCallbacks); 196 | } 197 | } 198 | 199 | [BurstCompile] 200 | private struct BuildEventQueueJob : IJobParallelFor 201 | { 202 | [ReadOnly] 203 | public NativeList> queuedEvents; 204 | 205 | [ReadOnly] 206 | public NativeList subscribers; 207 | 208 | public NativeQueue>.Concurrent eventsToProcess; 209 | 210 | public void Execute(int index) 211 | { 212 | int count = subscribers.Length; 213 | QueuedEvent ev = queuedEvents[index]; 214 | 215 | for (int i = 0; i < count; i++) 216 | { 217 | if (subscribers[i].Equals(ev.target)) 218 | { 219 | eventsToProcess.Enqueue(new UnityEvent(ev.ev, i)); 220 | } 221 | } 222 | } 223 | } 224 | } 225 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/EventHandlerStandard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fe7b7073d17471f42961d9758b17a1ca 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/EventManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using UnityEvents.Internal; 4 | 5 | namespace UnityEvents 6 | { 7 | /// 8 | /// EventManager manages systems with the various Unity lifetime ticks. Allows systems that run in FixedUpdate, 9 | /// Update, and LateUpdate. 10 | /// 11 | public class EventManager : MonoBehaviour 12 | { 13 | private static UnityEventSystem _fixedUpdateSystem = new UnityEventSystem(); 14 | private static UnityEventSystem _updateSystem = new UnityEventSystem(); 15 | private static UnityEventSystem _lateUpdateSystem = new UnityEventSystem(); 16 | 17 | /// 18 | /// Subscribe a listener to an event in the specific update tick. 19 | /// 20 | /// The target to subscribe to. 21 | /// The event callback 22 | /// The update type to subscribe to. 23 | /// The event 24 | public static void Subscribe(EventTarget target, Action eventCallback, EventUpdateTick tick) 25 | where T_Event : struct 26 | { 27 | if (tick == EventUpdateTick.FixedUpdate) 28 | { 29 | _fixedUpdateSystem.Subscribe(target, eventCallback); 30 | } 31 | else if (tick == EventUpdateTick.Update) 32 | { 33 | _updateSystem.Subscribe(target, eventCallback); 34 | } 35 | else // Late Update 36 | { 37 | _lateUpdateSystem.Subscribe(target, eventCallback); 38 | } 39 | } 40 | 41 | /// 42 | /// Subscribe a job that processes during an event in the specific update tick. 43 | /// 44 | /// The target to subscribe to. 45 | /// The job, and starting data, to run when the event fires. 46 | /// The callback that is invoked when the job has finished. 47 | /// The update type to subscribe to. 48 | /// The event type. 49 | /// The job type. 50 | public static void SubscribeWithJob( 51 | EventTarget target, 52 | T_Job job, 53 | Action onComplete, 54 | EventUpdateTick tick) 55 | where T_Job : struct, IJobForEvent 56 | where T_Event : struct 57 | { 58 | if (tick == EventUpdateTick.FixedUpdate) 59 | { 60 | _fixedUpdateSystem.SubscribeWithJob(target, job, onComplete); 61 | } 62 | else if (tick == EventUpdateTick.Update) 63 | { 64 | _updateSystem.SubscribeWithJob(target, job, onComplete); 65 | } 66 | else // Late Update 67 | { 68 | _lateUpdateSystem.SubscribeWithJob(target, job, onComplete); 69 | } 70 | } 71 | 72 | /// 73 | /// Unsubscribe a listener from an event in the specific update tick. 74 | /// 75 | /// The target to unsubscribe from. 76 | /// The event callback 77 | /// The update type to unsubscribe to. 78 | /// The event 79 | public static void Unsubscribe(EventTarget target, Action eventCallback, EventUpdateTick tick) 80 | where T_Event : struct 81 | { 82 | if (tick == EventUpdateTick.FixedUpdate) 83 | { 84 | _fixedUpdateSystem.Unsubscribe(target, eventCallback); 85 | } 86 | else if (tick == EventUpdateTick.Update) 87 | { 88 | _updateSystem.Unsubscribe(target, eventCallback); 89 | } 90 | else // Late Update 91 | { 92 | _lateUpdateSystem.Unsubscribe(target, eventCallback); 93 | } 94 | } 95 | 96 | /// 97 | /// Unsubscribe a job that processed during from an event in the specific update tick. 98 | /// 99 | /// The target to unsubscribe from. 100 | /// The callback that is invoked when the job has finished. 101 | /// The update type to unsubscribe to. 102 | /// The job type. 103 | /// The event type. 104 | public static void UnsubscribeWithJob(EventTarget target, Action onComplete, 105 | EventUpdateTick tick) 106 | where T_Job : struct, IJobForEvent 107 | where T_Event : struct 108 | { 109 | if (tick == EventUpdateTick.FixedUpdate) 110 | { 111 | _fixedUpdateSystem.UnsubscribeWithJob(target, onComplete); 112 | } 113 | else if (tick == EventUpdateTick.Update) 114 | { 115 | _updateSystem.UnsubscribeWithJob(target, onComplete); 116 | } 117 | else // Late Update 118 | { 119 | _lateUpdateSystem.UnsubscribeWithJob(target, onComplete); 120 | } 121 | } 122 | 123 | /// 124 | /// Send an event to be processed in a specific update tick. 125 | /// 126 | /// The target to send the event to. 127 | /// The event to send 128 | /// The update tick to send to. 129 | /// The event type. 130 | public static void SendEvent(EventTarget target, T_Event ev, EventUpdateTick tick) 131 | where T_Event : struct 132 | { 133 | if (tick == EventUpdateTick.FixedUpdate) 134 | { 135 | _fixedUpdateSystem.QueueEvent(target, ev); 136 | } 137 | else if (tick == EventUpdateTick.Update) 138 | { 139 | _updateSystem.QueueEvent(target, ev); 140 | } 141 | else // Late Update 142 | { 143 | _lateUpdateSystem.QueueEvent(target, ev); 144 | } 145 | } 146 | 147 | /// 148 | /// Flushes all currently queued events NOW 149 | /// 150 | public static void FlushAll() 151 | { 152 | _fixedUpdateSystem.ProcessEvents(); 153 | _updateSystem.ProcessEvents(); 154 | _lateUpdateSystem.ProcessEvents(); 155 | } 156 | 157 | /// 158 | /// Reset all the event systems with all update types. 159 | /// 160 | public static void ResetAll() 161 | { 162 | _fixedUpdateSystem.Reset(); 163 | _updateSystem.Reset(); 164 | _lateUpdateSystem.Reset(); 165 | } 166 | 167 | /// 168 | /// Debug function to verify there are no lingering listeners. Throws an exception if there's a listener. 169 | /// 170 | public static void VerifyNoSubscribersAll() 171 | { 172 | _fixedUpdateSystem.VerifyNoSubscribers(); 173 | _updateSystem.VerifyNoSubscribers(); 174 | _lateUpdateSystem.VerifyNoSubscribers(); 175 | } 176 | 177 | /// 178 | /// Debug function to verify there are no lingering listeners. Logs each offending system instead of throwing an 179 | /// exception. 180 | /// 181 | public static void VerifyNoSubscribersAllLog() 182 | { 183 | _fixedUpdateSystem.VerifyNoSubscribersLog(); 184 | _updateSystem.VerifyNoSubscribersLog(); 185 | _lateUpdateSystem.VerifyNoSubscribersLog(); 186 | } 187 | 188 | private void FixedUpdate() 189 | { 190 | _fixedUpdateSystem.ProcessEvents(); 191 | } 192 | 193 | private void Update() 194 | { 195 | _updateSystem.ProcessEvents(); 196 | } 197 | 198 | private void LateUpdate() 199 | { 200 | _lateUpdateSystem.ProcessEvents(); 201 | } 202 | 203 | private void OnDestroy() 204 | { 205 | ResetAll(); 206 | 207 | _fixedUpdateSystem.Dispose(); 208 | _updateSystem.Dispose(); 209 | _lateUpdateSystem.Dispose(); 210 | } 211 | 212 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] 213 | private static void Initialize() 214 | { 215 | GameObject em = new GameObject("[EVENT MANAGER DO]", typeof(EventManager)); 216 | DontDestroyOnLoad(em); 217 | } 218 | } 219 | 220 | public enum EventUpdateTick 221 | { 222 | FixedUpdate, 223 | Update, 224 | LateUpdate 225 | } 226 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/EventManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 090143b0b25343443ac673308f3acce2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/EventTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEvents.Internal; 3 | using Object = UnityEngine.Object; 4 | 5 | namespace UnityEvents 6 | { 7 | /// 8 | /// Used to represent the target of events. This is something that be subscribed to, unsubscribed from, and have 9 | /// events sent to. For example, the global event system uses an event target to maintain this. The GameObject event 10 | /// system has an event target for each GameObject. 11 | /// 12 | public struct EventTarget: IEquatable 13 | { 14 | public readonly ulong id; 15 | 16 | public static readonly EventTarget NULL_TARGET = new EventTarget(NULL_ID); 17 | 18 | // We reserve the first uint.MaxValue values for GameObjects 19 | private static ulong _ids = (ulong)uint.MaxValue + 1; 20 | private const ulong NULL_ID = ulong.MaxValue; 21 | 22 | /// 23 | /// Creates a target with a specific ID. This CAN clash with a previously created target of an id. 24 | /// Creating new target of the same id intentionally is fine and will work interchangeably. 25 | /// 26 | /// Id to bind the target to. 27 | public EventTarget(ulong id) 28 | { 29 | this.id = id; 30 | } 31 | 32 | /// 33 | /// Creates a target with a specific ID. This CAN clash with a previously created target of an id. 34 | /// Creating new target of the same id intentionally is fine and will work interchangeably. 35 | /// 36 | /// Id to bind the target to. 37 | public EventTarget(int id) : this(unchecked((uint)id)) 38 | { 39 | 40 | } 41 | 42 | /// 43 | /// Creates a new unique event target. 44 | /// 45 | /// The new target. 46 | public static EventTarget CreateTarget() 47 | { 48 | return new EventTarget(_ids++); 49 | } 50 | 51 | /// 52 | /// Creates an event target associated with the supplied Unity Object. 53 | /// 54 | /// The object to associate the target with. 55 | /// The new target. 56 | public static EventTarget CreateTarget(Object obj) 57 | { 58 | if (obj == null) 59 | { 60 | return NULL_TARGET; 61 | } 62 | 63 | return new EventTarget(obj.GetInstanceID()); 64 | } 65 | 66 | /// 67 | /// Reserves a reservation of targets to be leveraged by the caller. For custom management for some number of targets. 68 | /// 69 | /// The number of targets to reserve. 70 | /// The starting id of the reservation, this should be 71 | public static EventTargetReservation ReserveTargets(ulong count) 72 | { 73 | ulong start = _ids; 74 | #if !DISABLE_EVENT_SAFETY_CHKS 75 | checked 76 | { 77 | _ids += count; 78 | } 79 | #else 80 | _ids += count; 81 | #endif 82 | 83 | return new EventTargetReservation(start, count); 84 | } 85 | 86 | public bool Equals(EventTarget other) 87 | { 88 | return id == other.id; 89 | } 90 | 91 | public override bool Equals(object obj) 92 | { 93 | if (ReferenceEquals(null, obj)) return false; 94 | return obj is EventTarget other && Equals(other); 95 | } 96 | 97 | public override int GetHashCode() 98 | { 99 | return id.GetHashCode(); 100 | } 101 | } 102 | 103 | /// 104 | /// Is a reservation of a block of event targets. 105 | /// 106 | public struct EventTargetReservation : IEquatable 107 | { 108 | private readonly ulong _reservationStart; 109 | private readonly ulong _reservationCount; 110 | 111 | // Generated by JetBrains 112 | private const int HASHCODE_MULTIPLIER = 397; 113 | 114 | public EventTargetReservation(ulong reservationStart, ulong reservationCount) 115 | { 116 | _reservationStart = reservationStart; 117 | _reservationCount = reservationCount; 118 | } 119 | 120 | /// 121 | /// Get an event target from the reservation. 122 | /// 123 | /// The index of the event target. 124 | /// The event Target. 125 | /// Throws if an invalid index. 126 | public EventTarget GetEntityTarget(int index) 127 | { 128 | #if !DISABLE_EVENT_SAFETY_CHKS 129 | if (index < 0 || (ulong)index >= _reservationCount) 130 | { 131 | throw new IndexOutOfReservedTargetsException(); 132 | } 133 | #endif 134 | 135 | return new EventTarget(_reservationStart + (ulong)index); 136 | } 137 | 138 | /// 139 | /// Get an event target from the reservation. 140 | /// 141 | /// The index of the event target. 142 | /// The event Target. 143 | /// Throws if an invalid index. 144 | public EventTarget GetEntityTarget(ulong index) 145 | { 146 | #if !DISABLE_EVENT_SAFETY_CHKS 147 | if (index >= _reservationCount) 148 | { 149 | throw new IndexOutOfReservedTargetsException(); 150 | } 151 | #endif 152 | 153 | return new EventTarget(_reservationStart + index); 154 | } 155 | 156 | public bool Equals(EventTargetReservation other) 157 | { 158 | return _reservationStart == other._reservationStart && _reservationCount == other._reservationCount; 159 | } 160 | 161 | public override bool Equals(object obj) 162 | { 163 | if (ReferenceEquals(null, obj)) return false; 164 | return obj is EventTargetReservation other && Equals(other); 165 | } 166 | 167 | public override int GetHashCode() 168 | { 169 | unchecked 170 | { 171 | return (_reservationStart.GetHashCode() * HASHCODE_MULTIPLIER) ^ _reservationCount.GetHashCode(); 172 | } 173 | } 174 | } 175 | } 176 | 177 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/EventTarget.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6730ad9c87e27254e8fe54ffec402ad0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/GameObjectEventSystem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using UnityEvents.Internal; 4 | 5 | namespace UnityEvents 6 | { 7 | public static class GameObjectEventSystem 8 | { 9 | public static void Subscribe(this GameObject gObj, Action callback) where T_Event : struct 10 | { 11 | EventManager.Subscribe(EventTarget.CreateTarget(gObj), callback, EventUpdateTick.FixedUpdate); 12 | } 13 | 14 | public static void SubscribeWithJob(this GameObject gObj, T_Job job, Action onComplete) 15 | where T_Job : struct, IJobForEvent 16 | where T_Event : struct 17 | { 18 | EventManager.SubscribeWithJob( 19 | EventTarget.CreateTarget(gObj), 20 | job, 21 | onComplete, 22 | EventUpdateTick.FixedUpdate); 23 | } 24 | 25 | public static void Unsubscribe(this GameObject gObj, Action callback) 26 | where T_Event : struct 27 | { 28 | EventManager.Unsubscribe(EventTarget.CreateTarget(gObj), callback, EventUpdateTick.FixedUpdate); 29 | } 30 | 31 | public static void UnsubscribeWithJob(this GameObject gObj, Action onComplete) 32 | where T_Job : struct, IJobForEvent 33 | where T_Event : struct 34 | { 35 | EventManager.UnsubscribeWithJob( 36 | EventTarget.CreateTarget(gObj), 37 | onComplete, 38 | EventUpdateTick.FixedUpdate); 39 | } 40 | 41 | public static void SendEvent(this GameObject gObj, T_Event ev) where T_Event : struct 42 | { 43 | EventManager.SendEvent(EventTarget.CreateTarget(gObj), ev, EventUpdateTick.FixedUpdate); 44 | } 45 | 46 | public static void SubscribeUI(this GameObject gObj, Action callback) 47 | where T_Event : struct 48 | { 49 | EventManager.Subscribe(EventTarget.CreateTarget(gObj), callback, EventUpdateTick.LateUpdate); 50 | } 51 | 52 | public static void SubscribeUIWithJob(this GameObject gObj, T_Job job, Action onComplete) 53 | where T_Job : struct, IJobForEvent 54 | where T_Event : struct 55 | { 56 | EventManager.SubscribeWithJob( 57 | EventTarget.CreateTarget(gObj), 58 | job, 59 | onComplete, 60 | EventUpdateTick.LateUpdate); 61 | } 62 | 63 | public static void UnsubscribeUI(this GameObject gObj, Action callback) 64 | where T_Event : struct 65 | { 66 | EventManager.Unsubscribe( 67 | EventTarget.CreateTarget(gObj), 68 | callback, 69 | EventUpdateTick.LateUpdate); 70 | } 71 | 72 | public static void UnsubscribeUIWithJob(this GameObject gObj, Action onComplete) 73 | where T_Job : struct, IJobForEvent 74 | where T_Event : struct 75 | { 76 | EventManager.UnsubscribeWithJob( 77 | EventTarget.CreateTarget(gObj), 78 | onComplete, 79 | EventUpdateTick.LateUpdate); 80 | } 81 | 82 | public static void SendEventUI(this GameObject gObj, T_Event ev) where T_Event : struct 83 | { 84 | EventManager.SendEvent(EventTarget.CreateTarget(gObj), ev, EventUpdateTick.LateUpdate); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/GameObjectEventSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ede1248eea3935f459f28473d6e164a4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/GlobalEventSystem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEvents.Internal; 3 | 4 | namespace UnityEvents 5 | { 6 | /// 7 | /// A system that handles global events for Fixed Update. Intended for gameplay events. 8 | /// 9 | public static class GlobalEventSystem 10 | { 11 | private static TickEventSystem _simSystem = new TickEventSystem(EventUpdateTick.FixedUpdate); 12 | private static TickEventSystem _uiSystem = new TickEventSystem(EventUpdateTick.LateUpdate); 13 | 14 | /// 15 | /// Subscribe a listener to the global event system. 16 | /// 17 | /// The callback that's invoked when an event occurs. 18 | /// The event type. 19 | public static void Subscribe(Action callback) where T_Event : struct 20 | { 21 | _simSystem.Subscribe(callback); 22 | } 23 | 24 | /// 25 | /// Subscribe a job to the global event system. 26 | /// 27 | /// The job that is processed when an event occurs. 28 | /// The callback that's invoked when the job is done. 29 | /// The job type. 30 | /// The event type. 31 | public static void SubscribeWithJob(T_Job job, Action onComplete) 32 | where T_Job : struct, IJobForEvent 33 | where T_Event : struct 34 | { 35 | _simSystem.SubscribeWithJob(job, onComplete); 36 | } 37 | 38 | /// 39 | /// Unsubscribe a listener from the global event system. 40 | /// 41 | /// The callback to unsubscribe. 42 | /// The event type. 43 | public static void Unsubscribe(Action callback) where T_Event : struct 44 | { 45 | _simSystem.Unsubscribe(callback); 46 | } 47 | 48 | /// 49 | /// Unsubscribe a job from the global event system. 50 | /// 51 | /// The on complete callback to unsubscribe 52 | /// The job type to unsubscribe. 53 | /// The event type. 54 | public static void UnsubscribeWithJob(Action onComplete) 55 | where T_Job : struct, IJobForEvent 56 | where T_Event : struct 57 | { 58 | _simSystem.UnsubscribeWithJob(onComplete); 59 | } 60 | 61 | /// 62 | /// Send an event to the global event system. 63 | /// 64 | /// The event to send. 65 | /// The event type. 66 | public static void SendEvent(T_Event ev) where T_Event : struct 67 | { 68 | _simSystem.SendEvent(ev); 69 | } 70 | 71 | /// 72 | /// Subscribe a listener to the global UI event system. 73 | /// 74 | /// The callback that's invoked when an event occurs. 75 | /// The event type. 76 | public static void SubscribeUI(Action callback) where T_Event : struct 77 | { 78 | _uiSystem.Subscribe(callback); 79 | } 80 | 81 | /// 82 | /// Subscribe a job to the global UI event system. 83 | /// 84 | /// The job that is processed when an event occurs. 85 | /// The callback that's invoked when the job is done. 86 | /// The job type. 87 | /// The event type. 88 | public static void SubscribeUIWithJob(T_Job job, Action onComplete) 89 | where T_Job : struct, IJobForEvent 90 | where T_Event : struct 91 | { 92 | _uiSystem.SubscribeWithJob(job, onComplete); 93 | } 94 | 95 | /// 96 | /// Unsubscribe a listener from the global UI event system. 97 | /// 98 | /// The callback to unsubscribe. 99 | /// The event type. 100 | public static void UnsubscribeUI(Action callback) where T_Event : struct 101 | { 102 | _uiSystem.Unsubscribe(callback); 103 | } 104 | 105 | /// 106 | /// Unsubscribe a job from the global UI event system. 107 | /// 108 | /// The on complete callback to unsubscribe 109 | /// The job type to unsubscribe. 110 | /// The event type. 111 | public static void UnsubscribeUIWithJob(Action onComplete) 112 | where T_Job : struct, IJobForEvent 113 | where T_Event : struct 114 | { 115 | _uiSystem.UnsubscribeWithJob(onComplete); 116 | } 117 | 118 | /// 119 | /// Send an event to the global UI event system. 120 | /// 121 | /// The event to send. 122 | /// The event type. 123 | public static void SendEventUI(T_Event ev) where T_Event : struct 124 | { 125 | _uiSystem.SendEvent(ev); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/GlobalEventSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 07a6801a4bfbcf74998a7834297b4af2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/Internal.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 51feeee6e92af4b4caf4c2d1d2435a33 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/Internal/UnityEventsExceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UnityEvents.Internal 5 | { 6 | public class MultipleSubscriptionsException : Exception 7 | { 8 | public MultipleSubscriptionsException(Action callback) 9 | : base($"Not allowed to subscribe the same callback to the same entity! Target: {callback.Target.GetType().Name} Event: {typeof(T).Name}") 10 | { 11 | 12 | } 13 | } 14 | 15 | public class SubscriberStillListeningException : Exception 16 | where T_Event : struct 17 | { 18 | public SubscriberStillListeningException(List> listeners) 19 | : base(GenerateMessage(listeners)) 20 | { 21 | } 22 | 23 | private static string GenerateMessage(List> listeners) 24 | { 25 | string msg = $"The following subscribers are still listening to the {typeof(T_Event).Name} system!"; 26 | 27 | foreach (Action listener in listeners) 28 | { 29 | if (listener == null) 30 | { 31 | msg += "\n"; 32 | } 33 | else 34 | { 35 | msg += $"\n{listener.Method.Name}"; 36 | } 37 | } 38 | 39 | return msg; 40 | } 41 | } 42 | 43 | public class IndexOutOfReservedTargetsException : Exception 44 | { 45 | 46 | } 47 | 48 | public class EventTypeNotBlittableException : Exception 49 | { 50 | public EventTypeNotBlittableException(Type type) 51 | : base($"Event type {type.Name} must be blittable!") 52 | {} 53 | } 54 | 55 | public class JobTypeNotBlittableException : Exception 56 | { 57 | public JobTypeNotBlittableException(Type type) 58 | : base($"Job type {type.Name} must be blittable!") 59 | {} 60 | } 61 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/Internal/UnityEventsExceptions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 382c09bd05d845940a497099bc7f460b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/Internal/UnityEventsInterfaces.cs: -------------------------------------------------------------------------------- 1 | namespace UnityEvents.Internal 2 | { 3 | public interface IEventSystem 4 | { 5 | void Reset(); 6 | void ProcessEvents(); 7 | void VerifyNoSubscribers(); 8 | } 9 | 10 | public interface IJobEventSystem : IEventSystem where T: struct 11 | { 12 | void QueueEvent(EventTarget target, T ev); 13 | } 14 | 15 | public interface IJobForEvent where T : struct 16 | { 17 | void ExecuteEvent(T ev); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/Internal/UnityEventsInterfaces.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e334ac3284c6305449960f9272914393 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/Internal/UnityEventsMisc.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UnityEvents.Internal 4 | { 5 | public struct QueuedEvent where T_Event : struct 6 | { 7 | public EventTarget target; 8 | public T_Event ev; 9 | 10 | public QueuedEvent(EventTarget target, T_Event ev) 11 | { 12 | this.target = target; 13 | this.ev = ev; 14 | } 15 | } 16 | 17 | public struct UnityEvent where T_Event : struct 18 | { 19 | public readonly T_Event ev; 20 | public readonly int subscriberIndex; 21 | 22 | public UnityEvent(T_Event ev, int subscriberIndex) 23 | { 24 | this.ev = ev; 25 | this.subscriberIndex = subscriberIndex; 26 | } 27 | } 28 | 29 | public struct EntityCallbackId : IEquatable> 30 | { 31 | public EventTarget target; 32 | public Action callback; 33 | 34 | // Generated by Jetbrains 35 | private const int HASHCODE_MULTIPLIER = 397; 36 | 37 | public EntityCallbackId(EventTarget target, Action callback) 38 | { 39 | this.target = target; 40 | this.callback = callback; 41 | } 42 | 43 | public bool Equals(EntityCallbackId other) 44 | { 45 | return target.Equals(other.target) && Equals(callback, other.callback); 46 | } 47 | 48 | public override bool Equals(object obj) 49 | { 50 | if (ReferenceEquals(null, obj)) return false; 51 | return obj is EntityCallbackId other && Equals(other); 52 | } 53 | 54 | public override int GetHashCode() 55 | { 56 | unchecked 57 | { 58 | return (target.GetHashCode() * HASHCODE_MULTIPLIER) ^ (callback != null ? callback.GetHashCode() : 0); 59 | } 60 | } 61 | }} 62 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/Internal/UnityEventsMisc.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b7a0c1e34b6672441bce3c23bee72cd8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/TickEventSystem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEvents.Internal; 3 | 4 | namespace UnityEvents 5 | { 6 | /// 7 | /// Event System that runs in a given update tick (FixedUpdate, Update, or LateUpdate). Can be used to create 8 | /// custom event systems. 9 | /// 10 | public class TickEventSystem 11 | { 12 | private EventUpdateTick _tick; 13 | private EventTarget _target; 14 | 15 | /// 16 | /// Create an tick based event system. 17 | /// 18 | /// Which tick to run in. 19 | public TickEventSystem(EventUpdateTick updateTick) 20 | { 21 | _tick = updateTick; 22 | _target = EventTarget.CreateTarget(); 23 | } 24 | 25 | /// 26 | /// Subscribe a listener to the tick based event system. 27 | /// 28 | /// The callback that's invoked when an event occurs. 29 | /// The event type. 30 | public void Subscribe(Action callback) where T_Event : struct 31 | { 32 | EventManager.Subscribe(_target, callback, _tick); 33 | } 34 | 35 | /// 36 | /// Subscribe a job to the tick based event system. 37 | /// 38 | /// The job that is processed when an event occurs. 39 | /// The callback that's invoked when the job is done. 40 | /// The job type. 41 | /// The event type. 42 | public void SubscribeWithJob(T_Job job, Action onComplete) 43 | where T_Job : struct, IJobForEvent 44 | where T_Event : struct 45 | { 46 | EventManager.SubscribeWithJob(_target, job, onComplete, _tick); 47 | } 48 | 49 | /// 50 | /// Unsubscribe a listener from the tick based event system. 51 | /// 52 | /// The callback to unsubscribe. 53 | /// The event type. 54 | public void Unsubscribe(Action callback) where T_Event : struct 55 | { 56 | EventManager.Unsubscribe(_target, callback, _tick); 57 | } 58 | 59 | /// 60 | /// Unsubscribe a job from the tick based event system. 61 | /// 62 | /// The on complete callback to unsubscribe 63 | /// The job type to unsubscribe. 64 | /// The event type. 65 | public void UnsubscribeWithJob(Action onComplete) 66 | where T_Job : struct, IJobForEvent 67 | where T_Event : struct 68 | { 69 | EventManager.UnsubscribeWithJob(_target, onComplete, _tick); 70 | } 71 | 72 | /// 73 | /// Send an event to the tick based event system. 74 | /// 75 | /// The event to send. 76 | /// The event type. 77 | public void SendEvent(T_Event ev) where T_Event : struct 78 | { 79 | EventManager.SendEvent(_target, ev, _tick); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/TickEventSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f298f4b52c61874f9fb546cecd27a4d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/UnityEventSystem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEvents.Internal; 5 | 6 | namespace UnityEvents 7 | { 8 | /// 9 | /// The event system that handles subscribers for all events, can queue all events, and will process the events 10 | /// when told to. 11 | /// 12 | public class UnityEventSystem : IDisposable 13 | { 14 | private List _systems = new List(); 15 | private Dictionary _systemsCache = new Dictionary(); 16 | private Dictionary _jobSystemsCache = new Dictionary(); 17 | 18 | private Dictionary> _eventToJobSystems = 19 | new Dictionary>(); 20 | 21 | // Cache, hit the same event multiple for better results 22 | private Type _cachedSystemEventType; 23 | private IEventSystem _cacheSystem; 24 | 25 | private Type _cachedJobSystemsType; 26 | private List _cachedJobSystems; 27 | 28 | private Type _cachedJobSystemType; 29 | private IEventSystem _cachedJobSystem; 30 | 31 | /// 32 | /// Subscribe a listener to an event. 33 | /// 34 | /// The target to subscribe to. 35 | /// The event callback 36 | /// The event 37 | public void Subscribe(EventTarget target, Action eventCallback) where T_Event : struct 38 | { 39 | EventHandlerStandard system = GetSystem(); 40 | system.Subscribe(target, eventCallback); 41 | } 42 | 43 | /// 44 | /// Subscribe a job that processes during an event. 45 | /// 46 | /// The target to subscribe to. 47 | /// The job, and starting data, to run when the event fires. 48 | /// The callback that is invoked when the job has finished. 49 | /// The event type. 50 | /// The job type. 51 | public void SubscribeWithJob(EventTarget target, T_Job job, Action onComplete) 52 | where T_Job : struct, IJobForEvent 53 | where T_Event : struct 54 | { 55 | EventHandlerJob handler = GetJobSystem(); 56 | handler.Subscribe(target, job, onComplete); 57 | } 58 | 59 | /// 60 | /// Unsubscribe a listener from an event. 61 | /// 62 | /// The target to unsubscribe from. 63 | /// The event callback 64 | /// The event 65 | public void Unsubscribe(EventTarget target, Action eventCallback) where T_Event : struct 66 | { 67 | EventHandlerStandard system = GetSystem(); 68 | system.Unsubscribe(target, eventCallback); 69 | } 70 | 71 | /// 72 | /// Unsubscribe a job that processed during from an event. 73 | /// 74 | /// The target to unsubscribe from. 75 | /// The callback that is invoked when the job has finished. 76 | /// The job type. 77 | /// The event type. 78 | public void UnsubscribeWithJob(EventTarget target, Action onComplete) 79 | where T_Job : struct, IJobForEvent 80 | where T_Event : struct 81 | { 82 | EventHandlerJob handler = GetJobSystem(); 83 | handler.Unsubscribe(target, onComplete); 84 | } 85 | 86 | /// 87 | /// Queue an event. 88 | /// 89 | /// The target to queue an event with. 90 | /// The event to queue. 91 | /// The event type. 92 | public void QueueEvent(EventTarget target, T_Event ev) where T_Event : struct 93 | { 94 | EventHandlerStandard system = GetSystem(); 95 | system.QueueEvent(target, ev); 96 | 97 | List list = GetJobSystemsForEvent(); 98 | 99 | int count = list.Count; 100 | 101 | for (int i = 0; i < count; i++) 102 | { 103 | IJobEventSystem typedSystem = (IJobEventSystem) list[i]; 104 | typedSystem.QueueEvent(target, ev); 105 | } 106 | } 107 | 108 | /// 109 | /// Process all queued events. 110 | /// 111 | public void ProcessEvents() 112 | { 113 | int count = _systems.Count; 114 | 115 | for (int i = 0; i < count; i++) 116 | { 117 | _systems[i].ProcessEvents(); 118 | } 119 | } 120 | 121 | /// 122 | /// Reset all systems in the collection. 123 | /// 124 | public void Reset() 125 | { 126 | int count = _systems.Count; 127 | 128 | for (int i = 0; i < count; i++) 129 | { 130 | _systems[i].Reset(); 131 | } 132 | } 133 | 134 | /// 135 | /// Verify there are no subscribers in the systems. 136 | /// 137 | public void VerifyNoSubscribers() 138 | { 139 | int count = _systems.Count; 140 | 141 | for (int i = 0; i < count; i++) 142 | { 143 | _systems[i].VerifyNoSubscribers(); 144 | } 145 | } 146 | 147 | /// 148 | /// Verify there are no subscribers. Logs instead of throwing an exception. 149 | /// 150 | public void VerifyNoSubscribersLog() 151 | { 152 | int count = _systems.Count; 153 | 154 | for (int i = 0; i < count; i++) 155 | { 156 | try 157 | { 158 | _systems[i].VerifyNoSubscribers(); 159 | } 160 | catch (Exception e) 161 | { 162 | Debug.LogException(e); 163 | throw; 164 | } 165 | } 166 | } 167 | 168 | /// 169 | /// Disposes any resources held by the systems. 170 | /// 171 | public void Dispose() 172 | { 173 | int count = _systems.Count; 174 | 175 | for (int i = 0; i < count; i++) 176 | { 177 | if (_systems[i] is IDisposable disposable) 178 | { 179 | disposable.Dispose(); 180 | } 181 | } 182 | } 183 | 184 | private EventHandlerStandard GetSystem() where T_Event : struct 185 | { 186 | Type evType = typeof(T_Event); 187 | 188 | if (evType == _cachedSystemEventType) 189 | { 190 | return (EventHandlerStandard) _cacheSystem; 191 | } 192 | 193 | IEventSystem system; 194 | 195 | if (!_systemsCache.TryGetValue(evType, out system)) 196 | { 197 | system = new EventHandlerStandard(); 198 | _systems.Add(system); 199 | _systemsCache[evType] = system; 200 | } 201 | 202 | _cachedSystemEventType = evType; 203 | _cacheSystem = system; 204 | 205 | return (EventHandlerStandard) system; 206 | } 207 | 208 | private EventHandlerJob GetJobSystem() 209 | where T_Job : struct, IJobForEvent 210 | where T_Event : struct 211 | { 212 | Type jobType = typeof(T_Job); 213 | 214 | if (jobType == _cachedJobSystemType) 215 | { 216 | return (EventHandlerJob) _cachedJobSystem; 217 | } 218 | 219 | IEventSystem system; 220 | 221 | if (!_jobSystemsCache.TryGetValue(typeof(T_Job), out system)) 222 | { 223 | system = new EventHandlerJob(); 224 | _systems.Add(system); 225 | _jobSystemsCache[typeof(T_Job)] = system; 226 | } 227 | 228 | _cachedJobSystemType = jobType; 229 | _cachedJobSystem = system; 230 | 231 | return (EventHandlerJob) system; 232 | } 233 | 234 | private List GetJobSystemsForEvent() where T_Event : struct 235 | { 236 | Type evType = typeof(T_Event); 237 | 238 | if (evType == _cachedJobSystemsType) 239 | { 240 | return _cachedJobSystems; 241 | } 242 | 243 | List list; 244 | 245 | if (!_eventToJobSystems.TryGetValue(evType, out list)) 246 | { 247 | list = new List(); 248 | _eventToJobSystems[evType] = list; 249 | } 250 | 251 | _cachedJobSystemsType = evType; 252 | _cachedJobSystems = list; 253 | 254 | return list; 255 | } 256 | } 257 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/UnityEventSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 577ef3321fe573846a63f8f8ffe12425 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/UnityEvents.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "UnityEvents", 3 | "references": [ 4 | "Unity.Jobs", 5 | "Unity.Burst", 6 | "Unity.Mathematics", 7 | "Unity.Collections" 8 | ], 9 | "optionalUnityReferences": [], 10 | "includePlatforms": [], 11 | "excludePlatforms": [], 12 | "allowUnsafeCode": false, 13 | "overrideReferences": false, 14 | "precompiledReferences": [], 15 | "autoReferenced": true, 16 | "defineConstraints": [] 17 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Scripts/UnityEvents.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f8c4ed1600e01de42a3fac384d8ac7c9 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 35c3e8bfb7053e2408e7a5f21bd49d17 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestEventManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using NUnit.Framework; 4 | using UnityEngine; 5 | using UnityEngine.TestTools; 6 | 7 | namespace UnityEvents.Test 8 | { 9 | 10 | public class TestEventManager 11 | { 12 | [TearDown] 13 | public void TearDown() 14 | { 15 | EventManager.ResetAll(); 16 | } 17 | 18 | [UnityTest] 19 | public IEnumerator TestSimpleValue() 20 | { 21 | EventTarget target = EventTarget.CreateTarget(); 22 | 23 | int value = 0; 24 | Action callback = x => { value += x.value; }; 25 | 26 | EventManager.Subscribe(target, callback, EventUpdateTick.Update); 27 | 28 | EventManager.SendEvent(target, new EvSimpleEvent(10), EventUpdateTick.Update); 29 | Assert.IsTrue(value == 0); 30 | 31 | yield return null; 32 | 33 | Assert.IsTrue(value == 10); 34 | } 35 | 36 | [UnityTest] 37 | public IEnumerator TestSimpleValueJob() 38 | { 39 | EventTarget target = EventTarget.CreateTarget(); 40 | 41 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 42 | 43 | EventManager.SubscribeWithJob(target, new TestJob(), callback, EventUpdateTick.Update); 44 | EventManager.SendEvent(target, new EvSimpleEvent(10), EventUpdateTick.Update); 45 | 46 | yield return null; 47 | } 48 | 49 | [UnityTest] 50 | public IEnumerator TestUpdateEvents() 51 | { 52 | EventTarget target = EventTarget.CreateTarget(); 53 | 54 | Action updateCallback = x => 55 | { 56 | string stacktrace = Environment.StackTrace; 57 | Assert.IsTrue(stacktrace.Contains("EventManager.Update ()")); 58 | }; 59 | 60 | Action fixedUpdateCallback = x => 61 | { 62 | string stacktrace = Environment.StackTrace; 63 | Assert.IsTrue(stacktrace.Contains("EventManager.FixedUpdate ()")); 64 | }; 65 | 66 | Action lateUpdateCallback = x => 67 | { 68 | string stacktrace = Environment.StackTrace; 69 | Assert.IsTrue(stacktrace.Contains("EventManager.LateUpdate ()")); 70 | }; 71 | 72 | EventManager.Subscribe(target, updateCallback, EventUpdateTick.Update); 73 | EventManager.Subscribe(target, fixedUpdateCallback, EventUpdateTick.FixedUpdate); 74 | EventManager.Subscribe(target, lateUpdateCallback, EventUpdateTick.LateUpdate); 75 | 76 | EventManager.SendEvent(target, new EvSimpleEvent(), EventUpdateTick.Update); 77 | EventManager.SendEvent(target, new EvSimpleEvent(), EventUpdateTick.FixedUpdate); 78 | EventManager.SendEvent(target, new EvSimpleEvent(), EventUpdateTick.LateUpdate); 79 | 80 | yield return new WaitForFixedUpdate(); 81 | yield return null; 82 | } 83 | 84 | [UnityTest] 85 | public IEnumerator TestUpdateMismatchEvent() 86 | { 87 | EventTarget target = EventTarget.CreateTarget(); 88 | 89 | int value = 0; 90 | Action callback = x => { value += 1; }; 91 | 92 | EventManager.Subscribe(target, callback, EventUpdateTick.Update); 93 | EventManager.SendEvent(target, new EvSimpleEvent(), EventUpdateTick.LateUpdate); 94 | EventManager.SendEvent(target, new EvSimpleEvent(), EventUpdateTick.FixedUpdate); 95 | 96 | yield return null; 97 | 98 | Assert.IsTrue(value == 0); 99 | 100 | EventManager.SendEvent(target, new EvSimpleEvent(), EventUpdateTick.Update); 101 | 102 | yield return null; 103 | Assert.IsTrue(value == 1); 104 | } 105 | 106 | [UnityTest] 107 | public IEnumerator TestMultipleEntities() 108 | { 109 | int value1 = 0; 110 | int value2 = 0; 111 | 112 | Action callback1 = x => { value1 += 1; }; 113 | Action callback2 = x => { value2 += 1; }; 114 | 115 | EventTarget entity1 = EventTarget.CreateTarget(); 116 | EventTarget entity2 = EventTarget.CreateTarget(); 117 | 118 | EventManager.Subscribe(entity1, callback1, EventUpdateTick.Update); 119 | EventManager.Subscribe(entity2, callback2, EventUpdateTick.Update); 120 | 121 | EventManager.SendEvent(entity1, new EvSimpleEvent(), EventUpdateTick.Update); 122 | 123 | yield return null; 124 | 125 | Assert.IsTrue(value1 == 1); 126 | Assert.IsTrue(value2 == 0); 127 | 128 | EventManager.SendEvent(entity2, new EvSimpleEvent(), EventUpdateTick.Update); 129 | 130 | yield return null; 131 | 132 | Assert.IsTrue(value1 == 1); 133 | Assert.IsTrue(value2 == 1); 134 | } 135 | 136 | [UnityTest] 137 | public IEnumerator TestMultipleEntitiesJob() 138 | { 139 | EventTarget entity1 = EventTarget.CreateTarget(); 140 | EventTarget entity2 = EventTarget.CreateTarget(); 141 | 142 | Action callback1 = x => { Assert.IsTrue(x.result == 10); }; 143 | Action callback2 = x => { Assert.IsTrue(x.result == 20); }; 144 | 145 | EventManager.SubscribeWithJob(entity1, new TestJob(), callback1, EventUpdateTick.Update); 146 | EventManager.SubscribeWithJob(entity2, new TestJob(), callback2, EventUpdateTick.Update); 147 | 148 | EventManager.SendEvent(entity1, new EvSimpleEvent(10), EventUpdateTick.Update); 149 | 150 | yield return null; 151 | 152 | EventManager.SendEvent(entity2, new EvSimpleEvent(20), EventUpdateTick.Update); 153 | 154 | yield return null; 155 | } 156 | 157 | [UnityTest] 158 | public IEnumerator TestStandardVsJob() 159 | { 160 | int value = 0; 161 | EventTarget target = EventTarget.CreateTarget(); 162 | 163 | Action callback1 = x => { Assert.IsTrue(x.result == 10); }; 164 | Action callback2 = x => { value += x.value; }; 165 | 166 | EventManager.SubscribeWithJob(target, new TestJob(), callback1, EventUpdateTick.Update); 167 | EventManager.Subscribe(target, callback2, EventUpdateTick.Update); 168 | 169 | EventManager.SendEvent(target, new EvSimpleEvent(10), EventUpdateTick.Update); 170 | 171 | yield return null; 172 | 173 | Assert.IsTrue(value == 10); 174 | } 175 | 176 | [UnityTest] 177 | public IEnumerator TestMultipleEntitiesStandardVsJob() 178 | { 179 | EventTarget entity1 = EventTarget.CreateTarget(); 180 | EventTarget entity2 = EventTarget.CreateTarget(); 181 | 182 | int value = 0; 183 | 184 | Action callback1 = x => { Assert.IsTrue(x.result == 10); }; 185 | Action callback2 = x => { value += x.value; }; 186 | 187 | EventManager.SubscribeWithJob(entity1, new TestJob(), callback1, EventUpdateTick.Update); 188 | EventManager.Subscribe(entity2, callback2, EventUpdateTick.Update); 189 | 190 | EventManager.SendEvent(entity1, new EvSimpleEvent(10), EventUpdateTick.Update); 191 | 192 | yield return null; 193 | 194 | Assert.IsTrue(value == 0); 195 | 196 | EventManager.SendEvent(entity2, new EvSimpleEvent(20), EventUpdateTick.Update); 197 | 198 | yield return null; 199 | 200 | Assert.IsTrue(value == 20); 201 | } 202 | 203 | [UnityTest] 204 | public IEnumerator TestFlush() 205 | { 206 | EventTarget target = EventTarget.CreateTarget(); 207 | 208 | int value = 0; 209 | Action callback = x => { value += x.value; }; 210 | 211 | EventManager.Subscribe(target, callback, EventUpdateTick.Update); 212 | 213 | EventManager.SendEvent(target, new EvSimpleEvent(10), EventUpdateTick.Update); 214 | 215 | EventManager.FlushAll(); 216 | Assert.IsTrue(value == 10); 217 | 218 | yield return null; 219 | 220 | Assert.IsTrue(value == 10); 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestEventManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 774afc10e75c0eb4ebceb4a277f88531 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestEventTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using UnityEvents.Internal; 4 | 5 | namespace UnityEvents.Test 6 | { 7 | public class TestEventTarget 8 | { 9 | [Test] 10 | public void TestGameObjectRange() 11 | { 12 | int minId = int.MinValue; 13 | int maxId = int.MaxValue; 14 | int allBits = unchecked((int)0xffffffff); 15 | 16 | // This represents the range for gameobjects, should only be the first 32 bits of a ulong 17 | EventTarget minTarget = new EventTarget(minId); 18 | EventTarget maxTarget = new EventTarget(maxId); 19 | EventTarget allBitsTarget = new EventTarget(allBits); 20 | 21 | ulong zeroedBits = 0xffffffff; 22 | zeroedBits <<= 32; 23 | 24 | Assert.IsTrue((minTarget.id & zeroedBits) == 0); 25 | Assert.IsTrue((maxTarget.id & zeroedBits) == 0); 26 | Assert.IsTrue((allBitsTarget.id & zeroedBits) == 0); 27 | Assert.IsTrue((EventTarget.CreateTarget().id & zeroedBits) != 0); 28 | } 29 | 30 | [Test] 31 | public void TestReservation() 32 | { 33 | EventTargetReservation reservation = EventTarget.ReserveTargets(3); 34 | EventTarget target1 = reservation.GetEntityTarget(0); 35 | EventTarget target2 = reservation.GetEntityTarget(1); 36 | EventTarget target3 = reservation.GetEntityTarget(2); 37 | 38 | Assert.IsFalse(target1.Equals(target2)); 39 | Assert.IsFalse(target2.Equals(target3)); 40 | Assert.IsFalse(target1.Equals(target3)); 41 | 42 | Assert.Throws(() => reservation.GetEntityTarget(-1)); 43 | Assert.Throws(() => reservation.GetEntityTarget(3)); 44 | } 45 | 46 | [Test] 47 | public void TestOverflow() 48 | { 49 | Assert.Throws(() => EventTarget.ReserveTargets(ulong.MaxValue)); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestEventTarget.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1538c44a666c48749ad3382cc47e3c06 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGameObjectEventSystemJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using NUnit.Framework; 4 | using UnityEngine; 5 | using UnityEngine.TestTools; 6 | using UnityEvents.Internal; 7 | using Object = UnityEngine.Object; 8 | 9 | namespace UnityEvents.Test 10 | { 11 | public class TestGameObjectEventSystemJob 12 | { 13 | private GameObject _gameObject; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _gameObject = new GameObject(); 19 | } 20 | 21 | [TearDown] 22 | public void TearDown() 23 | { 24 | if (_gameObject != null) 25 | { 26 | Object.Destroy(_gameObject); 27 | } 28 | 29 | EventManager.ResetAll(); 30 | } 31 | 32 | [UnityTest] 33 | public IEnumerator TestSimpleSubscribeAndEvent() 34 | { 35 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 36 | 37 | _gameObject.SubscribeWithJob(new TestJob(), callback); 38 | 39 | _gameObject.SendEvent(new EvSimpleEvent(10)); 40 | 41 | yield return new WaitForFixedUpdate(); 42 | 43 | _gameObject.UnsubscribeWithJob(callback); 44 | 45 | EventManager.VerifyNoSubscribersAll(); 46 | } 47 | 48 | [UnityTest] 49 | public IEnumerator TestMultipleSubscribersAndEvent() 50 | { 51 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 52 | Action callback2 = x => { Assert.IsTrue(x.result == 10); }; 53 | 54 | _gameObject.SubscribeWithJob(new TestJob(), callback); 55 | _gameObject.SubscribeWithJob(new TestJob(), callback2); 56 | 57 | _gameObject.SendEvent(new EvSimpleEvent(10)); 58 | 59 | yield return new WaitForFixedUpdate(); 60 | 61 | _gameObject.UnsubscribeWithJob(callback); 62 | _gameObject.UnsubscribeWithJob(callback2); 63 | 64 | EventManager.VerifyNoSubscribersAll(); 65 | } 66 | 67 | [UnityTest] 68 | public IEnumerator TestTwoSubscribesOneUnsubscribeEvent() 69 | { 70 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 71 | Action callback2 = x => { Assert.IsTrue(x.result == 10); }; 72 | 73 | _gameObject.SubscribeWithJob(new TestJob(), callback); 74 | _gameObject.SubscribeWithJob(new TestResetJob(), callback2); 75 | 76 | _gameObject.SendEvent(new EvSimpleEvent(10)); 77 | 78 | yield return new WaitForFixedUpdate(); 79 | 80 | _gameObject.SendEvent(new EvSimpleEvent(10)); 81 | _gameObject.UnsubscribeWithJob(callback); 82 | 83 | yield return new WaitForFixedUpdate(); 84 | 85 | _gameObject.UnsubscribeWithJob(callback2); 86 | 87 | EventManager.VerifyNoSubscribersAll(); 88 | } 89 | 90 | [Test] 91 | public void TestLingeringSubscriber() 92 | { 93 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 94 | _gameObject.SubscribeWithJob(new TestJob(), callback); 95 | 96 | Assert.Throws>(EventManager.VerifyNoSubscribersAll); 97 | } 98 | 99 | [UnityTest] 100 | public IEnumerator TestMultipleEvents() 101 | { 102 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 103 | _gameObject.SubscribeWithJob(new TestResetJob(), callback); 104 | 105 | _gameObject.SendEvent(new EvSimpleEvent(10)); 106 | 107 | yield return new WaitForFixedUpdate(); 108 | 109 | _gameObject.SendEvent(new EvSimpleEvent(10)); 110 | yield return new WaitForFixedUpdate(); 111 | 112 | _gameObject.SendEvent(new EvSimpleEvent(10)); 113 | yield return new WaitForFixedUpdate(); 114 | 115 | _gameObject.UnsubscribeWithJob(callback); 116 | 117 | EventManager.VerifyNoSubscribersAll(); 118 | } 119 | 120 | [UnityTest] 121 | public IEnumerator TestMultipleDifferentEvents() 122 | { 123 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 124 | Action callback2 = x => { Assert.IsTrue(x.result == 20); }; 125 | 126 | _gameObject.SubscribeWithJob(new TestJob(), callback); 127 | _gameObject.SubscribeWithJob(new TestJob2(), callback2); 128 | 129 | _gameObject.SendEvent(new EvSimpleEvent(10)); 130 | 131 | yield return new WaitForFixedUpdate(); 132 | 133 | _gameObject.SendEvent(new EvSimpleEvent2(20)); 134 | yield return new WaitForFixedUpdate(); 135 | 136 | _gameObject.UnsubscribeWithJob(callback); 137 | _gameObject.UnsubscribeWithJob(callback2); 138 | 139 | EventManager.VerifyNoSubscribersAll(); 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGameObjectEventSystemJob.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e30d7d5a34a321b4f8c9795f0c8b10b5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGameObjectEventSystemStandard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using NUnit.Framework; 4 | using UnityEngine; 5 | using UnityEngine.TestTools; 6 | using UnityEvents.Internal; 7 | using Object = UnityEngine.Object; 8 | 9 | namespace UnityEvents.Test 10 | { 11 | public class TestGameObjectEventSystemStandard 12 | { 13 | private GameObject _gameObject; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _gameObject = new GameObject(); 19 | } 20 | 21 | [TearDown] 22 | public void TearDown() 23 | { 24 | if (_gameObject != null) 25 | { 26 | Object.Destroy(_gameObject); 27 | } 28 | 29 | EventManager.ResetAll(); 30 | } 31 | 32 | [UnityTest] 33 | public IEnumerator TestSimpleSubscribeAndEvent() 34 | { 35 | int value = 0; 36 | Action callback = x => { value += 1; }; 37 | 38 | _gameObject.Subscribe(callback); 39 | 40 | _gameObject.SendEvent(new EvSimpleEvent()); 41 | 42 | yield return new WaitForFixedUpdate(); 43 | 44 | Assert.IsTrue(value == 1); 45 | 46 | _gameObject.Unsubscribe(callback); 47 | 48 | EventManager.VerifyNoSubscribersAll(); 49 | } 50 | 51 | [UnityTest] 52 | public IEnumerator TestMultipleSubscribersAndEvent() 53 | { 54 | int value = 0; 55 | Action callback = x => { value += 1; }; 56 | Action callback2 = x => { value += 2; }; 57 | 58 | _gameObject.Subscribe(callback); 59 | _gameObject.Subscribe(callback2); 60 | 61 | _gameObject.SendEvent(new EvSimpleEvent()); 62 | 63 | yield return new WaitForFixedUpdate(); 64 | 65 | Assert.IsTrue(value == 3); 66 | 67 | _gameObject.Unsubscribe(callback); 68 | _gameObject.Unsubscribe(callback2); 69 | 70 | EventManager.VerifyNoSubscribersAll(); 71 | } 72 | 73 | [UnityTest] 74 | public IEnumerator TestTwoSubscribesOneUnsubscribeEvent() 75 | { 76 | int value = 0; 77 | Action callback = x => { value += 1; }; 78 | Action callback2 = x => { value += 2; }; 79 | 80 | _gameObject.Subscribe(callback); 81 | _gameObject.Subscribe(callback2); 82 | 83 | _gameObject.SendEvent(new EvSimpleEvent()); 84 | 85 | yield return new WaitForFixedUpdate(); 86 | 87 | Assert.IsTrue(value == 3); 88 | 89 | _gameObject.SendEvent(new EvSimpleEvent()); 90 | _gameObject.Unsubscribe(callback); 91 | 92 | yield return new WaitForFixedUpdate(); 93 | 94 | Assert.IsTrue(value == 5); 95 | _gameObject.Unsubscribe(callback2); 96 | 97 | EventManager.VerifyNoSubscribersAll(); 98 | } 99 | 100 | [Test] 101 | public void TestLingeringSubscriber() 102 | { 103 | _gameObject.Subscribe(ev => { }); 104 | Assert.Throws>(EventManager.VerifyNoSubscribersAll); 105 | } 106 | 107 | [UnityTest] 108 | public IEnumerator TestMultipleEvents() 109 | { 110 | int value = 0; 111 | Action callback = x => { value += 1; }; 112 | 113 | _gameObject.Subscribe(callback); 114 | 115 | _gameObject.SendEvent(new EvSimpleEvent()); 116 | _gameObject.SendEvent(new EvSimpleEvent()); 117 | 118 | yield return new WaitForFixedUpdate(); 119 | 120 | Assert.IsTrue(value == 2); 121 | 122 | _gameObject.SendEvent(new EvSimpleEvent()); 123 | yield return new WaitForFixedUpdate(); 124 | 125 | Assert.IsTrue(value == 3); 126 | 127 | _gameObject.SendEvent(new EvSimpleEvent()); 128 | yield return new WaitForFixedUpdate(); 129 | 130 | Assert.IsTrue(value == 4); 131 | 132 | _gameObject.Unsubscribe(callback); 133 | 134 | EventManager.VerifyNoSubscribersAll(); 135 | } 136 | 137 | [UnityTest] 138 | public IEnumerator TestMultipleDifferentEvents() 139 | { 140 | int value1 = 0; 141 | int value2 = 0; 142 | 143 | Action callback = x => { value1 += 1; }; 144 | Action callback2 = x => { value2 += 2; }; 145 | 146 | _gameObject.Subscribe(callback); 147 | _gameObject.Subscribe(callback2); 148 | 149 | _gameObject.SendEvent(new EvSimpleEvent()); 150 | 151 | yield return new WaitForFixedUpdate(); 152 | 153 | Assert.IsTrue(value1 == 1); 154 | 155 | _gameObject.SendEvent(new EvSimpleEvent2()); 156 | yield return new WaitForFixedUpdate(); 157 | 158 | Assert.IsTrue(value2 == 2); 159 | _gameObject.Unsubscribe(callback); 160 | _gameObject.Unsubscribe(callback2); 161 | 162 | EventManager.VerifyNoSubscribersAll(); 163 | } 164 | } 165 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGameObjectEventSystemStandard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8c3538f2c55d6f948aabde34fbabf33f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGameObjectUIEventSystemJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using NUnit.Framework; 4 | using UnityEngine; 5 | using UnityEngine.TestTools; 6 | using UnityEvents.Internal; 7 | using Object = UnityEngine.Object; 8 | 9 | namespace UnityEvents.Test 10 | { 11 | public class TestGameObjectUIEventSystemJob 12 | { 13 | private GameObject _gameObject; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | _gameObject = new GameObject(); 19 | Time.timeScale = 0; 20 | } 21 | 22 | [TearDown] 23 | public void TearDown() 24 | { 25 | Time.timeScale = 1; 26 | 27 | if (_gameObject != null) 28 | { 29 | Object.Destroy(_gameObject); 30 | } 31 | 32 | EventManager.ResetAll(); 33 | } 34 | 35 | [UnityTest] 36 | public IEnumerator TestSimpleSubscribeAndEvent() 37 | { 38 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 39 | 40 | _gameObject.SubscribeUIWithJob(new TestJob(), callback); 41 | 42 | _gameObject.SendEventUI(new EvSimpleEvent(10)); 43 | 44 | yield return null; 45 | 46 | _gameObject.UnsubscribeUIWithJob(callback); 47 | 48 | EventManager.VerifyNoSubscribersAll(); 49 | } 50 | 51 | [UnityTest] 52 | public IEnumerator TestMultipleSubscribersAndEvent() 53 | { 54 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 55 | Action callback2 = x => { Assert.IsTrue(x.result == 10); }; 56 | 57 | _gameObject.SubscribeUIWithJob(new TestJob(), callback); 58 | _gameObject.SubscribeUIWithJob(new TestJob(), callback2); 59 | 60 | _gameObject.SendEventUI(new EvSimpleEvent(10)); 61 | 62 | yield return null; 63 | 64 | _gameObject.UnsubscribeUIWithJob(callback); 65 | _gameObject.UnsubscribeUIWithJob(callback2); 66 | 67 | EventManager.VerifyNoSubscribersAll(); 68 | } 69 | 70 | [UnityTest] 71 | public IEnumerator TestTwoSubscribesOneUnsubscribeEvent() 72 | { 73 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 74 | Action callback2 = x => { Assert.IsTrue(x.result == 10); }; 75 | 76 | _gameObject.SubscribeUIWithJob(new TestJob(), callback); 77 | _gameObject.SubscribeUIWithJob(new TestResetJob(), callback2); 78 | 79 | _gameObject.SendEventUI(new EvSimpleEvent(10)); 80 | 81 | yield return null; 82 | 83 | _gameObject.SendEventUI(new EvSimpleEvent(10)); 84 | _gameObject.UnsubscribeUIWithJob(callback); 85 | 86 | yield return null; 87 | 88 | _gameObject.UnsubscribeUIWithJob(callback2); 89 | 90 | EventManager.VerifyNoSubscribersAll(); 91 | } 92 | 93 | [Test] 94 | public void TestLingeringSubscriber() 95 | { 96 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 97 | _gameObject.SubscribeUIWithJob(new TestJob(), callback); 98 | 99 | Assert.Throws>(EventManager.VerifyNoSubscribersAll); 100 | } 101 | 102 | [UnityTest] 103 | public IEnumerator TestMultipleEvents() 104 | { 105 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 106 | _gameObject.SubscribeUIWithJob(new TestResetJob(), callback); 107 | 108 | _gameObject.SendEventUI(new EvSimpleEvent(10)); 109 | 110 | yield return null; 111 | 112 | _gameObject.SendEventUI(new EvSimpleEvent(10)); 113 | yield return null; 114 | 115 | _gameObject.SendEventUI(new EvSimpleEvent(10)); 116 | yield return null; 117 | 118 | _gameObject.UnsubscribeUIWithJob(callback); 119 | 120 | EventManager.VerifyNoSubscribersAll(); 121 | } 122 | 123 | [UnityTest] 124 | public IEnumerator TestMultipleDifferentEvents() 125 | { 126 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 127 | Action callback2 = x => { Assert.IsTrue(x.result == 20); }; 128 | 129 | _gameObject.SubscribeUIWithJob(new TestJob(), callback); 130 | _gameObject.SubscribeUIWithJob(new TestJob2(), callback2); 131 | 132 | _gameObject.SendEventUI(new EvSimpleEvent(10)); 133 | 134 | yield return null; 135 | 136 | _gameObject.SendEventUI(new EvSimpleEvent2(20)); 137 | yield return null; 138 | 139 | _gameObject.UnsubscribeUIWithJob(callback); 140 | _gameObject.UnsubscribeUIWithJob(callback2); 141 | 142 | EventManager.VerifyNoSubscribersAll(); 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGameObjectUIEventSystemJob.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 73bd0d02ced215042b52b2b3c1d30650 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGameObjectUIEventSystemStandard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using NUnit.Framework; 4 | using UnityEngine; 5 | using UnityEngine.TestTools; 6 | using UnityEvents.Internal; 7 | using Object = UnityEngine.Object; 8 | 9 | namespace UnityEvents.Test 10 | { 11 | public class TestGameObjectUIEventSystemStandard 12 | { 13 | private GameObject _gameObject; 14 | 15 | [SetUp] 16 | public void SetUp() 17 | { 18 | Time.timeScale = 0; 19 | _gameObject = new GameObject(); 20 | } 21 | 22 | [TearDown] 23 | public void TearDown() 24 | { 25 | Time.timeScale = 1; 26 | 27 | if (_gameObject != null) 28 | { 29 | Object.Destroy(_gameObject); 30 | } 31 | 32 | EventManager.ResetAll(); 33 | } 34 | 35 | [UnityTest] 36 | public IEnumerator TestSimpleSubscribeAndEvent() 37 | { 38 | int value = 0; 39 | Action callback = x => { value += 1; }; 40 | 41 | _gameObject.SubscribeUI(callback); 42 | 43 | _gameObject.SendEventUI(new EvSimpleEvent()); 44 | 45 | yield return null; 46 | 47 | Assert.IsTrue(value == 1); 48 | 49 | _gameObject.UnsubscribeUI(callback); 50 | 51 | EventManager.VerifyNoSubscribersAll(); 52 | } 53 | 54 | [UnityTest] 55 | public IEnumerator TestMultipleSubscribersAndEvent() 56 | { 57 | int value = 0; 58 | Action callback = x => { value += 1; }; 59 | Action callback2 = x => { value += 2; }; 60 | 61 | _gameObject.SubscribeUI(callback); 62 | _gameObject.SubscribeUI(callback2); 63 | 64 | _gameObject.SendEventUI(new EvSimpleEvent()); 65 | 66 | yield return null; 67 | 68 | Assert.IsTrue(value == 3); 69 | 70 | _gameObject.UnsubscribeUI(callback); 71 | _gameObject.UnsubscribeUI(callback2); 72 | 73 | EventManager.VerifyNoSubscribersAll(); 74 | } 75 | 76 | [UnityTest] 77 | public IEnumerator TestTwoSubscribesOneUnsubscribeEvent() 78 | { 79 | int value = 0; 80 | Action callback = x => { value += 1; }; 81 | Action callback2 = x => { value += 2; }; 82 | 83 | _gameObject.SubscribeUI(callback); 84 | _gameObject.SubscribeUI(callback2); 85 | 86 | _gameObject.SendEventUI(new EvSimpleEvent()); 87 | 88 | yield return null; 89 | 90 | Assert.IsTrue(value == 3); 91 | 92 | _gameObject.SendEventUI(new EvSimpleEvent()); 93 | _gameObject.UnsubscribeUI(callback); 94 | 95 | yield return null; 96 | 97 | Assert.IsTrue(value == 5); 98 | _gameObject.UnsubscribeUI(callback2); 99 | 100 | EventManager.VerifyNoSubscribersAll(); 101 | } 102 | 103 | [Test] 104 | public void TestLingeringSubscriber() 105 | { 106 | _gameObject.SubscribeUI(ev => { }); 107 | Assert.Throws>(EventManager.VerifyNoSubscribersAll); 108 | } 109 | 110 | [UnityTest] 111 | public IEnumerator TestMultipleEvents() 112 | { 113 | int value = 0; 114 | Action callback = x => { value += 1; }; 115 | 116 | _gameObject.SubscribeUI(callback); 117 | 118 | _gameObject.SendEventUI(new EvSimpleEvent()); 119 | _gameObject.SendEventUI(new EvSimpleEvent()); 120 | 121 | yield return null; 122 | 123 | Assert.IsTrue(value == 2); 124 | 125 | _gameObject.SendEventUI(new EvSimpleEvent()); 126 | yield return null; 127 | 128 | Assert.IsTrue(value == 3); 129 | 130 | _gameObject.SendEventUI(new EvSimpleEvent()); 131 | yield return null; 132 | 133 | Assert.IsTrue(value == 4); 134 | 135 | _gameObject.UnsubscribeUI(callback); 136 | 137 | EventManager.VerifyNoSubscribersAll(); 138 | } 139 | 140 | [UnityTest] 141 | public IEnumerator TestMultipleDifferentEvents() 142 | { 143 | int value1 = 0; 144 | int value2 = 0; 145 | 146 | Action callback = x => { value1 += 1; }; 147 | Action callback2 = x => { value2 += 2; }; 148 | 149 | _gameObject.SubscribeUI(callback); 150 | _gameObject.SubscribeUI(callback2); 151 | 152 | _gameObject.SendEventUI(new EvSimpleEvent()); 153 | 154 | yield return null; 155 | 156 | Assert.IsTrue(value1 == 1); 157 | 158 | _gameObject.SendEventUI(new EvSimpleEvent2()); 159 | yield return null; 160 | 161 | Assert.IsTrue(value2 == 2); 162 | _gameObject.UnsubscribeUI(callback); 163 | _gameObject.UnsubscribeUI(callback2); 164 | 165 | EventManager.VerifyNoSubscribersAll(); 166 | } 167 | } 168 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGameObjectUIEventSystemStandard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb084504ebd27a240b239042dacb2415 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGlobalEventSystemJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using NUnit.Framework; 4 | using UnityEngine; 5 | using UnityEngine.TestTools; 6 | using UnityEvents.Internal; 7 | 8 | namespace UnityEvents.Test 9 | { 10 | public class TestGlobalEventSystemJob 11 | { 12 | [TearDown] 13 | public void TearDown() 14 | { 15 | EventManager.ResetAll(); 16 | } 17 | 18 | [UnityTest] 19 | public IEnumerator TestSimpleSubscribeAndEvent() 20 | { 21 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 22 | 23 | GlobalEventSystem.SubscribeWithJob(new TestJob(), callback); 24 | 25 | GlobalEventSystem.SendEvent(new EvSimpleEvent(10)); 26 | 27 | yield return new WaitForFixedUpdate(); 28 | 29 | GlobalEventSystem.UnsubscribeWithJob(callback); 30 | 31 | EventManager.VerifyNoSubscribersAll(); 32 | } 33 | 34 | [UnityTest] 35 | public IEnumerator TestMultipleSubscribersAndEvent() 36 | { 37 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 38 | Action callback2 = x => { Assert.IsTrue(x.result == 10); }; 39 | 40 | GlobalEventSystem.SubscribeWithJob(new TestJob(), callback); 41 | GlobalEventSystem.SubscribeWithJob(new TestJob(), callback2); 42 | 43 | GlobalEventSystem.SendEvent(new EvSimpleEvent(10)); 44 | 45 | yield return new WaitForFixedUpdate(); 46 | 47 | GlobalEventSystem.UnsubscribeWithJob(callback); 48 | GlobalEventSystem.UnsubscribeWithJob(callback2); 49 | 50 | EventManager.VerifyNoSubscribersAll(); 51 | } 52 | 53 | [UnityTest] 54 | public IEnumerator TestTwoSubscribesOneUnsubscribeEvent() 55 | { 56 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 57 | Action callback2 = x => { Assert.IsTrue(x.result == 10); }; 58 | 59 | GlobalEventSystem.SubscribeWithJob(new TestJob(), callback); 60 | GlobalEventSystem.SubscribeWithJob(new TestResetJob(), callback2); 61 | 62 | GlobalEventSystem.SendEvent(new EvSimpleEvent(10)); 63 | 64 | yield return new WaitForFixedUpdate(); 65 | 66 | GlobalEventSystem.SendEvent(new EvSimpleEvent(10)); 67 | GlobalEventSystem.UnsubscribeWithJob(callback); 68 | 69 | yield return new WaitForFixedUpdate(); 70 | 71 | GlobalEventSystem.UnsubscribeWithJob(callback2); 72 | 73 | EventManager.VerifyNoSubscribersAll(); 74 | } 75 | 76 | [Test] 77 | public void TestLingeringSubscriber() 78 | { 79 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 80 | GlobalEventSystem.SubscribeWithJob(new TestJob(), callback); 81 | 82 | Assert.Throws>(EventManager.VerifyNoSubscribersAll); 83 | } 84 | 85 | [UnityTest] 86 | public IEnumerator TestMultipleEvents() 87 | { 88 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 89 | GlobalEventSystem.SubscribeWithJob(new TestResetJob(), callback); 90 | 91 | GlobalEventSystem.SendEvent(new EvSimpleEvent(10)); 92 | 93 | yield return new WaitForFixedUpdate(); 94 | 95 | GlobalEventSystem.SendEvent(new EvSimpleEvent(10)); 96 | yield return new WaitForFixedUpdate(); 97 | 98 | GlobalEventSystem.SendEvent(new EvSimpleEvent(10)); 99 | yield return new WaitForFixedUpdate(); 100 | 101 | GlobalEventSystem.UnsubscribeWithJob(callback); 102 | 103 | EventManager.VerifyNoSubscribersAll(); 104 | } 105 | 106 | [UnityTest] 107 | public IEnumerator TestMultipleDifferentEvents() 108 | { 109 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 110 | Action callback2 = x => { Assert.IsTrue(x.result == 20); }; 111 | 112 | GlobalEventSystem.SubscribeWithJob(new TestJob(), callback); 113 | GlobalEventSystem.SubscribeWithJob(new TestJob2(), callback2); 114 | 115 | GlobalEventSystem.SendEvent(new EvSimpleEvent(10)); 116 | 117 | yield return new WaitForFixedUpdate(); 118 | 119 | GlobalEventSystem.SendEvent(new EvSimpleEvent2(20)); 120 | yield return new WaitForFixedUpdate(); 121 | 122 | GlobalEventSystem.UnsubscribeWithJob(callback); 123 | GlobalEventSystem.UnsubscribeWithJob(callback2); 124 | 125 | EventManager.VerifyNoSubscribersAll(); 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGlobalEventSystemJob.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4a59ab90a07dedd4381da973d5becd04 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGlobalEventSystemStandard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using NUnit.Framework; 4 | using UnityEngine; 5 | using UnityEngine.TestTools; 6 | using UnityEvents.Internal; 7 | 8 | namespace UnityEvents.Test 9 | { 10 | public class TestGlobalEventSystemStandard 11 | { 12 | [TearDown] 13 | public void TearDown() 14 | { 15 | EventManager.ResetAll(); 16 | } 17 | 18 | [UnityTest] 19 | public IEnumerator TestSimpleSubscribeAndEvent() 20 | { 21 | int value = 0; 22 | Action callback = x => { value += 1; }; 23 | 24 | GlobalEventSystem.Subscribe(callback); 25 | 26 | GlobalEventSystem.SendEvent(new EvSimpleEvent()); 27 | 28 | yield return new WaitForFixedUpdate(); 29 | 30 | Assert.IsTrue(value == 1); 31 | 32 | GlobalEventSystem.Unsubscribe(callback); 33 | 34 | EventManager.VerifyNoSubscribersAll(); 35 | } 36 | 37 | [UnityTest] 38 | public IEnumerator TestMultipleSubscribersAndEvent() 39 | { 40 | int value = 0; 41 | Action callback = x => { value += 1; }; 42 | Action callback2 = x => { value += 2; }; 43 | 44 | GlobalEventSystem.Subscribe(callback); 45 | GlobalEventSystem.Subscribe(callback2); 46 | 47 | GlobalEventSystem.SendEvent(new EvSimpleEvent()); 48 | 49 | yield return new WaitForFixedUpdate(); 50 | 51 | Assert.IsTrue(value == 3); 52 | 53 | GlobalEventSystem.Unsubscribe(callback); 54 | GlobalEventSystem.Unsubscribe(callback2); 55 | 56 | EventManager.VerifyNoSubscribersAll(); 57 | } 58 | 59 | [UnityTest] 60 | public IEnumerator TestTwoSubscribesOneUnsubscribeEvent() 61 | { 62 | int value = 0; 63 | Action callback = x => { value += 1; }; 64 | Action callback2 = x => { value += 2; }; 65 | 66 | GlobalEventSystem.Subscribe(callback); 67 | GlobalEventSystem.Subscribe(callback2); 68 | 69 | GlobalEventSystem.SendEvent(new EvSimpleEvent()); 70 | 71 | yield return new WaitForFixedUpdate(); 72 | 73 | Assert.IsTrue(value == 3); 74 | 75 | GlobalEventSystem.SendEvent(new EvSimpleEvent()); 76 | GlobalEventSystem.Unsubscribe(callback); 77 | 78 | yield return new WaitForFixedUpdate(); 79 | 80 | Assert.IsTrue(value == 5); 81 | GlobalEventSystem.Unsubscribe(callback2); 82 | 83 | EventManager.VerifyNoSubscribersAll(); 84 | } 85 | 86 | [Test] 87 | public void TestLingeringSubscriber() 88 | { 89 | GlobalEventSystem.Subscribe(ev => { }); 90 | Assert.Throws>(EventManager.VerifyNoSubscribersAll); 91 | } 92 | 93 | [UnityTest] 94 | public IEnumerator TestMultipleEvents() 95 | { 96 | int value = 0; 97 | Action callback = x => { value += 1; }; 98 | 99 | GlobalEventSystem.Subscribe(callback); 100 | 101 | GlobalEventSystem.SendEvent(new EvSimpleEvent()); 102 | GlobalEventSystem.SendEvent(new EvSimpleEvent()); 103 | 104 | yield return new WaitForFixedUpdate(); 105 | 106 | Assert.IsTrue(value == 2); 107 | 108 | GlobalEventSystem.SendEvent(new EvSimpleEvent()); 109 | yield return new WaitForFixedUpdate(); 110 | 111 | Assert.IsTrue(value == 3); 112 | 113 | GlobalEventSystem.SendEvent(new EvSimpleEvent()); 114 | yield return new WaitForFixedUpdate(); 115 | 116 | Assert.IsTrue(value == 4); 117 | 118 | GlobalEventSystem.Unsubscribe(callback); 119 | 120 | EventManager.VerifyNoSubscribersAll(); 121 | } 122 | 123 | [UnityTest] 124 | public IEnumerator TestMultipleDifferentEvents() 125 | { 126 | int value1 = 0; 127 | int value2 = 0; 128 | 129 | Action callback = x => { value1 += 1; }; 130 | Action callback2 = x => { value2 += 2; }; 131 | 132 | GlobalEventSystem.Subscribe(callback); 133 | GlobalEventSystem.Subscribe(callback2); 134 | 135 | GlobalEventSystem.SendEvent(new EvSimpleEvent()); 136 | 137 | yield return new WaitForFixedUpdate(); 138 | 139 | Assert.IsTrue(value1 == 1); 140 | 141 | GlobalEventSystem.SendEvent(new EvSimpleEvent2()); 142 | yield return new WaitForFixedUpdate(); 143 | 144 | Assert.IsTrue(value2 == 2); 145 | GlobalEventSystem.Unsubscribe(callback); 146 | GlobalEventSystem.Unsubscribe(callback2); 147 | 148 | EventManager.VerifyNoSubscribersAll(); 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGlobalEventSystemStandard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec8e2d536f1e6c2479fc0c7ad34b638e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGlobalUIEventSystemJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using NUnit.Framework; 4 | using UnityEngine; 5 | using UnityEngine.TestTools; 6 | using UnityEvents.Internal; 7 | 8 | namespace UnityEvents.Test 9 | { 10 | public class TestGlobalUIEventSystemJob 11 | { 12 | [SetUp] 13 | public void Setup() 14 | { 15 | Time.timeScale = 0; 16 | } 17 | 18 | [TearDown] 19 | public void TearDown() 20 | { 21 | Time.timeScale = 1; 22 | EventManager.ResetAll(); 23 | } 24 | 25 | [UnityTest] 26 | public IEnumerator TestSimpleSubscribeAndEvent() 27 | { 28 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 29 | 30 | GlobalEventSystem.SubscribeUIWithJob(new TestJob(), callback); 31 | 32 | GlobalEventSystem.SendEventUI(new EvSimpleEvent(10)); 33 | 34 | yield return null; 35 | 36 | GlobalEventSystem.UnsubscribeUIWithJob(callback); 37 | 38 | EventManager.VerifyNoSubscribersAll(); 39 | } 40 | 41 | [UnityTest] 42 | public IEnumerator TestMultipleSubscribersAndEvent() 43 | { 44 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 45 | Action callback2 = x => { Assert.IsTrue(x.result == 10); }; 46 | 47 | GlobalEventSystem.SubscribeUIWithJob(new TestJob(), callback); 48 | GlobalEventSystem.SubscribeUIWithJob(new TestJob(), callback2); 49 | 50 | GlobalEventSystem.SendEventUI(new EvSimpleEvent(10)); 51 | 52 | yield return null; 53 | 54 | GlobalEventSystem.UnsubscribeUIWithJob(callback); 55 | GlobalEventSystem.UnsubscribeUIWithJob(callback2); 56 | 57 | EventManager.VerifyNoSubscribersAll(); 58 | } 59 | 60 | [UnityTest] 61 | public IEnumerator TestTwoSubscribesOneUnsubscribeEvent() 62 | { 63 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 64 | Action callback2 = x => { Assert.IsTrue(x.result == 10); }; 65 | 66 | GlobalEventSystem.SubscribeUIWithJob(new TestJob(), callback); 67 | GlobalEventSystem.SubscribeUIWithJob(new TestResetJob(), callback2); 68 | 69 | GlobalEventSystem.SendEventUI(new EvSimpleEvent(10)); 70 | 71 | yield return null; 72 | 73 | GlobalEventSystem.SendEventUI(new EvSimpleEvent(10)); 74 | GlobalEventSystem.UnsubscribeUIWithJob(callback); 75 | 76 | yield return null; 77 | 78 | GlobalEventSystem.UnsubscribeUIWithJob(callback2); 79 | 80 | EventManager.VerifyNoSubscribersAll(); 81 | } 82 | 83 | [Test] 84 | public void TestLingeringSubscriber() 85 | { 86 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 87 | GlobalEventSystem.SubscribeUIWithJob(new TestJob(), callback); 88 | 89 | Assert.Throws>(EventManager.VerifyNoSubscribersAll); 90 | } 91 | 92 | [UnityTest] 93 | public IEnumerator TestMultipleEvents() 94 | { 95 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 96 | GlobalEventSystem.SubscribeUIWithJob(new TestResetJob(), callback); 97 | 98 | GlobalEventSystem.SendEventUI(new EvSimpleEvent(10)); 99 | 100 | yield return null; 101 | 102 | GlobalEventSystem.SendEventUI(new EvSimpleEvent(10)); 103 | yield return null; 104 | 105 | GlobalEventSystem.SendEventUI(new EvSimpleEvent(10)); 106 | yield return null; 107 | 108 | GlobalEventSystem.UnsubscribeUIWithJob(callback); 109 | 110 | EventManager.VerifyNoSubscribersAll(); 111 | } 112 | 113 | [UnityTest] 114 | public IEnumerator TestMultipleDifferentEvents() 115 | { 116 | Action callback = x => { Assert.IsTrue(x.result == 10); }; 117 | Action callback2 = x => { Assert.IsTrue(x.result == 20); }; 118 | 119 | GlobalEventSystem.SubscribeUIWithJob(new TestJob(), callback); 120 | GlobalEventSystem.SubscribeUIWithJob(new TestJob2(), callback2); 121 | 122 | GlobalEventSystem.SendEventUI(new EvSimpleEvent(10)); 123 | 124 | yield return null; 125 | 126 | GlobalEventSystem.SendEventUI(new EvSimpleEvent2(20)); 127 | yield return null; 128 | 129 | GlobalEventSystem.UnsubscribeUIWithJob(callback); 130 | GlobalEventSystem.UnsubscribeUIWithJob(callback2); 131 | 132 | EventManager.VerifyNoSubscribersAll(); 133 | } 134 | } 135 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGlobalUIEventSystemJob.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e9bf9be3a2f650e46a51c8d5420ac679 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGlobalUIEventSystemStandard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using NUnit.Framework; 4 | using UnityEngine; 5 | using UnityEngine.TestTools; 6 | using UnityEvents.Internal; 7 | 8 | namespace UnityEvents.Test 9 | { 10 | public class TestGlobalUIEventSystemStandard 11 | { 12 | [SetUp] 13 | public void Setup() 14 | { 15 | Time.timeScale = 0; 16 | } 17 | 18 | [TearDown] 19 | public void TearDown() 20 | { 21 | Time.timeScale = 1; 22 | EventManager.ResetAll(); 23 | } 24 | 25 | [UnityTest] 26 | public IEnumerator TestSimpleSubscribeAndEvent() 27 | { 28 | int value = 0; 29 | Action callback = x => { value += 1; }; 30 | 31 | GlobalEventSystem.SubscribeUI(callback); 32 | 33 | GlobalEventSystem.SendEventUI(new EvSimpleEvent()); 34 | 35 | yield return null; 36 | 37 | Assert.IsTrue(value == 1); 38 | 39 | GlobalEventSystem.UnsubscribeUI(callback); 40 | 41 | EventManager.VerifyNoSubscribersAll(); 42 | } 43 | 44 | [UnityTest] 45 | public IEnumerator TestMultipleSubscribersAndEvent() 46 | { 47 | int value = 0; 48 | Action callback = x => { value += 1; }; 49 | Action callback2 = x => { value += 2; }; 50 | 51 | GlobalEventSystem.SubscribeUI(callback); 52 | GlobalEventSystem.SubscribeUI(callback2); 53 | 54 | GlobalEventSystem.SendEventUI(new EvSimpleEvent()); 55 | 56 | yield return null; 57 | 58 | Assert.IsTrue(value == 3); 59 | 60 | GlobalEventSystem.UnsubscribeUI(callback); 61 | GlobalEventSystem.UnsubscribeUI(callback2); 62 | 63 | EventManager.VerifyNoSubscribersAll(); 64 | } 65 | 66 | [UnityTest] 67 | public IEnumerator TestTwoSubscribesOneUnsubscribeEvent() 68 | { 69 | int value = 0; 70 | Action callback = x => { value += 1; }; 71 | Action callback2 = x => { value += 2; }; 72 | 73 | GlobalEventSystem.SubscribeUI(callback); 74 | GlobalEventSystem.SubscribeUI(callback2); 75 | 76 | GlobalEventSystem.SendEventUI(new EvSimpleEvent()); 77 | 78 | yield return null; 79 | 80 | Assert.IsTrue(value == 3); 81 | 82 | GlobalEventSystem.SendEventUI(new EvSimpleEvent()); 83 | GlobalEventSystem.UnsubscribeUI(callback); 84 | 85 | yield return null; 86 | 87 | Assert.IsTrue(value == 5); 88 | GlobalEventSystem.UnsubscribeUI(callback2); 89 | 90 | EventManager.VerifyNoSubscribersAll(); 91 | } 92 | 93 | [Test] 94 | public void TestLingeringSubscriber() 95 | { 96 | GlobalEventSystem.SubscribeUI(ev => { }); 97 | Assert.Throws>(EventManager 98 | .VerifyNoSubscribersAll); 99 | } 100 | 101 | [UnityTest] 102 | public IEnumerator TestMultipleEvents() 103 | { 104 | int value = 0; 105 | Action callback = x => { value += 1; }; 106 | 107 | GlobalEventSystem.SubscribeUI(callback); 108 | 109 | GlobalEventSystem.SendEventUI(new EvSimpleEvent()); 110 | GlobalEventSystem.SendEventUI(new EvSimpleEvent()); 111 | 112 | yield return null; 113 | 114 | Assert.IsTrue(value == 2); 115 | 116 | GlobalEventSystem.SendEventUI(new EvSimpleEvent()); 117 | yield return null; 118 | 119 | Assert.IsTrue(value == 3); 120 | 121 | GlobalEventSystem.SendEventUI(new EvSimpleEvent()); 122 | yield return null; 123 | 124 | Assert.IsTrue(value == 4); 125 | 126 | GlobalEventSystem.UnsubscribeUI(callback); 127 | 128 | EventManager.VerifyNoSubscribersAll(); 129 | } 130 | 131 | [UnityTest] 132 | public IEnumerator TestMultipleDifferentEvents() 133 | { 134 | int value1 = 0; 135 | int value2 = 0; 136 | 137 | Action callback = x => { value1 += 1; }; 138 | Action callback2 = x => { value2 += 2; }; 139 | 140 | GlobalEventSystem.SubscribeUI(callback); 141 | GlobalEventSystem.SubscribeUI(callback2); 142 | 143 | GlobalEventSystem.SendEventUI(new EvSimpleEvent()); 144 | 145 | yield return null; 146 | 147 | Assert.IsTrue(value1 == 1); 148 | 149 | GlobalEventSystem.SendEventUI(new EvSimpleEvent2()); 150 | yield return null; 151 | 152 | Assert.IsTrue(value2 == 2); 153 | GlobalEventSystem.UnsubscribeUI(callback); 154 | GlobalEventSystem.UnsubscribeUI(callback2); 155 | 156 | EventManager.VerifyNoSubscribersAll(); 157 | } 158 | } 159 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestGlobalUIEventSystemStandard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5ae0f2a51a8b2f1498bec70ccf23b898 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestUnityEventJobSystem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using UnityEvents.Internal; 4 | 5 | namespace UnityEvents.Test 6 | { 7 | public class TestUnityEventJobSystem 8 | { 9 | private EventHandlerJob _handler; 10 | 11 | [SetUp] 12 | public void SetUp() 13 | { 14 | _handler = new EventHandlerJob(); 15 | } 16 | 17 | [TearDown] 18 | public void TearDown() 19 | { 20 | _handler.Reset(); 21 | _handler.Dispose(); 22 | } 23 | 24 | [Test] 25 | public void TestSimpleEvent() 26 | { 27 | EventTarget target = EventTarget.CreateTarget(); 28 | 29 | int value = 10; 30 | 31 | Action callback = x => { Assert.IsTrue(x.result == value); }; 32 | 33 | _handler.Subscribe(target, new TestJob(value), callback); 34 | 35 | _handler.QueueEvent(target, new EvSimpleEvent(10)); 36 | value = 20; 37 | _handler.ProcessEvents(); 38 | 39 | _handler.Unsubscribe(target, callback); 40 | _handler.VerifyNoSubscribers(); 41 | 42 | _handler.QueueEvent(target, new EvSimpleEvent(10)); 43 | _handler.ProcessEvents(); 44 | } 45 | 46 | [Test] 47 | public void TestOtherUnsubscribe() 48 | { 49 | EventTarget target1 = EventTarget.CreateTarget(); 50 | EventTarget target2 = EventTarget.CreateTarget(); 51 | 52 | int value = 5; 53 | 54 | Action callback = x => { Assert.IsTrue(x.result == value); }; 55 | Action callback2 = x => { Assert.Fail(); }; 56 | 57 | _handler.Subscribe(target1, new TestJob(value), callback); 58 | _handler.Subscribe(target2, new TestJob(value), callback2); 59 | _handler.Unsubscribe(target2, callback2); 60 | _handler.QueueEvent(target1, new EvSimpleEvent(10)); 61 | 62 | value = 15; 63 | _handler.ProcessEvents(); 64 | _handler.Unsubscribe(target1, callback); 65 | _handler.VerifyNoSubscribers(); 66 | } 67 | 68 | [Test] 69 | public void TestMeUnsubscribe() 70 | { 71 | EventTarget target1 = EventTarget.CreateTarget(); 72 | EventTarget target2 = EventTarget.CreateTarget(); 73 | 74 | int value = -1; 75 | 76 | Action callback = x => { Assert.Fail(); }; 77 | 78 | _handler.Subscribe(target1, new TestJob(value), callback); 79 | _handler.Subscribe(target2, new TestJob(value), callback); 80 | _handler.Unsubscribe(target1, callback); 81 | _handler.QueueEvent(target1, new EvSimpleEvent(10)); 82 | 83 | _handler.ProcessEvents(); 84 | _handler.Unsubscribe(target2, callback); 85 | _handler.VerifyNoSubscribers(); 86 | 87 | Assert.IsTrue(value == -1); 88 | } 89 | 90 | [Test] 91 | public void TestMultipleEvents() 92 | { 93 | EventTarget target = EventTarget.CreateTarget(); 94 | 95 | int value = -1; 96 | 97 | Action callback = x => { Assert.IsTrue(x.result == value); }; 98 | 99 | _handler.Subscribe(target, new TestJob(value), callback); 100 | 101 | // Should warn! 102 | _handler.QueueEvent(target, new EvSimpleEvent(10)); 103 | _handler.QueueEvent(target, new EvSimpleEvent(10)); 104 | _handler.QueueEvent(target, new EvSimpleEvent(10)); 105 | _handler.QueueEvent(target, new EvSimpleEvent(10)); 106 | 107 | // Only one event is accepted 108 | value = 9; 109 | _handler.ProcessEvents(); 110 | 111 | _handler.Unsubscribe(target, callback); 112 | _handler.VerifyNoSubscribers(); 113 | 114 | _handler.QueueEvent(target, new EvSimpleEvent(10)); 115 | _handler.ProcessEvents(); 116 | } 117 | 118 | [Test] 119 | public void TestMultipleSubscribes() 120 | { 121 | EventTarget target = EventTarget.CreateTarget(); 122 | 123 | Action callback = x => { }; 124 | 125 | _handler.Subscribe(target, new TestJob(), callback); 126 | 127 | Assert.Throws>(() => 128 | _handler.Subscribe(target, new TestJob(), callback)); 129 | } 130 | 131 | [Test] 132 | public void TestMultipleEntities() 133 | { 134 | EventTarget target1 = EventTarget.CreateTarget(); 135 | EventTarget target2 = EventTarget.CreateTarget(); 136 | 137 | int value1 = 1; 138 | int value2 = 11; 139 | 140 | Action callback = x => { Assert.IsTrue(x.result == value1); }; 141 | Action callback2 = x => { Assert.IsTrue(x.result == value2); }; 142 | 143 | _handler.Subscribe(target1, new TestJob(value1), callback); 144 | _handler.Subscribe(target2, new TestJob(value2), callback2); 145 | _handler.QueueEvent(target1, new EvSimpleEvent(10)); 146 | _handler.QueueEvent(target2, new EvSimpleEvent(30)); 147 | 148 | value1 = 11; 149 | value2 = 41; 150 | 151 | _handler.ProcessEvents(); 152 | _handler.Unsubscribe(target1, callback); 153 | _handler.Unsubscribe(target2, callback2); 154 | _handler.VerifyNoSubscribers(); 155 | } 156 | 157 | [Test] 158 | public void TestMultipleSubscribeUnsubscribesEvents() 159 | { 160 | EventTarget target1 = EventTarget.CreateTarget(); 161 | EventTarget target2 = EventTarget.CreateTarget(); 162 | 163 | int value1 = 0; 164 | int value2 = 0; 165 | 166 | Action callback = x => { Assert.IsTrue(x.result == value1); }; 167 | Action callback2 = x => { Assert.IsTrue(x.result == value2); }; 168 | 169 | _handler.Subscribe(target1, new TestJob(value1), callback); 170 | _handler.Subscribe(target2, new TestJob(value2), callback2); 171 | _handler.Unsubscribe(target2, callback2); 172 | 173 | _handler.QueueEvent(target1, new EvSimpleEvent(10)); 174 | _handler.QueueEvent(target2, new EvSimpleEvent(30)); 175 | 176 | value1 = 10; 177 | Assert.IsTrue(value2 == 0); 178 | _handler.ProcessEvents(); 179 | 180 | _handler.Subscribe(target2, new TestJob(value2), callback2); 181 | 182 | _handler.QueueEvent(target1, new EvSimpleEvent(10)); 183 | _handler.QueueEvent(target2, new EvSimpleEvent(30)); 184 | 185 | value1 = 20; 186 | value2 = 30; 187 | _handler.ProcessEvents(); 188 | 189 | _handler.Unsubscribe(target1, callback); 190 | 191 | _handler.QueueEvent(target1, new EvSimpleEvent(10)); 192 | _handler.QueueEvent(target2, new EvSimpleEvent(30)); 193 | 194 | Assert.IsTrue(value1 == 20); 195 | value2 = 60; 196 | _handler.ProcessEvents(); 197 | 198 | _handler.Subscribe(target1, new TestJob(value1), callback); 199 | 200 | _handler.QueueEvent(target1, new EvSimpleEvent(10)); 201 | _handler.QueueEvent(target2, new EvSimpleEvent(30)); 202 | 203 | value1 = 30; 204 | value2 = 90; 205 | _handler.ProcessEvents(); 206 | 207 | _handler.Unsubscribe(target2, callback2); 208 | 209 | _handler.QueueEvent(target1, new EvSimpleEvent(10)); 210 | _handler.QueueEvent(target2, new EvSimpleEvent(30)); 211 | 212 | value1 = 40; 213 | Assert.IsTrue(value2 == 90); 214 | _handler.ProcessEvents(); 215 | 216 | _handler.Unsubscribe(target1, callback); 217 | 218 | _handler.QueueEvent(target1, new EvSimpleEvent(10)); 219 | _handler.QueueEvent(target2, new EvSimpleEvent(30)); 220 | _handler.ProcessEvents(); 221 | 222 | _handler.VerifyNoSubscribers(); 223 | 224 | Assert.IsTrue(value1 == 40); 225 | Assert.IsTrue(value2 == 90); 226 | } 227 | 228 | [Test] 229 | public void TestUnblittableEvent() 230 | { 231 | Assert.Throws(() => 232 | { 233 | EventHandlerJob system = 234 | new EventHandlerJob(); 235 | }); 236 | 237 | Assert.Throws(() => 238 | { 239 | EventHandlerJob system = 240 | new EventHandlerJob(); 241 | }); 242 | } 243 | } 244 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestUnityEventJobSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e968ef5503146c142923eef65a19e320 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestUnityEventStandardSystem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using UnityEvents.Internal; 4 | 5 | namespace UnityEvents.Test 6 | { 7 | public class TestUnityEventStandardSystem 8 | { 9 | private EventHandlerStandard _system; 10 | 11 | [SetUp] 12 | public void SetUp() 13 | { 14 | _system = new EventHandlerStandard(); 15 | } 16 | 17 | [TearDown] 18 | public void TearDown() 19 | { 20 | _system.Reset(); 21 | _system.Dispose(); 22 | } 23 | 24 | [Test] 25 | public void TestSimpleEvent() 26 | { 27 | EventTarget target = EventTarget.CreateTarget(); 28 | 29 | int value = 0; 30 | 31 | Action callback = x => value += x.value; 32 | 33 | _system.Subscribe(target, callback); 34 | 35 | _system.QueueEvent(target, new EvSimpleEvent(10)); 36 | _system.ProcessEvents(); 37 | 38 | _system.Unsubscribe(target, callback); 39 | _system.VerifyNoSubscribers(); 40 | 41 | _system.QueueEvent(target, new EvSimpleEvent(10)); 42 | _system.ProcessEvents(); 43 | 44 | Assert.IsTrue(value == 10); 45 | } 46 | 47 | [Test] 48 | public void TestOtherUnsubscribe() 49 | { 50 | EventTarget target1 = EventTarget.CreateTarget(); 51 | EventTarget target2 = EventTarget.CreateTarget(); 52 | 53 | int value = 0; 54 | 55 | Action callback = x => value += x.value; 56 | 57 | _system.Subscribe(target1, callback); 58 | _system.Subscribe(target2, callback); 59 | _system.Unsubscribe(target2, callback); 60 | _system.QueueEvent(target1, new EvSimpleEvent(10)); 61 | 62 | _system.ProcessEvents(); 63 | _system.Unsubscribe(target1, callback); 64 | _system.VerifyNoSubscribers(); 65 | 66 | Assert.IsTrue(value == 10); 67 | } 68 | 69 | [Test] 70 | public void TestMeUnsubscribe() 71 | { 72 | EventTarget target1 = EventTarget.CreateTarget(); 73 | EventTarget target2 = EventTarget.CreateTarget(); 74 | 75 | int value = 0; 76 | 77 | Action callback = x => value += x.value; 78 | 79 | _system.Subscribe(target1, callback); 80 | _system.Subscribe(target2, callback); 81 | _system.Unsubscribe(target1, callback); 82 | _system.QueueEvent(target1, new EvSimpleEvent(10)); 83 | 84 | _system.ProcessEvents(); 85 | _system.Unsubscribe(target2, callback); 86 | _system.VerifyNoSubscribers(); 87 | 88 | Assert.IsTrue(value == 0); 89 | } 90 | 91 | [Test] 92 | public void TestMultipleEvents() 93 | { 94 | EventTarget target = EventTarget.CreateTarget(); 95 | 96 | int value = 0; 97 | 98 | Action callback = x => value += x.value; 99 | 100 | _system.Subscribe(target, callback); 101 | 102 | _system.QueueEvent(target, new EvSimpleEvent(10)); 103 | _system.QueueEvent(target, new EvSimpleEvent(10)); 104 | _system.QueueEvent(target, new EvSimpleEvent(10)); 105 | _system.QueueEvent(target, new EvSimpleEvent(10)); 106 | _system.ProcessEvents(); 107 | 108 | _system.Unsubscribe(target, callback); 109 | _system.VerifyNoSubscribers(); 110 | 111 | _system.QueueEvent(target, new EvSimpleEvent(10)); 112 | _system.ProcessEvents(); 113 | 114 | Assert.IsTrue(value == 40); 115 | } 116 | 117 | [Test] 118 | public void TestMultipleEntities() 119 | { 120 | EventTarget target1 = EventTarget.CreateTarget(); 121 | EventTarget target2 = EventTarget.CreateTarget(); 122 | 123 | int value1 = 0; 124 | int value2 = 0; 125 | 126 | Action callback = x => value1 += x.value; 127 | Action callback2 = x => value2 += x.value; 128 | 129 | _system.Subscribe(target1, callback); 130 | _system.Subscribe(target2, callback2); 131 | _system.QueueEvent(target1, new EvSimpleEvent(10)); 132 | _system.QueueEvent(target2, new EvSimpleEvent(30)); 133 | 134 | _system.ProcessEvents(); 135 | _system.Unsubscribe(target1, callback); 136 | _system.Unsubscribe(target2, callback2); 137 | _system.VerifyNoSubscribers(); 138 | 139 | Assert.IsTrue(value1 == 10); 140 | Assert.IsTrue(value2 == 30); 141 | } 142 | 143 | [Test] 144 | public void TestMultipleSubscribes() 145 | { 146 | EventTarget target = EventTarget.CreateTarget(); 147 | 148 | Action callback = x => { }; 149 | 150 | _system.Subscribe(target, callback); 151 | 152 | Assert.Throws>(() => _system.Subscribe(target, callback)); 153 | } 154 | 155 | [Test] 156 | public void TestMultipleSubscribeUnsubscribesEvents() 157 | { 158 | EventTarget target1 = EventTarget.CreateTarget(); 159 | EventTarget target2 = EventTarget.CreateTarget(); 160 | 161 | int value1 = 0; 162 | int value2 = 0; 163 | 164 | Action callback = x => value1 += x.value; 165 | Action callback2 = x => value2 += x.value; 166 | 167 | _system.Subscribe(target1, callback); 168 | _system.Subscribe(target2, callback2); 169 | _system.Unsubscribe(target2, callback2); 170 | 171 | _system.QueueEvent(target1, new EvSimpleEvent(10)); 172 | _system.QueueEvent(target2, new EvSimpleEvent(30)); 173 | _system.ProcessEvents(); 174 | 175 | Assert.IsTrue(value1 == 10); 176 | Assert.IsTrue(value2 == 0); 177 | 178 | _system.Subscribe(target2, callback2); 179 | 180 | _system.QueueEvent(target1, new EvSimpleEvent(10)); 181 | _system.QueueEvent(target2, new EvSimpleEvent(30)); 182 | _system.ProcessEvents(); 183 | 184 | Assert.IsTrue(value1 == 20); 185 | Assert.IsTrue(value2 == 30); 186 | 187 | _system.Unsubscribe(target1, callback); 188 | 189 | _system.QueueEvent(target1, new EvSimpleEvent(10)); 190 | _system.QueueEvent(target2, new EvSimpleEvent(30)); 191 | _system.ProcessEvents(); 192 | 193 | Assert.IsTrue(value1 == 20); 194 | Assert.IsTrue(value2 == 60); 195 | 196 | _system.Subscribe(target1, callback); 197 | 198 | _system.QueueEvent(target1, new EvSimpleEvent(10)); 199 | _system.QueueEvent(target2, new EvSimpleEvent(30)); 200 | _system.ProcessEvents(); 201 | 202 | Assert.IsTrue(value1 == 30); 203 | Assert.IsTrue(value2 == 90); 204 | 205 | _system.Unsubscribe(target2, callback2); 206 | 207 | _system.QueueEvent(target1, new EvSimpleEvent(10)); 208 | _system.QueueEvent(target2, new EvSimpleEvent(30)); 209 | _system.ProcessEvents(); 210 | 211 | Assert.IsTrue(value1 == 40); 212 | Assert.IsTrue(value2 == 90); 213 | 214 | _system.Unsubscribe(target1, callback); 215 | 216 | _system.QueueEvent(target1, new EvSimpleEvent(10)); 217 | _system.QueueEvent(target2, new EvSimpleEvent(30)); 218 | _system.ProcessEvents(); 219 | 220 | _system.VerifyNoSubscribers(); 221 | 222 | Assert.IsTrue(value1 == 40); 223 | Assert.IsTrue(value2 == 90); 224 | } 225 | 226 | [Test] 227 | public void TestUnblittableEvent() 228 | { 229 | Assert.Throws(() => 230 | { 231 | EventHandlerStandard system = new EventHandlerStandard(); 232 | }); 233 | } 234 | } 235 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestUnityEventStandardSystem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ed0278a0d682bfa44a2b68bfc91c829f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestUnityEventsMisc.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEvents.Internal; 3 | 4 | namespace UnityEvents.Test 5 | { 6 | public struct EvSimpleEvent 7 | { 8 | public int value; 9 | 10 | public EvSimpleEvent(int value) 11 | { 12 | this.value = value; 13 | } 14 | } 15 | 16 | public struct EvSimpleEvent2 17 | { 18 | public int value; 19 | 20 | public EvSimpleEvent2(int value) 21 | { 22 | this.value = value; 23 | } 24 | } 25 | 26 | public struct UnblittableEvent 27 | { 28 | public GameObject gObj; 29 | } 30 | 31 | public struct TestJob : IJobForEvent 32 | { 33 | public int result; 34 | 35 | public TestJob(int result) 36 | { 37 | this.result = result; 38 | } 39 | 40 | public void ExecuteEvent(EvSimpleEvent ev) 41 | { 42 | result += ev.value; 43 | } 44 | } 45 | 46 | public struct TestJob2 : IJobForEvent 47 | { 48 | public int result; 49 | 50 | public TestJob2(int result) 51 | { 52 | this.result = result; 53 | } 54 | 55 | public void ExecuteEvent(EvSimpleEvent2 ev) 56 | { 57 | result += ev.value; 58 | } 59 | } 60 | 61 | public struct TestResetJob : IJobForEvent 62 | { 63 | public int result; 64 | 65 | public TestResetJob(int result) 66 | { 67 | this.result = result; 68 | } 69 | 70 | public void ExecuteEvent(EvSimpleEvent ev) 71 | { 72 | result = 0; 73 | result += ev.value; 74 | } 75 | } 76 | 77 | public struct TestUnblittableJob : IJobForEvent 78 | { 79 | public GameObject gObj; 80 | 81 | public void ExecuteEvent(EvSimpleEvent ev) 82 | { 83 | } 84 | } 85 | 86 | public struct TestBlittableJobForUnblittable : IJobForEvent 87 | { 88 | public void ExecuteEvent(UnblittableEvent ev) 89 | { 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/TestUnityEventsMisc.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: da67c203e6891f04bbd95eb121936ed1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/UnityEvents.Test.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TestsPlay", 3 | "references": [ 4 | "UnityEvents" 5 | ], 6 | "optionalUnityReferences": [ 7 | "TestAssemblies" 8 | ], 9 | "includePlatforms": [], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [] 16 | } -------------------------------------------------------------------------------- /Assets/UnityEvents/Tests/UnityEvents.Test.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7d26686ae717fd4469734a4c1810c282 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Galvanic Games 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.ads": "2.0.8", 4 | "com.unity.analytics": "3.2.2", 5 | "com.unity.burst": "0.2.4-preview.41", 6 | "com.unity.collab-proxy": "1.2.15", 7 | "com.unity.collections": "0.0.9-preview.11", 8 | "com.unity.jobs": "0.0.7-preview.6", 9 | "com.unity.mathematics": "0.0.12-preview.19", 10 | "com.unity.package-manager-ui": "2.0.3", 11 | "com.unity.purchasing": "2.0.3", 12 | "com.unity.textmeshpro": "1.3.0", 13 | "com.unity.modules.ai": "1.0.0", 14 | "com.unity.modules.animation": "1.0.0", 15 | "com.unity.modules.assetbundle": "1.0.0", 16 | "com.unity.modules.audio": "1.0.0", 17 | "com.unity.modules.cloth": "1.0.0", 18 | "com.unity.modules.director": "1.0.0", 19 | "com.unity.modules.imageconversion": "1.0.0", 20 | "com.unity.modules.imgui": "1.0.0", 21 | "com.unity.modules.jsonserialize": "1.0.0", 22 | "com.unity.modules.particlesystem": "1.0.0", 23 | "com.unity.modules.physics": "1.0.0", 24 | "com.unity.modules.physics2d": "1.0.0", 25 | "com.unity.modules.screencapture": "1.0.0", 26 | "com.unity.modules.terrain": "1.0.0", 27 | "com.unity.modules.terrainphysics": "1.0.0", 28 | "com.unity.modules.tilemap": "1.0.0", 29 | "com.unity.modules.ui": "1.0.0", 30 | "com.unity.modules.uielements": "1.0.0", 31 | "com.unity.modules.umbra": "1.0.0", 32 | "com.unity.modules.unityanalytics": "1.0.0", 33 | "com.unity.modules.unitywebrequest": "1.0.0", 34 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 35 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 36 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 37 | "com.unity.modules.unitywebrequestwww": "1.0.0", 38 | "com.unity.modules.vehicles": "1.0.0", 39 | "com.unity.modules.video": "1.0.0", 40 | "com.unity.modules.vr": "1.0.0", 41 | "com.unity.modules.wind": "1.0.0", 42 | "com.unity.modules.xr": "1.0.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/PresetManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2018.3.5f1 2 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/VFXManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GalvanicGames/unity-events/19dcab35d6c4426a14771d9fbab5afd92382aece/ProjectSettings/VFXManager.asset -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity Events 2.0 # 2 | A performant code focused strongly typed publisher/subscriber event system to decouple objects from talking directly to each other. Supports global event system and per GameObject event systems that send deferred events to be processed at a later tick (FixedUpdate, Update, or LateUpdate). Allows regular callback events and multithreaded jobs that trigger on events. 3 | 4 | Custom Event Systems can be created to control when events are processed instead of relying on the update ticks. 5 | 6 | Uses Unity's new Job System and the burst compiler. Both of those features are considered in preview and experimental. Use at your own risk! 7 | 8 | #### Obtain! #### 9 | [Releases](https://github.com/GalvanicGames/unity-events/releases) 10 | 11 | If you'd like the most up to date version (which is the most cool), then pull the repo or download it [here](https://github.com/GalvanicGames/unity-events/archive/master.zip) and copy the files in Assets to your project's Assets folder. 12 | 13 | ## Setup 14 | Once the Unity Events asset has been imported into the project then the event system is ready to be used. 15 | 16 | ### Prerequisites ### 17 | Requires the following Unity packages: 18 | ``` 19 | Jobs 20 | Mathematics 21 | Collections 22 | Burst 23 | ``` 24 | 25 | Also requires: 26 | ``` 27 | .NET 4.x Runtime (Default in 2018.3) 28 | ``` 29 | 30 | ## Examples 31 | There are multiple [simple](Assets/UnityEvents/Examples/Simple) and [advanced](Assets/UnityEvents/Examples/Advance) examples in the repository and can be looked at for guidance. 32 | 33 | As a simple example here is how an event can be sent to a Global event system and a GameObject's local event system. 34 | ```csharp 35 | // I have to be an unmanaged type! Need references? Use an id and have a lookup database system. 36 | private struct EvExampleEvent 37 | { 38 | public int exampleValue; 39 | 40 | public EvExampleEvent(int exampleValue) 41 | { 42 | this.exampleValue = exampleValue; 43 | } 44 | } 45 | 46 | // The callback that will be invoked on an event 47 | private void OnExampleEvent(EvExampleEvent ev) 48 | { 49 | Debug.Log("Event received! Value: " + ev.exampleValue); 50 | } 51 | 52 | private void OnEnable() 53 | { 54 | // Subscribes to the global event system, handles events in FixedUpdate 55 | GlobalEventSystem.Subscribe(OnExampleEvent); 56 | 57 | // Subscribes to THIS GameObject's event system! Also Fixed Update 58 | gameObject.Subscribe(OnExampleEvent); 59 | } 60 | 61 | public void SendEvents() 62 | { 63 | // Send an event to the global event system, will be processed in the next FixedUpdate 64 | GlobalEventSystem.SendEvent(new EvExampleEvent(10)); 65 | 66 | // Send an event to a specific GameObject, only listeners subscribed to that gameobject will get 67 | // this event. Also will be processed in the next FixedUpdate 68 | gameObject.SendEvent(new EvExampleEvent(99)); 69 | } 70 | 71 | ``` 72 | 73 | ## BLITTABLE NOTE! 74 | Unity Events 2.0 requires that events/jobs are [blittable](https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types) types. This is done to allow compatibility with the burst compiler and Unity's Job system. Also has a benefit of encouraging "better" programming practices since the events are deferred. References may become stale and GameObjects may have been destroyed and are "null" by the time the event is processed. Send the data the event represents rather than a reference to an object. If a reference is needed then create a look up database and send the id of the object for event listeners to look up to process on. If an array/list is needed then consider using something like [ValueTypeLists](https://gist.github.com/cjddmut/cb43af3ee191af78363f41a3188c0f7b). 75 | 76 | ## 'DISABLE_EVENT_SAFETY_CHKS' Define Symbol 77 | Unity Events 2.0 does various safety checks to make sure it isn't being used inappropriately. These can be turned off by defning 'DISABLE_EVENT_SAFETY_CHKS' with the compiler (or in Unity go to 'Player Settings > Scripting Define Symbols'). Turning it off can improve performance since no checks will always be faster than any check. Use at your own risk! 78 | 79 | ## Dropped Features 80 | Unity Events 2.0 was rebuilt with performance and flexibility more in mind. Because of this some features of the original version of Unity Events have been dropped. If these features are important than the previous version of Unity Events can be found [here](https://github.com/GalvanicGames/unity-events/releases/tag/1.0). 81 | --------------------------------------------------------------------------------