[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FEPC2VA2R80VCFG29BYZ9K":3,"skill-same:01M6FEPC2VA2R80VCFG29BYZ9K":49},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":22,"linkOnly":23,"markdownContent":24,"markdownBody":24,"frontMatter":25,"refName":26,"commitSha":27,"skillDirectory":28,"forksCount":29,"repositoryHtmlUrl":30,"repositoryHomepageUrl":31,"ownerHtmlUrl":32,"ownerBlogUrl":6,"ownerDescription":33,"updatedAt":34,"install":35,"resources":48},"01M6FEPC2VA2R80VCFG29BYZ9K","ue-actor-component-architecture",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fquodsoler\u002Funreal-engine-skills\u002Fue-actor-component-architecture\u002FSKILL.md",[],[18,19,20,21],"component","architecture","component architecture","ue actor component architecture","2026-11-10 10:12:30",false,"# UE Actor-Component Architecture\n\nYou are an expert in Unreal Engine's Actor-Component architecture.\n\n## Project Context\n\nBefore responding, read `.agents\u002Fue-project-context.md` for the project's subsystem inventory, coding conventions, and any existing actor hierarchies or component patterns. This tells you which base classes are established and what naming conventions apply.\n\n## Information Gathering\n\nClarify the developer's specific need before diving in:\n\n- New actor from scratch, or adding behavior to an existing one?\n- Logic-only (UActorComponent) or needs world position (USceneComponent)?\n- Spawning requirement (deferred init, pooling, net-spawned)?\n- Lifecycle bug (BeginPlay\u002FConstructor confusion, component not initialized)?\n- Cross-actor behavior via interfaces?\n\n---\n\n## Core Architecture Mental Model\n\nUnreal's Actor-Component system is **composition over inheritance**. An `AActor` is a container that owns components. Behavior, rendering, collision, and logic are all expressed through `UActorComponent` subclasses.\n\n```\nUObject\n  └── AActor                         (placeable\u002Fspawnable world entity)\n        └── owns N x UActorComponent (reusable behavior units)\n              └── USceneComponent    (adds transform + attachment)\n                    └── UPrimitiveComponent (adds collision + rendering)\n```\n\n`AActor` is a full `UObject` — never `new`\u002F`delete` an actor. Always use `SpawnActor` and `Destroy`.\n\n---\n\n## Actor Lifecycle\n\nFull event order and safety rules are in `references\u002Factor-lifecycle.md`. Key sequence:\n\n```\nConstructor                  → CreateDefaultSubobject, tick config, default values\nPostActorCreated             → spawned actors only; before construction script\nPostInitializeComponents     → all components initialized; world accessible\nBeginPlay                    → game running; full logic OK; components BeginPlay fires here\nTick(DeltaTime)              → per-frame; each ticking component's TickComponent fires\nEndPlay(EEndPlayReason)      → cleanup; ClearAllTimers; call Super\nDestroyed                    → pre-GC; avoid complex logic\n```\n\n### Constructor vs BeginPlay\n\n**Constructor** runs first on the **Class Default Object (CDO)** — an archetype used for default values. `GetWorld()` returns `nullptr` on the CDO. Never access the world or other actors in the constructor.\n\n```cpp\n\u002F\u002F CORRECT — constructor-time only\nAMyActor::AMyActor()\n{\n    MeshComp = CreateDefaultSubobject\u003CUStaticMeshComponent>(TEXT(\"Mesh\"));\n    SetRootComponent(MeshComp);\n    PrimaryActorTick.bCanEverTick = true;\n    PrimaryActorTick.TickInterval = 0.1f;\n}\n\n\u002F\u002F CORRECT — world-dependent code belongs in BeginPlay\nvoid AMyActor::BeginPlay()\n{\n    Super::BeginPlay(); \u002F\u002F Required — always call Super\n    GetWorld()->SpawnActor\u003CAProjectile>(...);\n}\n```\n\n### PostInitializeComponents\n\nCalled before BeginPlay; components are initialized; world exists. Use it to bind delegates to own components.\n\n```cpp\nvoid AMyCharacter::PostInitializeComponents()\n{\n    Super::PostInitializeComponents();\n    HealthComponent->OnDeath.AddDynamic(this, &AMyCharacter::HandleDeath);\n}\n```\n\n### EndPlay — reasons matter\n\n| Reason | When |\n|---|---|\n| `Destroyed` | `Actor->Destroy()` called explicitly |\n| `LevelTransition` | Map change |\n| `EndPlayInEditor` | PIE session ended |\n| `RemovedFromWorld` | Level streaming unloaded the sublevel |\n| `Quit` | Application shutdown |\n\n```cpp\nvoid AMyActor::EndPlay(const EEndPlayReason::Type EndPlayReason)\n{\n    GetWorld()->GetTimerManager().ClearAllTimersForObject(this);\n    Super::EndPlay(EndPlayReason);\n}\n```\n\n### Network lifecycle note\n\n**Replicated actors**: on clients, `BeginPlay` may fire before all replicated properties arrive. Use `OnRep_` callbacks for initialization that depends on replicated state. `PostNetReceive()` fires after each replication update (including the initial one); guard one-time setup inside it with a `bHasInitialized` flag. `PostNetInit` is not a standard `AActor` virtual and should not be used as a general init hook.\n\n---\n\n## Component System\n\n### The three layers\n\n| Class | Transform | Rendering\u002FCollision | Use for |\n|---|---|---|---|\n| `UActorComponent` | No | No | Pure logic — health, inventory, AI data |\n| `USceneComponent` | Yes | No | Transform anchors, grouping, pivot points |\n| `UPrimitiveComponent` | Yes | Yes | Meshes, shapes, anything visible or collidable |\n\n**Notable subclasses**: `UStaticMeshComponent`, `USkeletalMeshComponent`, shape primitives (`UCapsuleComponent`, `UBoxComponent`, `USphereComponent`), `UWidgetComponent` (3D UI in world space — requires `\"UMG\"` module), `USpringArmComponent` + `UCameraComponent`, `UChildActorComponent`. See `references\u002Fcomponent-types.md`.\n\n### Component creation\n\n**In the constructor** (for default components that appear in the Details panel):\n\n```cpp\nAMyActor::AMyActor()\n{\n    \u002F\u002F CreateDefaultSubobject registers the component as a subobject —\n    \u002F\u002F it is serialized with the actor and visible in Blueprint editors.\n    MeshComp = CreateDefaultSubobject\u003CUStaticMeshComponent>(TEXT(\"Mesh\"));\n    SetRootComponent(MeshComp);\n\n    ArrowComp = CreateDefaultSubobject\u003CUArrowComponent>(TEXT(\"Arrow\"));\n    ArrowComp->SetupAttachment(MeshComp); \u002F\u002F Parent set here; no world needed\n\n    HealthComp = CreateDefaultSubobject\u003CUHealthComponent>(TEXT(\"Health\"));\n    \u002F\u002F Logic-only components need no attachment\n}\n```\n\n**At runtime** (dynamic addition):\n\n```cpp\nvoid AMyActor::AddLight()\n{\n    \u002F\u002F NewObject creates but does NOT register with the world\n    UPointLightComponent* Light = NewObject\u003CUPointLightComponent>(this,\n        UPointLightComponent::StaticClass(), TEXT(\"DynamicLight\"));\n\n    Light->SetupAttachment(GetRootComponent());\n    Light->RegisterComponent(); \u002F\u002F Gives it world presence (render proxy, physics)\n    Light->SetIntensity(5000.f);\n}\n\nvoid AMyActor::RemoveLight(UActorComponent* Comp)\n{\n    Comp->DestroyComponent(); \u002F\u002F Unregisters and marks for GC\n}\n\n\u002F\u002F UnregisterComponent() removes a component from the world without destroying it (reversible).\n\u002F\u002F DestroyComponent() marks it for GC — irreversible. Use Unregister when you may re-enable it later.\n```\n\nWhy this distinction matters: constructor-created components are owned subobjects and participate in the actor's GC root. Runtime components via `NewObject` are not automatically serialized unless you add them to a `UPROPERTY` array.\n\n### Attachment\n\n```cpp\n\u002F\u002F Constructor (SetupAttachment — no world required)\nSpringArmComp->SetupAttachment(RootComponent);\nCameraComp->SetupAttachment(SpringArmComp);\n\n\u002F\u002F Runtime (AttachToComponent — world must exist)\nWeaponMesh->AttachToComponent(\n    CharMesh,\n    FAttachmentTransformRules::SnapToTargetNotIncludingScale,\n    TEXT(\"WeaponSocket\")  \u002F\u002F Named socket on the skeletal mesh\n);\n\nWeaponMesh->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);\n```\n\n### Activation\n\n```cpp\n\u002F\u002F In constructor — opt out of auto-activation for optional components\nSoundComp->bAutoActivate = false;\n\n\u002F\u002F Runtime — Activate() checks ShouldActivate() internally\nSoundComp->Activate();\nSoundComp->Deactivate();\nSoundComp->SetActive(true, \u002F*bReset=*\u002Ffalse);\n```\n\n---\n\n## Spawning\n\n### Standard spawn\n\n```cpp\nFActorSpawnParameters Params;\nParams.Owner = this;\nParams.Instigator = GetInstigator();\nParams.SpawnCollisionHandlingOverride =\n    ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;\nParams.Name = FName(\"Enemy_Boss\");  \u002F\u002F deterministic name for replication (must be unique)\n\nAEnemy* Enemy = GetWorld()->SpawnActor\u003CAEnemy>(\n    AEnemy::StaticClass(), Location, Rotation, Params);\n```\n\n### Deferred spawning — configure before BeginPlay\n\nUse when the actor's `BeginPlay` reads data that must be set before it runs.\n\n```cpp\nAEnemy* Enemy = GetWorld()->SpawnActorDeferred\u003CAEnemy>(\n    AEnemy::StaticClass(), SpawnTransform, Owner, Instigator,\n    ESpawnActorCollisionHandlingMethod::AlwaysSpawn);\n\nif (Enemy)\n{\n    Enemy->SetEnemyData(EnemyDataAsset); \u002F\u002F Set BEFORE BeginPlay\n    Enemy->FinishSpawning(SpawnTransform);\n    \u002F\u002F FinishSpawning triggers PostInitializeComponents then BeginPlay\n}\n```\n\n### Object pooling\n\nFor high-frequency actors (projectiles, shell casings), repeated `SpawnActor`\u002F`Destroy` creates GC pressure. Pool them: pre-spawn, hide + disable collision to \"return,\" re-enable to \"reuse.\"\n\n```cpp\nAProjectile* AProjectilePool::Get()\n{\n    for (AProjectile* P : Pool)\n    {\n        \u002F\u002F IsHidden() reflects the pool's \"inactive\" state set on return.\n        \u002F\u002F IsActive() exists only on UActorComponent, not on AActor.\n        if (P->IsHidden())\n        {\n            P->SetActorHiddenInGame(false);\n            P->SetActorEnableCollision(true);\n            return P;\n        }\n    }\n    AProjectile* New = GetWorld()->SpawnActor\u003CAProjectile>(ProjectileClass, ...);\n    Pool.Add(New);\n    return New;\n}\n```\n\n---\n\n## Ticking\n\n### Setup\n\n```cpp\nAMyActor::AMyActor()\n{\n    PrimaryActorTick.bCanEverTick = true;\n    PrimaryActorTick.bStartWithTickEnabled = false; \u002F\u002F Enable in BeginPlay\n    PrimaryActorTick.TickInterval = 0.1f;           \u002F\u002F ~10 Hz throttle\n    PrimaryActorTick.TickGroup = TG_PostPhysics;    \u002F\u002F After physics settles\n}\n```\n\nTick groups: `TG_PrePhysics` (default, input\u002Fmovement) → `TG_DuringPhysics` (physics-coupled logic, runs during physics step) → `TG_PostPhysics` (camera, IK) → `TG_PostUpdateWork` (final reads).\n\n**Component tick**: Set `PrimaryComponentTick.bCanEverTick = true` in the component constructor, with `PrimaryComponentTick.TickGroup` for ordering — same API as actor tick.\n\n### Tick dependencies\n\n```cpp\n\u002F\u002F ActorA ticks after ActorB completes\nActorA->AddTickPrerequisiteActor(ActorB);\nComponentA->AddTickPrerequisiteComponent(ComponentB);\n```\n\n### When NOT to tick\n\nTick has per-frame cost even when nothing changes. Prefer:\n\n```cpp\n\u002F\u002F Delayed\u002Frepeating events → FTimerHandle\nGetWorld()->GetTimerManager().SetTimer(TimerHandle, this,\n    &AMyActor::OnTimerFired, 2.0f, \u002F*bLoop=*\u002Ftrue);\n\n\u002F\u002F State changes → delegates \u002F multicast delegates\nHealthComp->OnDeath.AddDynamic(this, &AMyActor::HandleDeath);\n\n\u002F\u002F Collision events → OnComponentBeginOverlap \u002F OnActorBeginOverlap\n```\n\nOnly tick for true per-frame needs: smooth interpolation, physics sub-stepping, streaming queries.\n\n---\n\n## Interfaces (UINTERFACE Pattern)\n\nInterfaces let unrelated actor types respond to the same message without coupling through inheritance. This replaces `Cast\u003CASpecificType>` scattered across your codebase.\n\n### Declaration\n\n```cpp\n\u002F\u002F IInteractable.h\nUINTERFACE(MinimalAPI, Blueprintable)\nclass UInteractable : public UInterface { GENERATED_BODY() };\n\nclass MYGAME_API IInteractable\n{\n    GENERATED_BODY()\npublic:\n    \u002F\u002F BlueprintNativeEvent: C++ default + Blueprint can override\n    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category=\"Interaction\")\n    void OnInteract(AActor* Instigator);\n};\n```\n\n### Implementation\n\n```cpp\n\u002F\u002F AChest.h\nUCLASS()\nclass AChest : public AActor, public IInteractable\n{\n    GENERATED_BODY()\npublic:\n    virtual void OnInteract_Implementation(AActor* Instigator) override;\n};\n```\n\n### Calling through the interface\n\n```cpp\n\u002F\u002F No cast needed — works on any actor or component\nif (Target->Implements\u003CUInteractable>())\n{\n    \u002F\u002F Execute_ prefix required for Blueprint-callable interface functions\n    IInteractable::Execute_OnInteract(Target, GetPawn());\n}\n```\n\n**Interface vs component**: use an interface for a *capability declaration* (\"this can be interacted with\") especially when Blueprint classes need to implement it. Use a component when the behavior has its own state, needs ticking, or is reused identically by many actor types.\n\n---\n\n## Composition Patterns\n\n### Favor components over deep inheritance\n\n```cpp\n\u002F\u002F Wrong: inheritance hierarchy collapses under varied requirements\nACharacter → AHero → ASwordHero → AFireSwordHero\n\n\u002F\u002F Right: flat base + composed components\nABaseCharacter\n  + UHealthComponent     (HP, damage, death event)\n  + UInventoryComponent  (items, equipment)\n  + UAbilityComponent    (skill execution)\n  + UStatusComponent     (buffs\u002Fdebuffs)\n```\n\n### Component-to-component communication\n\nComponents should not hold raw pointers to siblings. Query through the owner or use delegates:\n\n```cpp\n\u002F\u002F Query approach\nUHealthComponent* Health = GetOwner()->FindComponentByClass\u003CUHealthComponent>();\n\n\u002F\u002F Delegate approach — total decoupling\nHealthComp->OnDeath.AddDynamic(AbilityComp, &UAbilityComponent::OnOwnerDied);\n```\n\n### Data-driven composition\n\n```cpp\n\u002F\u002F UEnemyData (UDataAsset) — varies per enemy type\n\u002F\u002F AEnemy reads configuration at BeginPlay or via SpawnActorDeferred\n\nvoid AEnemy::Initialize(UEnemyData* Data)\n{\n    HealthComp->SetMaxHealth(Data->MaxHealth);\n\n    for (TSubclassOf\u003CUActorComponent> CompClass : Data->AdditionalComponents)\n    {\n        UActorComponent* Comp = NewObject\u003CUActorComponent>(this, CompClass);\n        Comp->RegisterComponent();\n    }\n}\n```\n\n---\n\n## Common Mistakes and Anti-Patterns\n\n### Inheritance abuse\n\n```cpp\n\u002F\u002F Wrong — one class per variant\nUCLASS() class AFireEnemy : public AEnemy { };\nUCLASS() class AIceEnemy  : public AEnemy { };\n\n\u002F\u002F Right — one class, multiple DataAssets\n\u002F\u002F UEnemyData_Fire.uasset, UEnemyData_Ice.uasset → AEnemy reads at BeginPlay\n```\n\n### Tick polling instead of events\n\n```cpp\n\u002F\u002F Wrong — checked every frame\nvoid AMyActor::Tick(float DeltaTime)\n{\n    if (HealthComp->IsDead()) { HandleDeath(); }\n}\n\n\u002F\u002F Right — event-driven, zero per-frame cost\nvoid AMyActor::BeginPlay()\n{\n    Super::BeginPlay();\n    HealthComp->OnDeath.AddDynamic(this, &AMyActor::HandleDeath);\n    SetActorTickEnabled(false);\n}\n```\n\n### Forgetting Super in lifecycle overrides\n\nEvery lifecycle override must call `Super::`. Skipping it breaks replication, GC, and Blueprint event forwarding.\n\n```cpp\n\u002F\u002F Always\nvoid AMyActor::BeginPlay()  { Super::BeginPlay(); ... }\nvoid AMyActor::EndPlay(...) { ...; Super::EndPlay(EndPlayReason); }\nvoid AMyActor::PostInitializeComponents() { Super::PostInitializeComponents(); ... }\n```\n\n### Storing raw actor pointers\n\n```cpp\n\u002F\u002F Wrong — crashes when the actor is destroyed\nAActor* CachedTarget;\n\n\u002F\u002F Right — use TWeakObjectPtr and check IsValid before use\nTWeakObjectPtr\u003CAActor> CachedTarget;\nif (CachedTarget.IsValid()) { CachedTarget->DoSomething(); }\n```\n\n---\n\n## Related Skills\n\n- `ue-cpp-foundations` — UCLASS, UPROPERTY, UFUNCTION macros underpinning all patterns above\n- `ue-gameplay-framework` — GameMode, PlayerController, Pawn layered on top of this system\n- `ue-physics-collision` — UPrimitiveComponent channels, sweeps, overlap events\n\n---\n\n## Quick Reference\n\n```\nConstructor          CreateDefaultSubobject, SetRootComponent, tick config\nPostInitialize       Bind delegates to own components; world accessible\nBeginPlay            Full game logic; SpawnActor; timer setup\nTick                 Per-frame only; prefer timers\u002Fevents\nEndPlay              ClearAllTimers; Super required\nDestroyed            Pre-GC; minimal logic\n\nCreateDefaultSubobject\u003CT>()          Constructor — owned, serialized, editable\nNewObject\u003CT>() + RegisterComponent() Runtime — dynamic, not auto-serialized\nSetupAttachment()                    Constructor parent declaration\nAttachToComponent()                  Runtime attachment with transform rules\n\nSpawnActor\u003CT>()                      Standard spawn\nSpawnActorDeferred\u003CT>() + Finish     Configure before BeginPlay fires\n```\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fquodsoler\u002Funreal-engine-skills\u002Fue-actor-component-architecture",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":36,"prompt":46,"zipAvailable":47},[37,40,43],{"tool":38,"command":39},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill ue-actor-component-architecture",{"tool":41,"command":42},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill ue-actor-component-architecture",{"tool":44,"command":45},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill ue-actor-component-architecture","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fquodsoler\u002Funreal-engine-skills\u002Fue-actor-component-architecture\u002FSKILL.md",true,[],[50,64,74,83,89,96],{"skillNo":51,"name":52,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":53,"categories":54,"keywords":60,"publishedAt":22},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[55],{"categoryNo":56,"categoryName":57,"taxonomyType":58,"taxonomyTypeDesc":59},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[61,62,63],"model","model hierarchy","model hierarchy skill",{"skillNo":65,"name":66,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":70,"publishedAt":22},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[69],{"categoryNo":56,"categoryName":57,"taxonomyType":58,"taxonomyTypeDesc":59},[71,72,73],"MCP","zoom","zoom mcp",{"skillNo":75,"name":76,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":22},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[80,81,82,72],"sdk","zoom apps sdk","apps",{"skillNo":84,"name":85,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":22},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[85],{"skillNo":90,"name":91,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":95,"publishedAt":22},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[94],{"categoryNo":56,"categoryName":57,"taxonomyType":58,"taxonomyTypeDesc":59},[91],{"skillNo":97,"name":98,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":22},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[98]]