整体概述参见:http://dreamyouxi.com:7129/blog/1203

物理应用中,性能消耗的大头主要来自两类操作:模拟和查询。大地图场景下,计算压力会更为突出。

以子弹飞行为例:若采用 CCD(连续碰撞检测)思想进行模拟,一发子弹的开销就相当可观。一般人的碰撞盒高度约为 1.8 米、宽度 0.5 米,因此场景查询步长取 0.5 米基本是可接受的最小值。子弹 1 秒飞行 400 米,需要迭代 800 次,开销极为巨大——单 CPU 测试下,1 秒仅能迭代 120 万次便已饱和。

在这个典型场景中,查询 1 万次的消耗约为 9ms。

CreateTestcast([=](Room*room)
{
	auto pre = PrefabsCache::GetInstance()->GetTestPrefab(TestPrefab::PlayerTmp);
	PrefabsCache::GetInstance()->GetPrefabs(100)->CreateGameObject(room);

	pre->transform.position.Set(3.0f, 10.0f, 0.0f);
	auto obj = pre->CreateGameObject(room);

	auto now = std::chrono::system_clock::now();
	for (int i = 0; i < 1200000; i++)
	{
		room->GetPhysicsScene()->Raycast(Vector3f(357.0f, 75.0f, 487.0f), Vector3f::down(), 30.0f, LayerMask::MaskAll);

	}

	auto cost = chrono::duration_cast<chrono::milliseconds> (chrono::system_clock::now() - now).count();
	cout << "cost time ms=" << cost << endl;
});

若以 64 人战斗为例,一帧内每个玩家仅能进行 156 次查询。射速按一帧移动 20 米计算,套用上述模型,每帧只能支持模拟约 4 发子弹,代价相当高昂。普通 AK 步枪的射速约为每秒 10 发,这已经是当前的性能上限。

要强行支持更高计算量,意味着单核会成为瓶颈,因此必须引入多核心支持。基本思路是分治:将大地图拆分为 N 个小地图,算法原型与八叉树的思想基本一致,从而实现及时完成计算任务的目标。

额外的难点在于:不同 CPU 核心所负责的场景之间需要无缝衔接,同时还要处理线程安全性问题——无论是场景查询还是物理模拟,都面临同样的挑战。

在查询场景中,还可以考虑一些辅助手段来加速处理,例如对部分情况利用高度图实现常数级查询。