godot-genre-rts

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Genre: Real-Time Strategy (RTS)

游戏类型:实时策略(RTS)

Expert blueprint for RTS games balancing strategy, micromanagement, and performance.
兼顾策略性、微操和性能的RTS游戏专业开发蓝图。

NEVER Do

绝对不要做的事

  • NEVER pathfinding jitter — Units pushing each other endlessly. Enable RVO avoidance (NavigationAgent2D.avoidance_enabled with radius).
  • NEVER excessive micromanagement — Automate mundane tasks (auto-attack nearby enemies, auto-resume gathering after drop-off).
  • NEVER _process on every unit — For 100+ units, use central UnitManager iterator. Saves massive function call overhead.
  • NEVER skip command queuing — Players expect Shift+Click to chain commands. Store Array[Command] and process sequentially.
  • NEVER forget fog of war — Unvisited areas should be hidden. Use SubViewport + shader mask for performance.

  • 绝对不要出现寻路抖动——单位之间无休止地互相推挤。启用RVO避让功能(设置NavigationAgent2D的avoidance_enabled属性并配置半径)。
  • 绝对不要过度依赖微操——自动化繁琐任务(自动攻击附近敌人、交付资源后自动恢复采集)。
  • 绝对不要在每个单位上单独处理逻辑——当单位数量超过100个时,使用中央UnitManager迭代处理。可大幅减少函数调用开销。
  • 绝对不要跳过命令队列——玩家期望通过Shift+点击来链式下达命令。使用Array[Command]存储命令并按顺序执行。
  • 绝对不要忘记战争迷雾——未探索区域应隐藏。使用SubViewport+着色器遮罩以保证性能。

Available Scripts

可用脚本

MANDATORY: Read the appropriate script before implementing the corresponding pattern.
强制要求:在实现对应模式前,请先阅读相应脚本。

rts_selection_manager.gd

rts_selection_manager.gd

Mouse-box unit selection with shift-add. Camera projection for 3D units, command issuing with queue support (shift+right click).

支持鼠标框选单位及Shift添加至选中列表。针对3D单位的相机投影,支持带队列功能的命令下达(Shift+右键)。

Core Loop

核心循环

  1. Gather: Units collect resources (Gold, Wood, etc.).
  2. Build: Construct base buildings to unlock tech/units.
  3. Train: Produce an army of diverse units.
  4. Command: Micromanage units in real-time battles.
  5. Expand: Secure map control and resources.
  1. 采集:单位收集资源(黄金、木材等)。
  2. 建造:建造基地建筑以解锁科技/单位。
  3. 训练:生产多样化的军队单位。
  4. 指挥:在实时战斗中微操单位。
  5. 扩张:掌控地图区域和资源。

Skill Chain

技能链

PhaseSkillsPurpose
1. Controls
godot-input-handling
,
camera-rts
Selection box, camera panning/zoom
2. Units
navigation-server
,
state-machines
Pathfinding, avoidance, states (Idle/Move/Attack)
3. Systems
fog-of-war
,
building-system
Map visibility, grid placement
4. AI
behavior-trees
,
utility-ai
Enemy commander logic
5. Polish
ui-minimap
,
godot-particles
Strategic overview, battle feedback
阶段技能用途
1. 控制
godot-input-handling
,
camera-rts
选择框、相机平移/缩放
2. 单位
navigation-server
,
state-machines
寻路、避让、状态(闲置/移动/攻击)
3. 系统
fog-of-war
,
building-system
地图可见性、网格放置
4. AI
behavior-trees
,
utility-ai
敌方指挥官逻辑
5. 优化
ui-minimap
,
godot-particles
战略概览、战斗反馈

Architecture Overview

架构概述

1. Selection Manager (Singleton or Commander Node)

1. 选择管理器(单例或指挥节点)

Handles mouse input for selecting units.
gdscript
undefined
处理鼠标输入以选择单位。
gdscript
undefined

selection_manager.gd

selection_manager.gd

extends Node2D
var selected_units: Array[Unit] = [] var drag_start: Vector2 var is_dragging: bool = false @onready var selection_box: Panel = $SelectionBox
func _unhandled_input(event): if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: if event.pressed: start_selection(event.position) else: end_selection(event.position) elif event is InputEventMouseMotion and is_dragging: update_selection_box(event.position)
func end_selection(end_pos: Vector2): is_dragging = false selection_box.visible = false var rect = Rect2(drag_start, end_pos - drag_start).abs()
if Input.is_key_pressed(KEY_SHIFT):
    # Add to selection
    pass
else:
    deselect_all()
    
# Query physics server for units in rect
var query = PhysicsShapeQueryParameters2D.new()
var shape = RectangleShape2D.new()
shape.size = rect.size
query.shape = shape
query.transform = Transform2D(0, rect.get_center())
# ... execute query and add units to selected_units

for unit in selected_units:
    unit.set_selected(true)
func issue_command(target_position: Vector2): for unit in selected_units: unit.move_to(target_position)
undefined
extends Node2D
var selected_units: Array[Unit] = [] var drag_start: Vector2 var is_dragging: bool = false @onready var selection_box: Panel = $SelectionBox
func _unhandled_input(event): if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: if event.pressed: start_selection(event.position) else: end_selection(event.position) elif event is InputEventMouseMotion and is_dragging: update_selection_box(event.position)
func end_selection(end_pos: Vector2): is_dragging = false selection_box.visible = false var rect = Rect2(drag_start, end_pos - drag_start).abs()
if Input.is_key_pressed(KEY_SHIFT):
    # 添加至选中列表
    pass
else:
    deselect_all()
    
# 向物理服务器查询矩形区域内的单位
var query = PhysicsShapeQueryParameters2D.new()
var shape = RectangleShape2D.new()
shape.size = rect.size
query.shape = shape
query.transform = Transform2D(0, rect.get_center())
# ... 执行查询并将单位添加至selected_units

for unit in selected_units:
    unit.set_selected(true)
func issue_command(target_position: Vector2): for unit in selected_units: unit.move_to(target_position)
undefined

2. Unit Controller (State Machine)

2. 单位控制器(状态机)

Units need robust state management to handle commands and auto-attacks.
gdscript
undefined
单位需要可靠的状态管理以处理命令和自动攻击。
gdscript
undefined

unit.gd

unit.gd

extends CharacterBody2D class_name Unit
enum State { IDLE, MOVE, ATTACK, HOLD } var state: State = State.IDLE var command_queue: Array[Command] = []
@onready var nav_agent: NavigationAgent2D = $NavigationAgent2D
func move_to(target: Vector2): nav_agent.target_position = target state = State.MOVE
func _physics_process(delta): if state == State.MOVE: if nav_agent.is_navigation_finished(): state = State.IDLE return
    var next_pos = nav_agent.get_next_path_position()
    var direction = global_position.direction_to(next_pos)
    velocity = direction * speed
    move_and_slide()
undefined
extends CharacterBody2D class_name Unit
enum State { IDLE, MOVE, ATTACK, HOLD } var state: State = State.IDLE var command_queue: Array[Command] = []
@onready var nav_agent: NavigationAgent2D = $NavigationAgent2D
func move_to(target: Vector2): nav_agent.target_position = target state = State.MOVE
func _physics_process(delta): if state == State.MOVE: if nav_agent.is_navigation_finished(): state = State.IDLE return
    var next_pos = nav_agent.get_next_path_position()
    var direction = global_position.direction_to(next_pos)
    velocity = direction * speed
    move_and_slide()
undefined

3. Fog of War

3. 战争迷雾

A system to hide unvisited areas. Usually implemented with a texture and a shader.
  • Grid Approach: 2D array of "visibility" values.
  • Viewport Texture: A
    SubViewport
    drawing white circles for units on a black background. This texture is then used as a mask in a shader on a full-screen
    ColorRect
    overlay.
gdshader
shader_type canvas_item;
uniform sampler2D visibility_texture; 
uniform vec4 fog_color : source_color;

void fragment() {
    float visibility = texture(visibility_texture, UV).r;
    COLOR = mix(fog_color, vec4(0,0,0,0), visibility);
}
用于隐藏未探索区域的系统。通常通过纹理和着色器实现。
  • 网格方式:存储可见性值的2D数组。
  • 视口纹理:使用
    SubViewport
    在黑色背景上为单位绘制白色圆形。然后将该纹理用作全屏
    ColorRect
    覆盖层的着色器遮罩。
gdshader
shader_type canvas_item;
uniform sampler2D visibility_texture; 
uniform vec4 fog_color : source_color;

void fragment() {
    float visibility = texture(visibility_texture, UV).r;
    COLOR = mix(fog_color, vec4(0,0,0,0), visibility);
}

Key Mechanics Implementation

关键机制实现

Command Queue

命令队列

Allow players to chain commands (Shift-Click).
  • Implementation: Store commands in an
    Array
    . When one finishes, pop the next.
  • Visuals: Draw lines showing the queued path.
允许玩家链式下达命令(Shift+点击)。
  • 实现方式:将命令存储在
    Array
    中。完成一个命令后,取出下一个。
  • 视觉反馈:绘制线条显示已排队的路径。

Resource Gathering

资源采集

  • Nodes:
    ResourceNode
    (Tree/GoldMine) and
    DropoffPoint
    (TownCenter).
  • Logic:
    1. Move to Resource.
    2. Work (Timer).
    3. Move to Dropoff.
    4. Deposit (Global Economy update).
    5. Repeat.
  • 节点
    ResourceNode
    (树木/金矿)和
    DropoffPoint
    (城镇中心)。
  • 逻辑:
    1. 移动至资源点。
    2. 采集(计时器控制)。
    3. 移动至交付点。
    4. 交付资源(更新全局经济系统)。
    5. 重复循环。

Common Pitfalls

常见陷阱

  1. Pathfinding Jitter: Units pushing each other endlessly. Fix: Use RVO (Reciprocal Velocity Obstacles) built into Godot's
    NavigationAgent2D
    (properties
    avoidance_enabled
    ,
    radius
    ).
  2. Too Much Micro: Automate mundane tasks (auto-attack nearby, auto-gather behavior).
  3. Performance: Too many nodes. Fix: Use
    MultiMeshInstance2D
    for rendering thousands of units if needed, and run logic on a
    Server
    node rather than individual scripts for mass units.
  1. 寻路抖动:单位之间无休止地互相推挤。解决方法:使用Godot的
    NavigationAgent2D
    内置的RVO(相对速度障碍物)功能(配置
    avoidance_enabled
    radius
    属性)。
  2. 过度微操:自动化繁琐任务(自动攻击附近敌人、自动采集行为)。
  3. 性能问题:节点数量过多。解决方法:如果需要渲染数千个单位,使用
    MultiMeshInstance2D
    ;对于大量单位,在
    Server
    节点上运行逻辑,而非每个单位单独使用脚本。

Godot-Specific Tips

Godot专属技巧

  • Avoidance:
    NavigationAgent2D
    has built-in RVO avoidance. Make sure to call
    set_velocity()
    and use the
    velocity_computed
    signal for the actual movement!
  • Server Architecture: For 100+ units, don't use
    _process
    on every unit. Have a central
    UnitManager
    iterate through active units to save function call overhead.
  • Groups: Use Groups heavily (
    Units
    ,
    Buildings
    ,
    Resources
    ) for easy selection filters.
  • 避让功能
    NavigationAgent2D
    内置RVO避让功能。确保调用
    set_velocity()
    并使用
    velocity_computed
    信号来控制实际移动!
  • 服务器架构:对于100+单位,不要在每个单位上使用
    _process
    。使用中央
    UnitManager
    遍历活跃单位,以减少函数调用开销。
  • 分组:大量使用分组(
    Units
    Buildings
    Resources
    )以简化选择过滤。

Reference

参考

  • Master Skill: godot-master
  • 核心技能:godot-master