godot-genre-battle-royale

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Genre: Battle Royale

游戏类型:Battle Royale

Expert blueprint for Battle Royale games with zone mechanics, large-scale networking, and survival gameplay.
包含缩圈机制、大规模网络和生存玩法的Battle Royale游戏专家蓝图。

NEVER Do

绝对禁止的操作

  • NEVER sync all 100 players every frame — Use relevancy system: only sync players within visual range. Far players update at 4Hz, nearby at 20Hz+.
  • NEVER make zone center fully random — New circle must overlap significantly with old circle, or players teleport. Limit offset to
    current_radius - target_radius
    .
  • NEVER use client-side hit detection — Client says "I shot at direction X", Server validates "Did it hit?". Prevents cheating.
  • NEVER spawn loot without pooling — 1000+ loot items cause GC spikes. Pool loot pickups and reuse instances.
  • NEVER forget VisibilityNotifier3D for distant players — Disable
    _process()
    and AnimationPlayer for players behind or far away. Saves 60-80% CPU.

  • 绝对不要每帧同步所有100名玩家 — 使用相关性系统:仅同步视觉范围内的玩家。远处玩家以4Hz更新,近处玩家以20Hz+更新。
  • 绝对不要让缩圈中心完全随机 — 新的安全区必须与旧安全区有显著重叠,否则玩家会被强制传送。将偏移量限制为
    current_radius - target_radius
  • 绝对不要使用客户端命中检测 — 客户端仅发送"我朝X方向射击",由服务器验证"是否命中"。以此防止作弊。
  • 绝对不要不使用对象池就生成Loot — 1000+件Loot物品会导致GC峰值。对Loot拾取物使用对象池并复用实例。
  • 绝对不要忘记为远距离玩家设置VisibilityNotifier3D — 对身后或远处的玩家禁用
    _process()
    和AnimationPlayer。可节省60-80%的CPU资源。

Available Scripts

可用脚本

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

kill_feed_bus.gd

kill_feed_bus.gd

Global elimination signal bus with match stat tracking. Single emission point for UI/logging, sorted killer rankings for end-game summary.
带有比赛统计跟踪的全局淘汰信号总线。为UI/日志提供单一发射点,可生成排序后的击杀者排行榜用于游戏结束总结。

storm_system.gd

storm_system.gd

Dynamic zone shrinking with damage interpolation. Tweens center/radius smoothly, scales damage by zone size for end-game intensity.

带有伤害插值的动态缩圈系统。平滑过渡中心点/半径,根据缩圈大小缩放伤害以提升游戏后期的紧张感。

Core Loop

核心循环

  1. Deploy: Player chooses a landing spot from an air vehicle.
  2. Loot: Player scavenges weapons and armor.
  3. Move: Player runs to the safe zone to avoid taking damage.
  4. Engage: Player fights others they encounter.
  5. Survive: Player attempts to be the last one standing.
  1. 部署:玩家从飞行器上选择降落点。
  2. 搜刮:玩家搜寻武器和护甲。
  3. 转移:玩家前往安全区以避免受到伤害。
  4. 交战:玩家与遭遇的其他玩家战斗。
  5. 存活:玩家尝试成为最后一名存活者。

Skill Chain

技能链

PhaseSkillsPurpose
1. Net
godot-multiplayer-networking
Authoritative server, lag compensation
2. Map
godot-3d-world-building
,
level-of-detail
Large terrain, chunking, distant trees
3. Items
godot-inventory-system
Managing backpack, attachments, armor
4. Combat
shooter-mechanics
,
ballistics
Projectile physics, damage calculation
5. Logic
game-manager
Managing the Storm/Zone state
阶段技能用途
1. 网络
godot-multiplayer-networking
权威服务器、延迟补偿
2. 地图
godot-3d-world-building
,
level-of-detail
大型地形、分块处理、远距离树木
3. 物品
godot-inventory-system
管理背包、配件、护甲
4. 战斗
shooter-mechanics
,
ballistics
抛射物物理、伤害计算
5. 逻辑
game-manager
管理风暴/缩圈状态

Architecture Overview

架构概述

1. The Zone Manager (The Storm)

1. 缩圈管理器(风暴系统)

Manages the shrinking safe area.
gdscript
undefined
管理不断缩小的安全区域。
gdscript
undefined

zone_manager.gd

zone_manager.gd

extends Node
@export var phases: Array[ZonePhase] var current_phase_index: int = 0 var current_radius: float = 2000.0 var target_radius: float = 2000.0 var center: Vector2 = Vector2.ZERO var target_center: Vector2 = Vector2.ZERO var shrink_speed: float = 0.0
func start_next_phase() -> void: var phase = phases[current_phase_index] target_radius = phase.end_radius # Pick new center WITHIN current circle but respecting new radius var random_angle = randf() * TAU var max_offset = current_radius - target_radius var offset = Vector2.RIGHT.rotated(random_angle) * (randf() * max_offset) target_center = center + offset
shrink_speed = (current_radius - target_radius) / phase.shrink_time
func _process(delta: float) -> void: if current_radius > target_radius: current_radius -= shrink_speed * delta center = center.move_toward(target_center, (shrink_speed * delta) * (center.distance_to(target_center) / (current_radius - target_radius)))
undefined
extends Node
@export var phases: Array[ZonePhase] var current_phase_index: int = 0 var current_radius: float = 2000.0 var target_radius: float = 2000.0 var center: Vector2 = Vector2.ZERO var target_center: Vector2 = Vector2.ZERO var shrink_speed: float = 0.0
func start_next_phase() -> void: var phase = phases[current_phase_index] target_radius = phase.end_radius # Pick new center WITHIN current circle but respecting new radius var random_angle = randf() * TAU var max_offset = current_radius - target_radius var offset = Vector2.RIGHT.rotated(random_angle) * (randf() * max_offset) target_center = center + offset
shrink_speed = (current_radius - target_radius) / phase.shrink_time
func _process(delta: float) -> void: if current_radius > target_radius: current_radius -= shrink_speed * delta center = center.move_toward(target_center, (shrink_speed * delta) * (center.distance_to(target_center) / (current_radius - target_radius)))
undefined

2. Loot Spawner

2. Loot生成器

Efficiently populating the world.
gdscript
undefined
高效填充游戏世界。
gdscript
undefined

loot_manager.gd

loot_manager.gd

func spawn_loot() -> void: for spawn_point in get_tree().get_nodes_in_group("loot_spawns"): if randf() < spawn_point.spawn_chance: var item_id = loot_table.roll_item() var loot_instance = loot_scene.instantiate() loot_instance.setup(item_id) add_child(loot_instance)
undefined
func spawn_loot() -> void: for spawn_point in get_tree().get_nodes_in_group("loot_spawns"): if randf() < spawn_point.spawn_chance: var item_id = loot_table.roll_item() var loot_instance = loot_scene.instantiate() loot_instance.setup(item_id) add_child(loot_instance)
undefined

3. Deployment System

3. 部署系统

Transitioning from plane to ground.
gdscript
undefined
从飞机到地面的过渡逻辑。
gdscript
undefined

player_controller.gd

player_controller.gd

enum State { IN_PLANE, FREEFALL, PARACHUTE, GROUNDED }
func _physics_process(delta: float) -> void: match current_state: State.FREEFALL: velocity.y = move_toward(velocity.y, -50.0, gravity * delta) move_and_slide() if position.y < auto_deploy_height: deploy_parachute()
undefined
enum State { IN_PLANE, FREEFALL, PARACHUTE, GROUNDED }
func _physics_process(delta: float) -> void: match current_state: State.FREEFALL: velocity.y = move_toward(velocity.y, -50.0, gravity * delta) move_and_slide() if position.y < auto_deploy_height: deploy_parachute()
undefined

Key Mechanics Implementation

核心机制实现

Zone Damage

缩圈伤害

Checking if player is outside the circle.
gdscript
func check_zone_damage() -> void:
    var dist = Vector2(global_position.x, global_position.z).distance_to(ZoneManager.center)
    if dist > ZoneManager.current_radius:
        take_damage(ZoneManager.dps * delta)
检测玩家是否在安全区外。
gdscript
func check_zone_damage() -> void:
    var dist = Vector2(global_position.x, global_position.z).distance_to(ZoneManager.center)
    if dist > ZoneManager.current_radius:
        take_damage(ZoneManager.dps * delta)

Networking Optimization

网络优化

You cannot sync 100 players every frame.
  • Relevancy: Only send updates for players within visual range.
  • Frequency: Update far-away players at 4Hz, nearby at 20Hz+ (Server Tick).
  • Snapshot Interpolation: Client buffers headers to play them back smoothly.
你无法每帧同步100名玩家。
  • 相关性系统:仅发送视觉范围内玩家的更新。
  • 更新频率:远距离玩家以4Hz更新,近处玩家以20Hz+更新(服务器 Tick)。
  • 快照插值:客户端缓存数据头以实现平滑回放。

Godot-Specific Tips

Godot专属技巧

  • MultiplayerSynchronizer: Use
    replication_interval
    to lower bandwidth for distant objects.
  • VisibilityNotifier3D: Critical. Disable
    _process
    and AnimationPlayer for players behind you or far away.
  • Occlusion Culling: Essential for large maps with buildings. Bake occlusion data.
  • HLOD: Use Hierarchical Level of Detail for terrain and large structures.
  • MultiplayerSynchronizer:使用
    replication_interval
    来降低远距离对象的带宽消耗。
  • VisibilityNotifier3D:至关重要。对身后或远处的玩家禁用
    _process
    和AnimationPlayer。
  • 遮挡剔除:对于包含建筑的大型地图必不可少。烘焙遮挡数据。
  • HLOD:对地形和大型结构使用层级细节(Hierarchical Level of Detail)。

Common Pitfalls

常见陷阱

  1. Too Main Loot: Too much loot causes lag. Fix: Use object pooling for loot pickups.
  2. Camping: Players hide forever. Fix: The Zone forces movement. Also, anti-camping mechanics like "scan reveals" (optional).
  3. Cheating: Client-side hit detection. Fix: Authoritative server logic. Client says "I shot at direction X", Server calculates "Did it hit?".
  1. Loot过多:过多的Loot会导致卡顿。解决方法:对Loot拾取物使用对象池。
  2. 蹲点:玩家一直躲着不出来。解决方法:缩圈机制强制玩家转移。还可加入反蹲点机制,比如"扫描暴露位置"(可选)。
  3. 作弊:客户端侧命中检测。解决方法:使用权威服务器逻辑。客户端仅发送"我朝X方向射击",由服务器计算"是否命中"。

Reference

参考资料

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