5. 地图设计
2026/4/14大约 6 分钟
地图设计
CS 的地图设计和普通 FPS 完全不同——它不是"随便摆几个障碍物",而是精心设计的战术空间。每张地图都有明确的路线、视线控制和节奏设计。这一章我们从零搭建一张简化版"沙二"(Dust2)风格的地图。
CS 地图设计原则
三条路线原则
每张标准 CS 地图都有三条从 T 出生点通往炸弹点的路线:
┌──────────────┐
│ 炸弹点 A │
└──────┬───────┘
│
┌──────┴───────┐ ← 中路(Mid)
T 出生点 ─────┤ 中间区域 ├───── CT 出生点
└──────┬───────┘
│
┌──────┴───────┐
│ 炸弹点 B │
└──────────────┘
路线 A:T出生 → A大道/A小道 → 炸弹点A
路线 Mid:T出生 → 中门 → 中路 → 连接各点
路线 B:T出生 → B通道/B洞 → 炸弹点B为什么要三条路线?
- 给 T 方提供选择——可以集中兵力走一条路,也可以分散多路进攻
- 给 CT 方增加防守难度——只有 5 个人,不可能同时守住所有路线
- 让每回合的战术都不同——CT 不知道 T 这次会从哪来
视线控制
CS 地图中的每条走廊、每个转角都经过精心设计:
| 设计元素 | 作用 | 示例 |
|---|---|---|
| 长直道 | 远距离交火区域 | Dust2 的 A 大道 |
| 近距离拐角 | 近战和冲锋枪有利 | B 洞的窄通道 |
| 高低差 | 站高处有视野优势 | A 平台比 A 大道高 |
| 掩体 | 藏身和 peek 用 | 箱子、墙壁缺口 |
| 烟雾位 | 可以用烟雾封锁的视线 | A 大道的门洞 |
炸弹点设计
每个炸弹点需要满足:
- 至少两个入口——CT 不可能只堵一个口就守住
- 有掩体——双方都有可以利用的遮挡物
- 有高低差——增加战术多样性
- 开阔但有遮挡——不能完全开阔(T 无法安放),也不能完全封闭(CT 无法反扑)
用 Godot 搭建地图
地图场景结构
Dust2 (Node3D) ← 地图根节点
├── Geometry (Node3D) ← 所有地图几何体
│ ├── Ground (StaticBody3D) ← 地面
│ │ └── CollisionShape3D
│ ├── Walls (Node3D) ← 所有墙壁
│ │ ├── WallAvenueLong (StaticBody3D)
│ │ ├── WallBHallway (StaticBody3D)
│ │ └── ...
│ ├── CoverBoxes (Node3D) ← 箱子掩体
│ │ ├── BoxA1 (StaticBody3D)
│ │ └── BoxA2 (StaticBody3D)
│ └── Platforms (Node3D) ← 高台和楼梯
│ ├── PlatformA (StaticBody3D)
│ └── StairsB (StaticBody3D)
│
├── SpawnPoints (Node3D) ← 出生点标记
│ ├── TSpawn (Marker3D) ← T 出生点
│ └── CTSpawn (Marker3D) ← CT 出生点
│
├── BombSites (Node3D) ← 炸弹点区域
│ ├── BombSiteA (Area3D) ← 炸弹点 A
│ │ └── CollisionShape3D
│ └── BombSiteB (Area3D) ← 炸弹点 B
│ └── CollisionShape3D
│
├── NavigationRegion3D ← AI 寻路区域
│ └── NavigationMesh
│
├── Lighting (Node3D) ← 灯光
│ ├── DirectionalLight3D ← 主光源(太阳)
│ └── WorldEnvironment ← 环境设置
│
└── AudioPositions (Node3D) ← 环境音效位置使用 CSG 搭建地图原型
CSG(Constructive Solid Geometry,构造实体几何)是快速搭建地图原型的最佳工具。你可以把它想象成"搭积木"——用方块、圆柱等基础形状组合出地图的轮廓。
C#
// 地图不需要太多代码,主要在编辑器中用 CSG 搭建。
// 这里展示如何用代码创建一个简单的走廊原型。
// 在地图场景的 _Ready 中调用(仅用于原型验证)
using Godot;
public partial class MapBuilder : Node3D
{
public override void _Ready()
{
// 创建地面
CreateBox(
new Vector3(0, -0.5f, 0),
new Vector3(60, 1, 60),
new Color(0.6f, 0.6f, 0.6f)
);
// 创建 A 大道的墙壁
CreateBox(
new Vector3(-15, 2, 0),
new Vector3(1, 4, 30),
new Color(0.8f, 0.75f, 0.7f)
);
// 创建 A 大道另一侧墙壁
CreateBox(
new Vector3(-5, 2, 0),
new Vector3(1, 4, 30),
new Color(0.8f, 0.75f, 0.7f)
);
// 创建 A 点的箱子掩体
CreateBox(
new Vector3(-10, 1, 5),
new Vector3(2, 2, 2),
new Color(0.55f, 0.4f, 0.25f)
);
CreateBox(
new Vector3(-8, 1.5f, 8),
new Vector3(2, 3, 2),
new Color(0.55f, 0.4f, 0.25f)
);
}
/// <summary>
/// 创建一个 CSG 方块。用于快速搭建地图原型。
/// </summary>
private void CreateBox(Vector3 position, Vector3 size, Color color)
{
var csg = new CSGBox3D();
csg.Position = position;
csg.Size = size;
csg.Color = color;
csg.UseCollision = true; // 启用碰撞
AddChild(csg);
}
}GDScript
# 地图不需要太多代码,主要在编辑器中用 CSG 搭建。
# 这里展示如何用代码创建一个简单的走廊原型。
extends Node3D
func _ready():
# 创建地面
_create_box(
Vector3(0, -0.5, 0),
Vector3(60, 1, 60),
Color(0.6, 0.6, 0.6)
)
# 创建 A 大道的墙壁
_create_box(
Vector3(-15, 2, 0),
Vector3(1, 4, 30),
Color(0.8, 0.75, 0.7)
)
# 创建 A 大道另一侧墙壁
_create_box(
Vector3(-5, 2, 0),
Vector3(1, 4, 30),
Color(0.8, 0.75, 0.7)
)
# 创建 A 点的箱子掩体
_create_box(
Vector3(-10, 1, 5),
Vector3(2, 2, 2),
Color(0.55, 0.4, 0.25)
)
_create_box(
Vector3(-8, 1.5, 8),
Vector3(2, 3, 2),
Color(0.55, 0.4, 0.25)
)
## 创建一个 CSG 方块。用于快速搭建地图原型。
func _create_box(position: Vector3, size: Vector3, color: Color):
var csg = CSGBox3D.new()
csg.position = position
csg.size = size
csg.color = color
csg.use_collision = true # 启用碰撞
add_child(csg)用编辑器搭建更快
上面的代码只是为了说明原理。实际开发中,直接在 Godot 编辑器里拖拽 CSG 节点来搭建地图要快得多。代码方式适合需要程序化生成地图的场景。
导航网格
AI 敌人需要知道地图哪里能走、哪里是墙。Godot 的 NavigationRegion3D 可以自动分析地图几何体,生成"导航网格"——一份描述地图可行走区域的数据。
设置步骤:
- 在地图场景中添加
NavigationRegion3D节点 - 在其下添加
NavigationMesh资源 - 在编辑器的 3D 视图中点击 "烘焙导航网格" 按钮
- Godot 会自动分析所有碰撞体,生成可行走区域
C#
// AI 角色使用导航网格寻路
var navigationAgent = GetNode<NavigationAgent3D>("NavigationAgent3D");
// 设置目标点
navigationAgent.TargetPosition = bombSitePosition;
// 获取下一条路径
var nextPosition = navigationAgent.GetNextPathPosition();
// 向下一个路径点移动
var direction = (nextPosition - GlobalPosition).Normalized();
Velocity = direction * moveSpeed;
MoveAndSlide();GDScript
# AI 角色使用导航网格寻路
var navigation_agent = $NavigationAgent3D as NavigationAgent3D
# 设置目标点
navigation_agent.target_position = bomb_site_position
# 获取下一条路径
var next_position = navigation_agent.get_next_path_position()
# 向下一个路径点移动
var direction = (next_position - global_position).normalized()
velocity = direction * move_speed
move_and_slide()炸弹点区域
炸弹点用 Area3D 定义——当携带 C4 的 T 方玩家进入这个区域时,才能安放炸弹。
C#
// BombSiteDetector.cs - 挂在炸弹点 Area3D 上
using Godot;
public partial class BombSiteDetector : Area3D
{
[Export] public string SiteName { get; set; } = "A";
public bool IsPlayerInSite { get; private set; }
public override void _Ready()
{
BodyEntered += OnBodyEntered;
BodyExited += OnBodyExited;
}
private void OnBodyEntered(Node3D body)
{
// 检查进入的是否是 T 方玩家且携带 C4
if (body.IsInGroup("terrorist"))
{
IsPlayerInSite = true;
}
}
private void OnBodyExited(Node3D body)
{
if (body.IsInGroup("terrorist"))
{
IsPlayerInSite = false;
}
}
}GDScript
# BombSiteDetector.gd - 挂在炸弹点 Area3D 上
extends Area3D
@export var site_name: String = "A"
var is_player_in_site: bool = false
func _ready():
body_entered.connect(_on_body_entered)
body_exited.connect(_on_body_exited)
func _on_body_entered(body: Node3D):
# 检查进入的是否是 T 方玩家且携带 C4
if body.is_in_group("terrorist"):
is_player_in_site = true
func _on_body_exited(body: Node3D):
if body.is_in_group("terrorist"):
is_player_in_site = false光照与环境
CS 的地图不需要花哨的光照,但基本的环境设置能让地图看起来舒服。
C#
// 地图中的光照设置(通常在编辑器中完成)
// 这里展示关键参数
// 主光源(模拟太阳)
var sun = new DirectionalLight3D();
sun.Rotation = new Vector3(
Mathf.DegToRad(-45), // 俯视角度
Mathf.DegToRad(-30), // 方向
0
);
sun.ShadowEnabled = true; // 开启阴影
sun.ShadowBias = 0.01; // 减少阴影漏光
sun.DirectionalShadowMaxDistance = 100f; // 阴影可见距离GDScript
# 地图中的光照设置(通常在编辑器中完成)
# 这里展示关键参数
# 主光源(模拟太阳)
var sun = DirectionalLight3D.new()
sun.rotation = Vector3(
deg_to_rad(-45), # 俯视角度
deg_to_rad(-30), # 方向
0
)
sun.shadow_enabled = true # 开启阴影
sun.shadow_bias = 0.01 # 减少阴影漏光
sun.directional_shadow_max_distance = 100.0 # 阴影可见距离小结
这一章完成了地图的设计和搭建:
- 设计原则:三条路线、视线控制、炸弹点设计
- CSG 原型:用方块快速搭建地图轮廓
- 导航网格:为 AI 角色提供寻路数据
- 炸弹点区域:用 Area3D 检测玩家是否在炸弹点内
- 光照环境:基础的光照设置
下一章我们实现 AI 敌人——让他们能巡逻、寻路、射击和安放/拆除炸弹。
