地图加载与碰撞追踪
本页说明一张地图如何从 map de_xxx 命令变成可运行的服务器世界:引擎怎样加载 BSP、建立碰撞模型、把实体字符串交给 server.dll,以及游戏代码最常用的射线追踪 UTIL_TraceLine 最终落到哪里。
相关页面:主循环与 HostState · 实体系统 · 资源与缓存 · 内容工具链
相关源码文件#
engine/host_state.cpp、engine/host.cpp:State_NewGame、Host_NewGameengine/sv_main.cpp:CGameServer::SpawnServer、SV_ActivateServerengine/modelloader.cpp:CModelLoader::Map_LoadModelengine/cmodel.cpp:CM_LoadMap、CM_BoxTraceengine/enginetrace.cpp:CEngineTrace::TraceRaygame/server/mapentities.cpp:实体字符串解析
1. 新游戏流程#
证据:
State_NewGame在需要时按需加载 server.dll,验证地图有效后调用Host_NewGame:engine/host_state.cpp:414-454。Host_NewGame执行游戏类型配置、设置多人标志与监听套接字、SpawnServer、通知插件处理器LevelInit(实体字符串来自CM_EntityString())、SV_ActivateServer,最后在非专用服务器上向命令缓冲写入connect localhost:<port>:engine/host.cpp:6193-6345。SpawnServer释放旧世界与状态、分配 edict、进入ss_loading、按名字加载世界模型(失败则ss_dead),再建字符串表、预缓存世界:engine/sv_main.cpp:2897-2934、engine/sv_main.cpp:2989、engine/sv_main.cpp:3042-3072、engine/sv_main.cpp:3119-3130、engine/sv_main.cpp:3170-3188。SV_ActivateServer回调游戏的ServerActivate、切换为ss_active、创建实体基线:engine/sv_main.cpp:2568-2587。
监听服务器上的本地客户端随后像远程客户端一样经历签入流程(见 网络通道与协议)。
2. BSP 加载#
Map_LoadModel 给加载过程开 4 分钟看门狗,标记已加载,并在 CMapLoadHelper 的初始化/关闭之间调用 Map_LoadModelGuts:engine/modelloader.cpp:5048-5083。Map_LoadModelGuts 先读取 LUMP_TEXINFO 并校验尺寸,然后首先加载碰撞模型 CM_LoadMap,再加载顶点等渲染数据:engine/modelloader.cpp:5088-5124。CM_LoadMap 的定义见 engine/cmodel.cpp:334。
地图中预置的实体由 BSP 的实体字符串驱动创建(玩家、武器、投射物等则在运行时动态创建):LevelInit 调用 MapEntity_ParseAllEntities,按 classname 通过工厂创建实体、解析键值、再统一 Spawn/Activate(详见 实体系统):game/server/gameinterface.cpp:1192-1275、game/server/mapentities.cpp:520-569。
3. 碰撞追踪#
游戏代码的 UTIL_TraceLine 构造 Ray_t 与过滤器后调用 enginetrace->TraceRay:game/shared/util_shared.h:309-317。引擎为服务端与客户端各暴露一个 IEngineTrace 实现:engine/enginetrace.cpp:240-244。
CEngineTrace::TraceRay 的顺序:
- 清空结果,对世界(BSP 刷子)执行
CM_BoxTrace;起点在固体内或过滤器只要求世界时提前返回:engine/enginetrace.cpp:2786-2846。 - 把射线截断到世界命中点,然后用空间分区
EnumerateElementsAlongRay收集沿线实体,按过滤器类型决定是否包含静态道具:engine/enginetrace.cpp:2853-2892。 - 对候选实体逐个
ClipRayToEntity:engine/enginetrace.cpp:1452。
BSP 层的盒体追踪与点内容查询入口:engine/cmodel.cpp:3194、engine/cmodel.cpp:3253、engine/cmodel.cpp:719。