游戏中的AOI(Area of Interest)算法

摘要:
AOI(兴趣区域)算法游戏中的AOI算法应该是游戏的基本核心。许多网络同步数据也由AOI输入和输出事件生成。计划设计一个统一的接口来封装不同的算法实现(网络上还有其他算法)。获取周围对象和观察者玩家对象集的接口,并在移动通过响应传入和传出事件的enter_cb之前计算网格SrcGrid和目标网格DstGrid。
游戏中的AOI(Area of Interest)算法



游戏的AOI算法应该算作游戏的基础核心了,许多逻辑都是因为AOI进出事件驱动的,许多网络同步数据也是因为AOI进出事件产生的。因此,良好的AOI算法和基于AOI算法的优化,是提高游戏性能的关键。


我在实践中所熟知的游戏AOI算法大致有两种,在此做一些总结,顺便梳理一下,打算设计出一套统一的接口封装不同的算法实现(网络上还有些其他算法,因为不熟悉不作记录了)。我所记录的这两种算法也算经典了,一个叫做网格法,一个叫做双链表法。

统一接口设计:

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中维护这样的集合。

网格算法:

既是把整个场景用网格划分成一个一个小区域(划分粒度可调整),每一个区域是当前场景该区域内的AOIEntity集合,当有一个AOIEntity移动时,根据对象移动之前坐标和目的地坐标,算出移动前所在网格SrcGrid和目的地网格DstGrid,根据一个可调的偏移参数,算出受这次移动影响的各个网格所在的一个网格区域(通常是一个包含这些网格的一个大网格),遍历每一个这样的网格里的每一个AOIEntity,与这个移动AOIEntity互相作比较,主要是比较这些事情:
1.是不是对方曾经在我的一个AOINode的半径内,移动后就不在了,是则产生离开回调;
2.是不是对方曾经不在我的一个AOINode的半径内,移动后就出现了,是则产生进入回调;
注意虽然移动是一个AOIEntity在移动,但是这种比较却要是互相的。
上面说的是网格算法的最简单实现了,当然实践上有许多地方可以优化和调整,包括使用更高效的数据结构,不细说。



双链表算法:

* 此算法名字是自己取的,因为算法基本上就是围绕两个双向链表在转--代表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;
}


网格算法原理和实现都简单,每次移动时遍历的受影响的单元是以网格为单位,并不是直接以Entity为单位,会产生许多次无效的遍历,对效率产生多少影响也是依赖网格的划分粒度和场景人数,不过总的来说对于不是海量的对象移动,加上一些上层逻辑相关的优化,一般的MMO已经是够用了。
双链表算法,巧妙的把一个AOI矩形拆成4个不同节点,每次移动遍历的受影响的单元直接是以Entity为单位,省去了许多无效遍历,但是在实现上要较网格算法复杂,另外其性能也是受场景中人数的影响。

免责声明:文章转载自《游戏中的AOI(Area of Interest)算法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇阿里大数据竞赛season1 总结CSS让指定的图片实现水平/翻转特效下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

节点操作--JavaScript

1 - 概念 网页中的所有内容都是节点(标签、属性、文本、注释),在DOM中,节点使用node来表示。 HTML DOM树中的所有节点均可通过JS进行访问,所有HTML元素(节点)均可被修改,也可以创建或者删除。 一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。 元素节点 nod...

从BF算法到kmp算法详解

正文索引 一、KMP介绍 二、例子:子串匹配母串 1.BF算法的解决方法 三、kmp算法的实现 (1)为什么已经有BF算法了还要有KMP算法呢? (2)发明的算法基本思想 (3)具体实现 一、KMP介绍 KMP算法是一种改进的字符串匹配算法(有BF算法改进而来,BF算法是暴利搜索匹配的方式,而KMP则是对BF算法的回溯过程进行改进,从而大幅度降低了时间复...

分布式一致性算法--Raft

     前面一篇文章讲了Paxos协议,这篇文章讲它的姊妹篇Raft协议,相对于Paxos协议,Raft协议更为简单,也更容易工程实现。有关Raft协议和工程实现可以参考这个链接https://raft.github.io/,里面包含了大量的论文,视屏已经动画演示,非常有助于理解协议。概念与术语leader:领导者,提供客户提供服务(生成写日志)的节点,...

NLP常用Python开发工具

一、Numpy NumPy系统是Python的一种开源的数值计算包。 包括: 1、一个强大的N维数组对象Array; 2、比较成熟的(广播)函数 库; 3、用于整合C/C++和Fortran代码的工具包; 4、实用的线性代数、傅里叶变换和随机数生成函数。 numpy和稀疏矩阵运算包scipy配合使用更加方便。 安装: pip install numpy 二...

新东方人工智能中台实践和AI部门管理经验分享

文章作者:张建鑫 前言 新东方人工智能开放平台 ( https://ai.xdf.cn/ ) 致力于教育+AI创新,以行业最低价格,提供智能语音、文字识别、人脸人体、自然语言理解等优质AI开放能力,助力中小公司快速低成本创新,全面赋能教育事业。欢迎访问网站,并留下宝贵意见。 与AI同行相比,新东方以少得多的人力和低得多的研发投入,从2020年8月,仅用一年...

TCP 的那些事儿(下)

本文转载自TCP 的那些事儿(下) 导语 这篇文章是下篇,所以如果你对TCP不熟悉的话,还请你先看看上篇《TCP的那些事儿(上)》 上篇中,我们介绍了TCP的协议头、状态机、数据重传中的东西。但是TCP要解决一个很大的事,那就是要在一个网络根据不同的情况来动态调整自己的发包的速度,小则让自己的连接更稳定,大则让整个网络更稳定。在你阅读下篇之前,你需要做好准...