Javascript 为笛卡尔平面上的单位优化每个循环的嵌套
一个游戏中有大量的单位对象被放置在一个数组中 这些单位具有x/y坐标,可在二维地图上定位Javascript 为笛卡尔平面上的单位优化每个循环的嵌套,javascript,arrays,algorithm,dictionary,Javascript,Arrays,Algorithm,Dictionary,一个游戏中有大量的单位对象被放置在一个数组中 这些单位具有x/y坐标,可在二维地图上定位 let units = [ {id: 1, x=3450, y = 1456}, {id: 2, x=5560, y = 2423}, {id: 3, x=1321, y = 3451} ] 大约每秒50次,游戏要求每个单位生成给定距离内其他单位的列表(通过战斗/躲避等方式与他们互动) 当单位计数增加到数千时,当前每个单位检查彼此单位之间距离的过程会急剧减慢,因为您开始获得指数级的
let units = [
{id: 1, x=3450, y = 1456},
{id: 2, x=5560, y = 2423},
{id: 3, x=1321, y = 3451}
]
大约每秒50次,游戏要求每个单位生成给定距离内其他单位的列表(通过战斗/躲避等方式与他们互动)
当单位计数增加到数千时,当前每个单位检查彼此单位之间距离的过程会急剧减慢,因为您开始获得指数级的所需测试
通过研究在线发布的类似问题,我们开始将单元分组到行/列单元集合中,然后只对那些“可能”足够接近且相关的单元执行距离测试。然而,我们发现构建这个分组实际上需要比它提供的收益更长的时间来构建和维护
下面是当前代码的一个可测试版本-在我相当典型的浏览器上,这需要大约一秒钟的时间来完成,并且需要对其进行大幅改进-欢迎提供优化建议
//创建世界
设mapWidth=5000;
设mapHeight=2000;
设releventDistance=200;
让unitCount=5000;
//新单位函数在地图上的随机位置创建一个单位
功能新单元(id){
设newUnit={};
newUnit.id=id;
newUnit.x=Math.floor(Math.random()*mapWidth);
newUnit.y=Math.floor(Math.random()*mapHeight);
//这一系列的“相关”邻居是足够接近的其他单位的集合,可以与之互动
newUnit.neights=[];
返回新单元;
}
//简单距离测试
功能距离(单位1、单位2){
设dx=unit1.x-unit2.x;
设dy=unit1.y-unit2.y;
返回Math.sqrt(dx*dx+dy*dy);
}
//单位集合
var myUnits=[];
//填充单元
for(设i=0;i{
myUnits.forEach(unit2=>{
//不要针对单元本身进行测试
if(unit.id!=unit2.id){
设unitDist=距离(单位,unit2);
if(unitDist{totalneightourcount+=myUnit.neights.length});
console.log(Math.floor(totalNeighbourCount/myUnits.length)+“:平均邻居数”);
您只能从索引加上一个内部循环进行迭代,并避免访问已访问的对
这种方法需要将该对添加到每个邻居
//创建世界
设mapWidth=5000;
设mapHeight=2000;
设releventDistance=200;
让unitCount=5000;
//新单位函数在地图上的随机位置创建一个单位
功能新单元(id){
设newUnit={};
newUnit.id=id;
newUnit.x=Math.floor(Math.random()*mapWidth);
newUnit.y=Math.floor(Math.random()*mapHeight);
//这一系列的“相关”邻居是足够接近的其他单位的集合,可以与之互动
newUnit.neights=[];
返回新单元;
}
//简单距离测试
功能距离(单位1、单位2){
设dx=unit1.x-unit2.x;
设dy=unit1.y-unit2.y;
返回Math.sqrt(dx*dx+dy*dy);
}
//单位集合
var myUnits=[];
//填充单元
对于(让i=0;i使用for(const unit of myUnits){}
而不是myUnits.forEach(unit=>{})
将时间缩短一半,这是一个有趣的观察结果,我同意这很有帮助!你能解释一下为什么吗?这个提示不会改变O(n)的复杂性,但是计算平方根是一个昂贵的操作(在这些级别上)。最好只预计算一次releventDistanceSquared=releventDistance*releventDistance;
,然后使用函数平方距离(unit1,unit2)
进行比较。这是一个合理的优化,没有缺点,谢谢