Marketplace

game-engines

Master game engines - Unity, Unreal Engine, Godot. Engine-specific workflows, systems architecture, and production best practices.

$ Instalar

git clone https://github.com/pluginagentmarketplace/custom-plugin-game-developer /tmp/custom-plugin-game-developer && cp -r /tmp/custom-plugin-game-developer/skills/game-engines ~/.claude/skills/custom-plugin-game-developer

// tip: Run this command in your terminal to install the skill


name: game-engines version: "2.0.0" description: | Master game engines - Unity, Unreal Engine, Godot. Engine-specific workflows, systems architecture, and production best practices. sasmp_version: "1.3.0" bonded_agent: 02-game-programmer bond_type: PRIMARY_BOND

parameters:

  • name: engine type: string required: false validation: enum: [unity, unreal, godot]
  • name: topic type: string required: false validation: enum: [architecture, physics, rendering, audio, networking, ui]

retry_policy: enabled: true max_attempts: 3 backoff: exponential

observability: log_events: [start, complete, error] metrics: [build_time, frame_time_ms, draw_calls]

Game Engines & Frameworks

Engine Comparison

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    ENGINE COMPARISON                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  UNITY (C#):                                                 β”‚
β”‚  β”œβ”€ Best for: 2D/3D, Mobile, Indie, VR/AR                  β”‚
β”‚  β”œβ”€ Learning: Moderate                                      β”‚
β”‚  β”œβ”€ Performance: Good (IL2CPP for native)                  β”‚
β”‚  └─ Market: 70%+ of mobile games                           β”‚
β”‚                                                              β”‚
β”‚  UNREAL (C++/Blueprints):                                    β”‚
β”‚  β”œβ”€ Best for: AAA, High-end graphics, Large teams          β”‚
β”‚  β”œβ”€ Learning: Steep (C++) / Easy (Blueprints)              β”‚
β”‚  β”œβ”€ Performance: Excellent                                  β”‚
β”‚  └─ Market: Major console/PC titles                        β”‚
β”‚                                                              β”‚
β”‚  GODOT (GDScript/C#):                                        β”‚
β”‚  β”œβ”€ Best for: 2D games, Learning, Open source              β”‚
β”‚  β”œβ”€ Learning: Easy                                          β”‚
β”‚  β”œβ”€ Performance: Good for 2D, Improving for 3D             β”‚
β”‚  └─ Market: Growing indie scene                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Unity Architecture

UNITY COMPONENT SYSTEM:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  GameObject                                                  β”‚
β”‚  β”œβ”€ Transform (required)                                    β”‚
β”‚  β”œβ”€ Renderer (MeshRenderer, SpriteRenderer)                β”‚
β”‚  β”œβ”€ Collider (BoxCollider, CapsuleCollider)                β”‚
β”‚  β”œβ”€ Rigidbody (physics simulation)                         β”‚
β”‚  └─ Custom MonoBehaviour scripts                           β”‚
β”‚                                                              β”‚
β”‚  LIFECYCLE:                                                  β”‚
β”‚  Awake() β†’ OnEnable() β†’ Start() β†’ FixedUpdate() β†’          β”‚
β”‚  Update() β†’ LateUpdate() β†’ OnDisable() β†’ OnDestroy()       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
// βœ… Production-Ready: Unity Component Pattern
public class PlayerController : MonoBehaviour
{
    [Header("Movement Settings")]
    [SerializeField] private float moveSpeed = 5f;
    [SerializeField] private float jumpForce = 10f;

    [Header("Ground Check")]
    [SerializeField] private Transform groundCheck;
    [SerializeField] private float groundRadius = 0.2f;
    [SerializeField] private LayerMask groundLayer;

    private Rigidbody2D _rb;
    private bool _isGrounded;
    private float _horizontalInput;

    // Cache components in Awake
    private void Awake()
    {
        _rb = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        // Input in Update (frame-rate independent)
        _horizontalInput = Input.GetAxisRaw("Horizontal");

        if (Input.GetButtonDown("Jump") && _isGrounded)
        {
            Jump();
        }
    }

    private void FixedUpdate()
    {
        // Physics in FixedUpdate (consistent timing)
        CheckGround();
        Move();
    }

    private void CheckGround()
    {
        _isGrounded = Physics2D.OverlapCircle(
            groundCheck.position, groundRadius, groundLayer);
    }

    private void Move()
    {
        _rb.velocity = new Vector2(
            _horizontalInput * moveSpeed,
            _rb.velocity.y);
    }

    private void Jump()
    {
        _rb.velocity = new Vector2(_rb.velocity.x, jumpForce);
    }
}

Unreal Engine Architecture

UNREAL ACTOR SYSTEM:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  AActor (Base class for all game objects)                   β”‚
β”‚  β”œβ”€ APawn (Can be possessed by controller)                 β”‚
β”‚  β”‚   └─ ACharacter (Has CharacterMovementComponent)        β”‚
β”‚  β”œβ”€ AGameMode (Game rules)                                 β”‚
β”‚  └─ APlayerController (Player input handling)              β”‚
β”‚                                                              β”‚
β”‚  COMPONENTS:                                                 β”‚
β”‚  β”œβ”€ USceneComponent (Transform hierarchy)                  β”‚
β”‚  β”œβ”€ UStaticMeshComponent (3D model)                        β”‚
β”‚  β”œβ”€ UCapsuleComponent (Collision)                          β”‚
β”‚  └─ UCharacterMovementComponent (Movement logic)           β”‚
β”‚                                                              β”‚
β”‚  LIFECYCLE:                                                  β”‚
β”‚  Constructor β†’ BeginPlay() β†’ Tick() β†’ EndPlay()            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
// βœ… Production-Ready: Unreal Character
UCLASS()
class MYGAME_API AMyCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    AMyCharacter();

    virtual void BeginPlay() override;
    virtual void Tick(float DeltaTime) override;
    virtual void SetupPlayerInputComponent(
        UInputComponent* PlayerInputComponent) override;

protected:
    UPROPERTY(EditAnywhere, Category = "Movement")
    float WalkSpeed = 600.0f;

    UPROPERTY(EditAnywhere, Category = "Movement")
    float SprintSpeed = 1200.0f;

    UPROPERTY(EditAnywhere, Category = "Combat")
    float MaxHealth = 100.0f;

private:
    UPROPERTY()
    float CurrentHealth;

    bool bIsSprinting;

    void MoveForward(float Value);
    void MoveRight(float Value);
    void StartSprint();
    void StopSprint();

    UFUNCTION()
    void OnTakeDamage(float Damage, AActor* DamageCauser);
};

// Implementation
void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();
    CurrentHealth = MaxHealth;
    GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
}

void AMyCharacter::SetupPlayerInputComponent(
    UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

    PlayerInputComponent->BindAxis("MoveForward", this,
        &AMyCharacter::MoveForward);
    PlayerInputComponent->BindAxis("MoveRight", this,
        &AMyCharacter::MoveRight);
    PlayerInputComponent->BindAction("Sprint", IE_Pressed, this,
        &AMyCharacter::StartSprint);
    PlayerInputComponent->BindAction("Sprint", IE_Released, this,
        &AMyCharacter::StopSprint);
}

Godot Architecture

GODOT NODE SYSTEM:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Node (Base class)                                           β”‚
β”‚  β”œβ”€ Node2D (2D game objects)                                β”‚
β”‚  β”‚   β”œβ”€ Sprite2D                                            β”‚
β”‚  β”‚   β”œβ”€ CharacterBody2D                                     β”‚
β”‚  β”‚   └─ Area2D                                              β”‚
β”‚  β”œβ”€ Node3D (3D game objects)                                β”‚
β”‚  β”‚   β”œβ”€ MeshInstance3D                                      β”‚
β”‚  β”‚   β”œβ”€ CharacterBody3D                                     β”‚
β”‚  β”‚   └─ Area3D                                              β”‚
β”‚  └─ Control (UI elements)                                   β”‚
β”‚                                                              β”‚
β”‚  LIFECYCLE:                                                  β”‚
β”‚  _init() β†’ _ready() β†’ _process() / _physics_process()      β”‚
β”‚                                                              β”‚
β”‚  SIGNALS (Event System):                                     β”‚
β”‚  signal hit(damage)                                         β”‚
β”‚  emit_signal("hit", 10)                                     β”‚
β”‚  connect("hit", target, "_on_hit")                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
# βœ… Production-Ready: Godot Player Controller
extends CharacterBody2D

class_name Player

signal health_changed(new_health, max_health)
signal died()

@export var move_speed: float = 200.0
@export var jump_force: float = 400.0
@export var max_health: int = 100

@onready var sprite: Sprite2D = $Sprite2D
@onready var animation: AnimationPlayer = $AnimationPlayer
@onready var coyote_timer: Timer = $CoyoteTimer

var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")
var current_health: int
var can_coyote_jump: bool = false

func _ready() -> void:
    current_health = max_health

func _physics_process(delta: float) -> void:
    # Apply gravity
    if not is_on_floor():
        velocity.y += gravity * delta

    # Handle coyote time
    if is_on_floor():
        can_coyote_jump = true
    elif can_coyote_jump and coyote_timer.is_stopped():
        coyote_timer.start()

    # Jump
    if Input.is_action_just_pressed("jump"):
        if is_on_floor() or can_coyote_jump:
            velocity.y = -jump_force
            can_coyote_jump = false

    # Horizontal movement
    var direction := Input.get_axis("move_left", "move_right")
    velocity.x = direction * move_speed

    # Flip sprite
    if direction != 0:
        sprite.flip_h = direction < 0

    # Update animation
    _update_animation()

    move_and_slide()

func _update_animation() -> void:
    if not is_on_floor():
        animation.play("jump")
    elif abs(velocity.x) > 10:
        animation.play("run")
    else:
        animation.play("idle")

func take_damage(amount: int) -> void:
    current_health = max(0, current_health - amount)
    health_changed.emit(current_health, max_health)

    if current_health <= 0:
        die()

func die() -> void:
    died.emit()
    queue_free()

func _on_coyote_timer_timeout() -> void:
    can_coyote_jump = false

Engine Feature Comparison

FEATURE MATRIX:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Feature          β”‚ Unity        β”‚ Unreal      β”‚ Godot     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  2D Support       β”‚ Excellent    β”‚ Basic       β”‚ Excellent β”‚
β”‚  3D Graphics      β”‚ Good         β”‚ Excellent   β”‚ Good      β”‚
β”‚  Physics          β”‚ PhysX/Box2D  β”‚ Chaos/PhysX β”‚ Godot     β”‚
β”‚  Animation        β”‚ Animator     β”‚ AnimGraph   β”‚ AnimTree  β”‚
β”‚  UI System        β”‚ uGUI/UITk    β”‚ UMG/Slate   β”‚ Control   β”‚
β”‚  Networking       β”‚ Netcode/MLAPIβ”‚ Built-in    β”‚ ENet/Nakamaβ”‚
β”‚  Mobile           β”‚ Excellent    β”‚ Good        β”‚ Good      β”‚
β”‚  Console          β”‚ Good         β”‚ Excellent   β”‚ Limited   β”‚
β”‚  VR/AR            β”‚ Excellent    β”‚ Excellent   β”‚ Basic     β”‚
β”‚  Learning Curve   β”‚ Moderate     β”‚ Steep       β”‚ Easy      β”‚
β”‚  License          β”‚ Revenue-basedβ”‚ 5% royalty  β”‚ MIT Free  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”§ Troubleshooting

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PROBLEM: Low frame rate in editor                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ SOLUTIONS:                                                   β”‚
β”‚ β†’ Disable unnecessary editor windows                        β”‚
β”‚ β†’ Reduce scene view quality                                 β”‚
β”‚ β†’ Hide gizmos for complex objects                           β”‚
β”‚ β†’ Build and test outside editor                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PROBLEM: Physics behaving inconsistently                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ SOLUTIONS:                                                   β”‚
β”‚ β†’ Use FixedUpdate/_physics_process for physics              β”‚
β”‚ β†’ Check fixed timestep settings                             β”‚
β”‚ β†’ Avoid moving static colliders                             β”‚
β”‚ β†’ Use continuous collision for fast objects                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PROBLEM: Animations not playing correctly                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ SOLUTIONS:                                                   β”‚
β”‚ β†’ Check animation state machine transitions                 β”‚
β”‚ β†’ Verify animation clip import settings                     β”‚
β”‚ β†’ Look for conflicting animation layers                     β”‚
β”‚ β†’ Ensure root motion settings match                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PROBLEM: Build size too large                               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ SOLUTIONS:                                                   β”‚
β”‚ β†’ Analyze build report                                      β”‚
β”‚ β†’ Remove unused assets                                      β”‚
β”‚ β†’ Compress textures and audio                               β”‚
β”‚ β†’ Enable code stripping (Unity) / Shipping (Unreal)         β”‚
β”‚ β†’ Split into downloadable content                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Learning Paths

LevelUnityUnrealGodot
Beginner (1-2 mo)Ruby's AdventureBlueprint BasicsYour First 2D Game
Intermediate (2-4 mo)3D PlatformerC++ Fundamentals3D Game Tutorial
Advanced (4-6 mo)Networking + ECSMultiplayer ShooterMultiplayer + Plugins

Use this skill: When learning game engines, building games, or optimizing engine performance.