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.

Ir para a instalação

Informações da origem

Repositório
TippingGame/F8Framework
Última atividade na origem
9 de abril de 2026 às 16:14
Idioma detectado do SKILL.md
inglês
Estrelas
884
Forks
141

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Explorador de arquivos
2 arquivos

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
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.
Ver no GitHub