必威体育Betway必威体育官网
当前位置:首页 > IT技术

游戏中AOI视野算法

时间:2019-09-30 17:45:32来源:IT技术作者:seo实验室小编阅读:65次「手机版」
 

aoi

AOI(Area Of Interest),中文就是感兴趣区域。通俗一点说,感兴趣区域就是玩家在场景实时看到的区域;也就是AOI会随着英雄的移动改变而改变。游戏的AOI算法应该算作游戏的基础核心了,许多逻辑都是因为AOI进出事件驱动的,许多网络同步数据也是因为AOI进出事件产生的。因此,良好的AOI算法和基于AOI算法的优化,是提高游戏性能的关键。

我在实践中所熟知的游戏AOI算法大致有4种,在此做一些总结,顺便梳理一下,打算设计出一套统一的接口封装不同的算法实现。4种算法:全场景同步法(最粗暴简单)、网格法、十字链表法、热点法(云风设计的,暂且叫这个名字)。

统一接口设计:

AOI需求大概是这样:

1.游戏地图上有一些npc和玩家在移动,每一个这样移动的对象我们叫做AOIEntity,每一个AOIEntity可以挂多个不同半径的AOI,每一个这种半径的AOI单元我们叫做AOINode,如此,AOIEntity拥有多个AOINode,然后每一个场景管理者AOIManager管理着多个这样的AOIEntity对象。

2.AOI进出事件由三种行为产生:进入场景,离开场景,在场景移动,因为这是AOIEntity相互之间的作用,故因放在AOIManager中统一管理,接口类似这样:

void AOIManager:Enter(AOIEntity *entity, cosnt Point& target_pos);

void AOIManager:Move(AOIEntity *entity, cosnt Point& target_pos);

void AOIManager:Leave(AOIEntity *entity);

3.添加一个AOINode的接口,主要参数是Id(用于标识这个AOI),半径,进出事件的callback函数

void AOIEntity:AddNode(int aoi_id, float radius, AOICB enter_cb, AOICB leave_cb);

4.获取周围对象和观察者玩家对象集合的接口,这个可以在更上层,通过在响应进出事件的enter_cb, leave_cb中维护这样的集合。

全场景同步法:

即任一实体变动时,都广播给其他在场的所有实体。

适用范围:玩家比较少的小型场景,比如组队副本。

游戏实例:比较早期的游戏,比如:天骄II及其衍生品等。

缺点:玩家较多时,消息量骤增。

优化方案:每个实体变动时,遍历所有实体,判断距离在视野内的,才广播。也可以实时维护这个可见列表。

网格算法:

既是把整个场景用网格划分成一个一个小区域(划分粒度可调整),每一个区域是当前场景该区域内的AOIEntity集合,当有一个AOIEntity移动时,根据对象移动之前坐标和目的地坐标,算出移动前所在网格SrcGrid和目的地网格DstGrid,根据一个可调的偏移参数,算出受这次移动影响的各个网格所在的一个网格区域(通常是一个包含这些网格的一个大网格),遍历每一个这样的网格里的每一个AOIEntity,与这个移动AOIEntity互相作比较,主要是比较这些事情:

1.是不是对方曾经在我的一个AOINode的半径内,移动后就不在了,是则产生离开回调;

2.是不是对方曾经不在我的一个AOINode的半径内,移动后就出现了,是则产生进入回调;

注意虽然移动是一个AOIEntity在移动,但是这种比较却要是互相的。

上面说的是网格算法的最简单实现了,当然实践上有许多地方可以优化和调整,包括使用更高效的数据结构,不细说。

细分:还可以分为“九宫格法”和“灯塔法”。“九宫格法”——每个区域中记录的是处在本区域的实体。“灯塔法”——每个区域中记录的是会观察到我的实体。“灯塔法”可以看做是“九宫格法”的进一步优化。

适用范围:多数2DMMORPG。

游戏实例:天龙八部及其衍生品等。

缺点:存储空间不仅和对象数量有关,还和场景大小有关。更浪费内存。且当场景规模大过对象数量规模时,性能还会下降。

优化方案:区域大小根据场景具体情况进行配置,可提高效率。比如5人副本,可以配成整个场景一个区域。

十字链表算法:

算法基本上就是围绕两个双向链表在转--代表X轴的链表(叫做LinkListX)和代表Y轴的链表(叫做LinkLIstY)。对于每一个AOI单元,以AOIEntity的坐标位置为中心,可以构造出一个AOI矩形(以四元组[xleft,xright,ytop,ybottom]表示)。LinkListX链接的是所有这样的AOI矩形的xleft,xright,LinkListY链接的是所有这样的AOI矩形的ytop,ybottom,并且两者都是按照坐标值从小到大的顺序链接起来的。这样每一个AOI单元都在LinkListX,LinkListY上产生了总共4个节点,特殊的对于每一个可见的AOIEntity,以他们的坐标(XCenter,YCenter)在LinkListX,LinkListY上又产生了总共2个节点。现在当AOIEntity在场景中移动时,他所包含的在LinkList中的节点会相应的更改坐标值,而LinkList为了维护从小到大的顺序,会遍历链表,移动位置,直到重新有序。LinkList在这个过程,会产生AOI事件。

* 具体来说,当AOIEntity要移动到(targetX,targetY), 对应的AOI矩形变成[targetX-R, targetX+R, targetY-R, targetY+R],显然这四个节点值的改变后LinkList不再有序,现在来调整LinkList,可以这样来理解这个过程,对象先在X轴上移动到targetX,对应的是在LinkListX上移动,每次交换两个节点的位置都应该判断:1.两者的拥有者是不是不同的Entity;2.是不是一个是代表Entity的节点,一个是代表AOI矩形边界的节点;3.两者的拥有者整体上能否确实产生AOI进出事件。然后在Y轴上移动到targetY,过程与X轴对称。

* 可以总结一下,LinkList的节点的属性:

struct LinkNode {

byte _type; // 代表类型,主要是区分AOI矩形的边界和Entity本身

AOINode *_owner; // 属于哪个AOI单元,这里把代表Entity本身的节点也当作一个R=0的AOI单元

int _pos_val; // 坐标值,

struct LinkNode *_next, *prev;

}

相关阅读

怎样让一个全新的操作模式进入大众视野?回顾苹果的做法

让人们学会用手指去操控一款电子产品,现在是2岁的孩子都能沉浸其中的游戏。但在2007年,这可以说是苹果最大的一次赌博和冒险。如果

游戏服务端之AOI概述

原文来自:http://blog.csdn.net/yitouhan/article/details/17642587AOI(Area Of Interest),中文就是感兴趣区域。通俗一点说,感兴趣

新视野大学英语(第三版)视听说4答案

Unit 1Sharing3.Answers: b-e-f-d-c-a4. 2 45.anti-socialaware ofappreciateattitudetolerantcome to an endwalk awayimpressLi

分享到:

栏目导航

推荐阅读

热门阅读