Skip to main content

f8-features-event-workflow

Use when implementing or troubleshooting Event feature workflows — message dispatching, event listening, EventDispatcher auto-cleanup, and strongly typed zero-GC event parameters (0-7 args, no object[] compatibility path) in F8Framework.

Quellinformationen

Repository
TippingGame/F8Framework
Letzte Quellaktivität
9. April 2026 um 16:14
Erkannte Sprache von SKILL.md
Englisch
Sterne
886
Forks
141

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
2 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
f8-features-event-workflow
description
Use when implementing or troubleshooting Event feature workflows — message dispatching, event listening, EventDispatcher auto-cleanup, and strongly typed zero-GC event parameters (0-7 args, no object[] compatibility path) in F8Framework.
# Event Feature Workflow > **⚠️ IMPORTANT**: Before using this feature, you **MUST** formally initialize F8Framework in the launch sequence. Ensure `ModuleCenter.Initialize(this);` has run first, then create the required module, for example `FF8.Message = ModuleCenter.CreateModule<MessageManager>();`. ## Use this skill when - The task is about event/message dispatching and listening. - The user asks about decoupled communication between components. - The user needs EventDispatcher auto-cleanup on UI or entities. - Troubleshooting event dead loops or missing callbacks. ## Path resolution 1. Prefer project source at Assets/F8Framework. 2. If F8Framework is installed as a package, use Packages/F8Framework. 3. For usage docs, read: Assets/F8Framework/Tests/Event/README.md ## Sources of truth - Runtime module: Assets/F8Framework/Runtime/Event - Editor module: Assets/F8Framework/Editor/Event - Test docs: Assets/F8Framework/Tests/Event ## Key classes and interfaces | Class | Role | |-------|------| | `MessageManager` | Core module. Access via `FF8.Message`. Global event bus. | | `EventDispatcher` | Mixin base class for auto-cleanup event listeners. Used by BaseView. | ## API quick reference ### Define events ```csharp public enum MessageEvent { Empty = 10000, ApplicationFocus = 10001, NotApplicationFocus = 10002, ApplicationQuit = 10003, } ``` ### Global event listening (via FF8.Message) ```csharp // Add listener (supports int and enum, pass 'this' for auto-cleanup) FF8.Message.AddEventListener(MessageEvent.ApplicationFocus, OnEvent, this); FF8.Message.AddEventListener<int, string>(10002, OnEventNoGC, this); FF8.Message.AddEventListener<MessageEvent, int, string>(MessageEvent.ApplicationFocus, OnEventNoGC, this); FF8.Message.AddEventListener<int, string, bool, float, long, byte, char>(10004, OnEventT7, this); // Dispatch event (without/with parameters) FF8.Message.DispatchEvent(MessageEvent.ApplicationFocus); FF8.Message.DispatchEvent(10002, 123, "data"); FF8.Message.DispatchEvent(MessageEvent.ApplicationFocus, 123, "data"); FF8.Message.DispatchEvent(10004, 123, "data", true, 1.5f, 999L, (byte)7, 'F'); // Async frame-sliced dispatch (executes 1 listener per frame) FF8.Message.DispatchEventAsync(MessageEvent.ApplicationFocus); FF8.Message.DispatchEventAsync(10002, 123, "data"); FF8.Message.DispatchEventAsync(MessageEvent.ApplicationFocus, 123, "data"); FF8.Message.DispatchEventAsync(10004, 123, "data", true, 1.5f, 999L, (byte)7, 'F'); // Remove listener FF8.Message.RemoveEventListener(MessageEvent.ApplicationFocus, OnEvent, this); FF8.Message.RemoveEventListener<int, string>(10002, OnEventNoGC, this); FF8.Message.RemoveEventListener<MessageEvent, int, string>(MessageEvent.ApplicationFocus, OnEventNoGC, this); FF8.Message.RemoveEventListener<int, string, bool, float, long, byte, char>(10004, OnEventT7, this); // Callback signatures void OnEvent() { } void OnEventNoGC(int id, string name) { } void OnEventT7(int id, string name, bool active, float speed, long score, byte level, char rank) { } ``` ### EventDispatcher pattern (auto-cleanup) ```csharp // In classes inheriting EventDispatcher (e.g., BaseView): AddEventListener(MessageEvent.ApplicationFocus, OnEvent); AddEventListener<int, string>(10002, OnEventNoGC); AddEventListener<int, string, bool, float, long, byte, char>(10004, OnEventT7); DispatchEvent(MessageEvent.ApplicationFocus); DispatchEvent(10002, 123, "data"); DispatchEvent(10004, 123, "data", true, 1.5f, 999L, (byte)7, 'F'); DispatchEventAsync(MessageEvent.ApplicationFocus); DispatchEventAsync(10002, 123, "data"); DispatchEventAsync(10004, 123, "data", true, 1.5f, 999L, (byte)7, 'F'); RemoveEventListener(MessageEvent.ApplicationFocus, OnEvent); RemoveEventListener<int, string>(10002, OnEventNoGC); RemoveEventListener<int, string, bool, float, long, byte, char>(10004, OnEventT7); // All listeners auto-cleaned on Clear() ``` ### Zero-GC recommendation ```csharp // Use the fixed-parameter overload matching the event payload size. FF8.Message.AddEventListener<int>(10010, OnHpChanged, this); FF8.Message.DispatchEvent(10010, 99); FF8.Message.DispatchEventAsync(10010, 99); FF8.Message.AddEventListener<int, int>(10011, OnDamage, this); FF8.Message.DispatchEvent(10011, 12, 3); FF8.Message.DispatchEventAsync(10011, 12, 3); FF8.Message.AddEventListener<int, int, int, int, int, int, int>(10012, OnCombo, this); FF8.Message.DispatchEvent(10012, 1, 2, 3, 4, 5, 6, 7); FF8.Message.DispatchEventAsync(10012, 1, 2, 3, 4, 5, 6, 7); void OnHpChanged(int hp) { } void OnDamage(int damage, int criticalType) { } void OnCombo(int a, int b, int c, int d, int e, int f, int g) { } ``` ## Workflow 1. Define event IDs as enum (start from 10000 to avoid framework conflicts). 2. Choose pattern: global `FF8.Message` or `EventDispatcher` mixin. 3. For UI/entity classes, prefer `EventDispatcher` for automatic cleanup. 4. Use the strongly typed overload matching the event payload size; the event module now supports 0~7 fixed parameters. 5. If you need to spread callback cost across frames, use `DispatchEventAsync(...)`; the current implementation executes 1 listener per frame. 6. Always pass `this` as the last parameter to `AddEventListener` for lifecycle binding. 7. The framework has built-in dead-loop prevention. 8. Use the Event System Monitor editor window to debug active listeners. ## Common error handling | Error | Cause | Solution | |-------|-------|----------| | Event not received | Listener added after dispatch | Ensure listener registration before dispatch | | Dead loop warning | Event A dispatches Event B which dispatches Event A | Break the cycle, use intermediate state | | Memory leak | Listeners not removed on destroy | Use EventDispatcher or pass `this` for auto-cleanup | | Wrong callback signature | Params mismatch | Match the overload exactly: `void()`, `void(T1)`, `void(T1,T2)` ... `void(T1,T2,T3,T4,T5,T6,T7)` | ## Cross-module dependencies - **UI**: BaseView extends EventDispatcher for auto-cleanup. - **Timer**: Application focus events used by Timer module. ## Output checklist - Event ID enum defined with proper range. - Listener pattern selected (global / EventDispatcher). - Files changed and why. - Validation status and remaining risks.
Auf GitHub ansehen