godot-genre-moba

Installation
SKILL.md

Genre: MOBA (Multiplayer Online Battle Arena)

Expert blueprint for MOBAs emphasizing competitive balance and strategic depth.

NEVER Do (Expert Anti-Patterns)

Networking & Authority

  • NEVER trust the client for damage calculation or resource costs; strictly validate mana, ranges, and hit detection on the authoritative server using multiplayer.is_server().
  • NEVER use TRANSFER_MODE_RELIABLE for continuous movement; strictly use UNRELIABLE or UNRELIABLE_ORDERED for position/velocity to prevent network congestion.
  • NEVER sync units at 60Hz; strictly use a lower tick rate (10-20Hz) via MultiplayerSynchronizer and implement Interp/Client-Side Prediction for visual smoothness.
  • NEVER attach individual synchronizers to hundreds of minions; strictly batch state updates into compressed byte arrays via a central manager.
  • NEVER synchronize complex Engine objects directly; strictly serialize state into primitive properties or Dictionaries for reliable peer-to-peer sync.

AI & Pathfinding

  • NEVER use expensive pathfinding for all minions every frame; strictly use Time Slicing to spread get_next_path_position() calls across multiple frames.
  • NEVER query NavigationAgent paths inside _process(); strictly use _physics_process() to interact with the navigation server and avoidance systems.
  • NEVER use complex visual geometry for NavMesh baking; parse simple primitives to avoid stalling the RenderingServer or crashing the engine.
  • NEVER set path_search_max_polygons too low in large maps; agents will stop or walk incorrectly if the limit is reached before the destination.
  • NEVER use Area2D for high-performance Fog of War LOS; strictly use nodeless physics queries (intersect_ray) to bypass node overhead.

Gameplay & Balancing

  • NEVER forget Tower "Dive" protection; towers MUST switch targets immediately if an enemy Hero damages an allied Hero within range (Priority: Hero attacking Ally > Minion > Hero).
  • NEVER allow "Snowballing" without counter-play; strictly implement Comeback Mechanisms (Kill Bounties, Catch-up XP) to maintain competitive tension.
  • NEVER manage hero stats as standard Node variables; strictly use custom Resource scripts for data separation and memory efficiency.
  • NEVER forget to call duplicate(true) on shared ability Resources; modifying a buff on a shared resource will affect all heroes globally.

Technical & Performance

  • NEVER use standard strings for status checks (e.g., "stunned"); strictly use StringName (&"stunned") for pointer-speed comparisons.
  • NEVER loop over massive Fog of War grids with floats; strictly use Vector2i and TileMapLayer to prevent precision jitter.
  • NEVER execute heavy world/minimap logic on the main thread; strictly offload complex array math to WorkerThreadPool to maintain 60+ FPS.
  • NEVER rigidly couple UI cooldowns to Hero scripts; strictly use a Signal Bus or Callable bindings for decoupled architecture.
  • NEVER evaluate exact floating-point equality (==); strictly use is_equal_approx() for range, cooldown, and mana validations.

🛠 Expert Components (scripts/)

Original Expert Patterns

Modular Components


Core Loop

  1. Lane: Player farms minions for gold/XP in a designated lane.
  2. Trade: Player exchanges damage with opponent hero.
  3. Gank: Player roams to other lanes to surprise enemies.
  4. Push: Team destroys towers to open the map.
  5. End: Destroy the enemy Core/Nexus.

Skill Chain

Phase Skills Purpose
1. Control rts-controls Right-click to move, A-move, Stop
2. AI godot-navigation-pathfinding Minion waves, Tower aggro logic
3. Combat godot-ability-system, godot-rpg-stats QWER abilities, cooldowns, scaling
4. Network godot-multiplayer-networking Authority, lag compensation, prediction
5. Map godot-3d-world-building Lanes, Jungle, River, Bases

Architecture Overview

1. Lane Manager

Spawns waves of minions periodically.

# lane_manager.gd
extends Node

@export var lane_path: Path3D
@export var spawn_interval: float = 30.0
var timer: float = 0.0

func _process(delta: float) -> void:
    timer -= delta
    if timer <= 0:
        spawn_wave()
        timer = spawn_interval

func spawn_wave() -> void:
    # Spawn 3 Melee, 3 Ranged, 1 Cannon (every 3rd wave)
    for i in range(3):
        spawn_minion(MeleeMinion, lane_path)
        await get_tree().create_timer(1.0).timeout

2. Minion AI

Simple but follows strict rules.

# minion_ai.gd
extends CharacterBody3D

enum State { MARCH, COMBAT }
var current_target: Node3D

func _physics_process(delta: float) -> void:
    match state:
        State.MARCH:
            move_along_path()
            scan_for_enemies()
        State.COMBAT:
            if is_instance_valid(current_target):
                attack(current_target)
            else:
                state = State.MARCH

3. Tower Aggro Logic

The most misunderstood mechanic by new players.

# tower.gd
func _on_aggro_check() -> void:
    # Priority 1: Enemy Hero attacking Ally Hero
    # Priority 2: Enemy Unit attacking Ally Hero
    # Priority 3: Closest Enemy Minion
    # Priority 4: Closest Enemy Hero
    var target = determine_best_target()
    if target:
        shoot_at(target)

4. Skill-Shot Ability Cycle

Implementation pattern for "QWER" targeting:

  1. Idle: Waiting for input.
  2. Telegraphed: Show indicator (skill_shot_indicator.gd) while mouse is held.
  3. Active: Spawn hitbox/projectile on release.
  4. Recovery: Brief backswing animation where movement/casting is locked.

Key Mechanics Implementation

Click-to-Move (RTS Style)

Raycasting from camera to terrain.

func _unhandled_input(event: InputEvent) -> void:
    if event.is_action_pressed("move"):
        var result = raycast_from_mouse()
        if result:
            nav_agent.target_position = result.position

Ability System (Data Driven)

Defining "Fireball" or "Hook" without unique scripts for everything.

# ability_data.gd
class_name Ability extends Resource
@export var cooldown: float
@export var mana_cost: float
@export var damage: float
@export var effect_scene: PackedScene

Godot-Specific Tips

  • NavigationAgent3D: Use avoidance_enabled for minions so they flow around each other like water, rather than stacking.
  • MultiplayerSynchronizer: Sync Health, Mana, and Cooldowns. Do NOT sync position every frame if using Client-Side Prediction (advanced).
  • Fog of War: Use a SubViewport with a fog texture. Paint "holes" in the texture where allies are. Project this texture onto the terrain shader.

Common Pitfalls

  1. Snowballing: Winning team gets too strong too fast. Fix: Implement "Comeback XP/Gold" mechanisms (bounties).
  2. Pathfinding Lag: 100 minions pathing every frame. Fix: Distribute pathfinding updates over multiple frames (Time Slicing).
  3. Hacking: Client says "I dealt 1000 damage". Fix: Client says "I cast Spell Q at Direction V". Server calculates damage.

Reference

Weekly Installs
70
GitHub Stars
137
First Seen
Today