浅谈游戏AI LOD的智能控制——LOD交易员

前引

LOD的概念

提到 细节层次 (Level of Details,简写LOD),大家可能首先会想到图像渲染,像游戏中大地图的3D物体会随玩家与其距离的远近而变化精度(主要是模型面数的变化,有时还会直接剔除)。Unity中的「LOD Group」组件就是做这事的。

而在游戏中这种变化玩家一般是难以察觉的,毕竟远距离的东西本身就不易看清,再让它「模糊」点也不会怎么样。当然,「穿帮」的时候也不是没有,比较常见的就是玩GTA时,远处地面建筑突然出现的情况,只不过一般这些都不会太影响游戏体验。

但现在有了这样可靠的自动调整技术,开发者可以摆放更多/更精致的物体在场景中,而无需太担心玩家设备的渲染压力。可以说LOD成为了现代大型游戏的基石技术之一,能在游戏中看到丰富美丽的画面它厥功至伟。


正文

AI的LOD

图像中的LOD聚焦模型面数的调整,为的是缓解GPU压力;LOD的概念也存在于游戏AI中,AI中的LOD则聚焦的是代码运行「代价」的调整,为的是缓解CPU压力。

AI的LOD通常可以从 复杂度 运行频率 两方面考虑:

  1. 「复杂度」可以通俗的理解为代码逻辑的难易程度。比方说,直线运动的复杂度肯定比A星寻路的复杂度低。在有障碍的地形上,怪物的移动通常要运用寻路算法,但对于那些玩家难以注意到的怪物的运动,我们就可以取巧——暂时用简单的直线运动代替。

  2. 「运行频率」就如其名,指代码运行的频率。比如,我们可以每两帧调用一次怪物AI相关代码而不是每帧都调用,对于更不引人注目的,我们还可以设置为更低。通过减少相关代码运行的次数,也可以降低CPU压力。

例如,我们可以在《原神》团队公布的AI框架设计中看到AI LOD相关内容:

可以看到,实际AI LOD的内容还是很细的,包括了感知、目标搜索、寻路、决策、动画播放等等,「运行频率」最高有30Hz,最低则是5Hz。

那AI LOD的变化要根据什么进行调整呢?也和图像LOD一样 (离玩家距离越近LOD越高,反之越小)么?

这的确是最传统的做法,但其实仔细想想,这样做是有不小局限的:

  1. 限制了角色分布意味着开发者需要在游戏中考虑玩家能够接受的最大NPC数量。如果玩家周围有超过100个智能角色,可能会给玩家的CPU带来过大的压力。因此,开发者不会让一个小区域内出现太多的角色。

  2. AI的真实度也受到了限制。即使采用了出色的AI行为决策方法,使得角色表现更为生动,但如果角色的数量过多,就会产生问题。处理大量AI角色并不是CPU的唯一任务,游戏还有其他要处理的事情。因此,设计过多的AI角色显然是不可行的。

  3. 距离阈值的设置相对繁琐。角色的AI LOD变化很大程度上依赖于事先设定好的距离判定值。这些值需要开发者耐心地调试。例如,当玩家与角色距离小于10m时,角色的AI LOD设置为“高”;当距离大于10m但小于50m时为“中”……这些设定的值就是LOD变化的距离阈值。如果设定的值过小,会使玩家发现游戏的不真实之处;而如果设定的值过大,会导致CPU占用过高,使游戏画面变得卡顿。因此,开发者需要根据经验和耐心地调试,找到合适的阈值。


AI LOD交易员

在这篇论文中,作者提出了一种特别的AI LOD调整方案—— 「LOD交易员(LOD Trader)」。它将运行AI所用到的系统资源视为「可投资的资产」,将场景中的各个AI当作「投资对象」。然后一一与之进行「交易」,即为每个AI确定各自的AI LOD方案,从而使得「利润」最大化——也就是在不透支系统资源的情况下,协调场景中各AI的LOD,使得总体能表现得最具真实性。

1. 特征图

首先要做个预处理工作——绘制好每个AI的 「特征图」。

那什么是「特征」?

例如,之前提到的「感知、目标搜索、寻路、决策、动画播放等等」,这些 AI LOD控制的具体内容 ,我们就称之为「特征」。每个「特征」都应当有多于1个的LOD(否则就没有调整的必要了),以寻路为例,假设它有两个LOD,一个「高」一个「低」,高 LOD 可以表示「使用 NavMesh 寻路」,低 LOD 可以表示「直线穿行抵达」。

我们将所有AI特征与其LOD的组合称为 「特征解决方案」。例如,一个角色AI的所有特征为:模型可见性、寻路、行为动画、目标查找,那么{可见性:高} + {寻路:高} + {行为动画:中} + {目标查找:低},就是一种特征解决方案。

可见,根据这样的排列组合,一个AI会有不少的特征解决方案。而特征之间很多是相互关联的,在这一系列的特征解决方案中,会存在相当一部分不合理的方案。比如{可见性:低}+{寻路:高}+{行为动画:低}+{目标查找:高},这个特征解决方案明显不合理,因为在模型不可见(我们将可见性「低」LOD视为隐藏模型)的情况下高质量寻路毫无意义。

所以,为了更好表示 特征之间的约束关系 从而筛除不合理的特征解决方案,我们使用特征图。它是一种单根节点的无环图,比如论文中的这个包含8个AI特征的特征图:

图中,圆圈表示的就是「特征」,方框表示的就是各特征所有的LOD;比如「Action anims(行为动画)」特征,就有三个LOD——None(无动画)、LQ(低质量)、HQ(高质量),这里高低质量动画可能是通过开关IK动画来区分的。

我们还能看到图中有两种「箭头」——虚线的和实线的。虚线表示的是 LOD切换顺序,比如「Exists」特征,就只能从「Yes」变为「No」,反之则不行;实线表示的是 特征与LOD的依赖关系,比如「Behavior」特征,它只有在「Exists」特征的LOD为「Yes」时才允许采用,也因为有这样的箭头,特征图能 得出「合理」特征解决方案。

作者所用的特征图最终只得出了252个特征解决方案,相比穷举的方式,剔除了非常多的不合理方案。

一个AI就有上百个特征解决方案,那多个AI会过多吗? 以普遍理性而论,特征图是可以共用的,也就是说,一个游戏中的几十种怪物,它们虽然形态各异、动作各异,但都可以用同一个特征图(因为它们的「特征」都相差不大,都有可见性、寻路、行为动画等),所以不必担心特征解决方案数量的问题。而且遍历特征图来得到特征解决方案的过程完全可以在开发时就完成(像使用Navmash那样),而不占用游戏运行。因此,即便有多个特征图或者一个特征图有过多特征也没关系。

2. 评估AI的重要性

区别于传统的根据距离来调节AI LOD的方式,我们会通过AI角色的「重要性」来调整。那何谓「重要」呢?一个游戏任务中,玩家密切追踪的关键剧情角色是重要的;与玩家相距非常近的路人角色也是重要的;玩家刻意聚焦观察的角色也是重要的……可以说,角色的「重要性」与玩家的心理密切相关,玩家关注的角色就需要高的LOD,否则就容易「穿帮」。几乎所有的「穿帮」都可以归为这三类:

  1. 不现实的状态(Unrealistic state,简称 US),一眼假的那些「穿帮」。比如,一个角色从一个空盘子里吃东西,或者穿墙跑,都可能导致不现实状态。

  2. 基本不连续 (Fundamental discontinuity,简称 FD),当角色当前状态与玩家对他过去状态的记忆相悖时,它就会发生。比如,角色在转角处消失,或者在玩家离开时停在原地数小时,都可能产生基本不连续。

  3. 不现实的长期行为(Unrealistic long-term behavior,简称 ULTB), 这种「穿帮」的破坏体验感的程度最轻,通常需要玩家长期观察才能察觉。比如,角色总是随机地而不是有明确目标地行走,汽车永远不会耗尽汽油,诸如此类。

在计算物体在屏幕上占据的画面大小时,一种可行的方法是通过包围盒到屏幕的投影面积。在Unity中,这一信息可以轻松获取,因为Render、Collider、Mesh都具有"bounds"属性,表示对象的包围盒。

虽说我们不会「读心术」,但却有办法「旁敲侧击」玩家对一个角色的关注程度:

1. 角色与玩家视野中心的偏移程度:离屏幕中心越远的角色通常受到的关注较少,因为玩家更倾向于关注屏幕正前方的角色。


2. 玩家对角色的记忆程度:根据遗忘曲线,最近遇到的角色记忆程度较高,因此更受关注。这可以通过时间衰减模型来量化。


3. 玩家对角色的持续观察时间:玩家持续盯着某些角色或者这些角色频繁出现在视野中,可能表示玩家更关注这些角色。


4. 玩家再度观察角色的可能性:与玩家的记忆程度密切相关,高记忆程度的角色更可能被玩家再度观察。论文可能提供了预测玩家再度观察可能性的公式。


在游戏内容方面,一些因素如任务中的关键角色、精英怪、Boss等更可能引起玩家的关注。这些因素是开发者可以根据需要补充的内容。

综合上面这些因素,我们就可以为「重要性」做一个可量化的定义了。在论文中,作者是将其制成了三维的「重要程度向量」,对应造成三种类型的「穿帮」的可能性。

而这个「制成」方式也很简单,只是将相关联的数据进行乘算再乘上一个常数,保证每个数据都有相同的数量级。

3.交易

接下来就是进行LOD交易,也就是调整LOD的过程了。首先还要说明一点,进行交易的LOD资源也是一个N维向量,维度的多少取决于AI消耗的资源类型,像文末实现的项目中,我的资源向量就是4维的(表示CPU、GPU等)。需要注意的是,这个向量的初始值需要提前给定,也就是确认可分配的各资源总量。

还需要为每个LOD 也设置好消耗资源,比如一个特征为「Locomotion」,它其中的「高」LOD资源消耗就是 (10, 10, 10, 10);「中」LOD资源消耗就是 (4, 4, 4, 4)。就像下面这样:

当然,具体数值的设定还要结合特征本身,比如「寻路」几乎不使用GPU资源,那寻路的LOD消耗资源中,GPU相关的数值就可以是0。

既然一个LOD就有一个「资源消耗向量」,一个特征解决方案又是各特征的LOD的组合,而资源的维数也是固定的,那我们可以将一个特征解决方案的资源消耗以矩阵的形式表示(一点线性代数的知识)。

  • 假设,某特征解决方案:{可见性:高} + {寻路:中} + {行为动画:低},那么:

这样一来,一个特征图的所有特征解决方案的系统资源消耗,就可以用一个「矩阵列表」表示了。

整个「交易」过程可用分为2个阶段:

  1. 升级阶段。升级阶段会按照「重要程度向量」从大到小的、尽可能多的选择角色AI的LOD进行升级,直至场景中的所有角色AI都有最高的AI LOD(通常不可能)或者有资源消耗殆尽。这个过程就是最大程度地选择场景中玩家关注的角色,并提高它们的AI LOD。

  2. 降级阶段。在升级状态结束后,如果有资源耗尽,就意味着有「资源总量向量」中有些维度上的数值变为了负数。降级阶段会按照「重要程度向量」从小到大的、尽可能多的选择角色AI的LOD进行降级,从而回收资源,直至资源总量均大于0(也就是没有耗尽现象)。这个过程就是降低玩家不关注的AI的LOD来回收系统资源。

总结

如此,「交易」就可以保证玩家关心的那些角色的AI LOD保持在较高水平并且系统资源还不透支。这其中其实还涉及了很多数学细节,篇幅所限,我无法详细为大家讲解了,感兴趣的可以自行去深挖!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/444078.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CSS基础知识

font-family: "Trebuchet MS", Verdana, sans-serif; 字体栈,浏览器会一个一个试过去看下哪个可以用 font-size16px; font-size1em; font-size100%;//相对于16px 字体大小,需要进行单位换算16px1em font-weightnormal;//400font-weight属性…

ai直播数字人:AI大模型应用开发的神奇世界

当AI技术的发展走向一个新的高峰,AI直播数字人逐渐成为人们关注的焦点。这种全新的数字人形态,通过大模型应用开发,带来了一个神奇世界。 在这个神奇世界里,AI直播数字人可以展现出与真实人类相媲美的外貌和声音。通过先进的图像…

HarmonyOS ArkTS工程目录结构(Stage模型)

1. ArkTS工程目录结构(Stage模型) 官方文档(https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/start-with-ets-stage-0000001477980905-V2) 1.1. AppScope AppScope > app.json5:应用的全局配…

图的单源最短路径问题

目录 一、简述 二、前置配置 三、迪杰斯特拉算法 四、改进的迪杰斯特拉算法 五、贝尔曼福特算法 一、简述 图是一种比较常用的数据结构,将问题转换成图相关的思路也是比较常用的。 图的单源最短路径问题,也就是图中某一个节点到图中其他节点的最短路…

基于SSM的植物园管理系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 开发技术简介 3 1.1 SSM框架 3 1.2 JSON 3 1.3 Ajax 4 1.4 Bootstrap前台框架 4 1.5 Eclipse 4 1.6 本章小结 4 2 系统分析 5 2.1可行性分析 5 2.1.1 技术可行性 5 2.1.2 经济可行性 5 2.1.3 操作可行性 5 2.2 功能需求 5 2.3 用例分析 6…

洞悉 Kubernetes 高阶奥秘:掌控资源、网络、存储,玩转容器化应用!

昨天我们已经入门了K8S,今天带大家学习一下资源、网络、存储这几个进阶的知识点模块内容。这几天陆陆续续会把K8S从头到尾讲一遍,最后会带大家实战一下,下面就开始今天的学习吧。 高级资源和控制器 Kubernetes 提供了一系列高级资源和控制器…

请编程输出无向无权图各个顶点的度 ← 链式前向星存图

【题目描述】请利用链式前向星存图,编程输出无向无权图各个顶点的度。【输入样例】 5 6 1 3 2 1 1 4 2 3 3 4 5 1【输出样例】 4 2 3 2 1【算法分析】 本例需要用到基于链式前向星的广度优先搜索(BFS)。 链式前向星广度优先搜索(B…

JavaScript 实现飞机大战

文章目录 一些关键点概览:核心模块的具体实现示例:飞机类(Plane)的基本结构:子弹类(Bullet)的基本结构:敌机类(Enemy)的基本结构: 基于前面定义的…

Idea创建Maven项目

Maven安装配置步骤: 解压安装 bin目录 : 存放的是可执行命令。(mvn 命令重点关注) conf目录 :存放Maven的配置文件。(settings.xml配置文件后期需要修改) lib目录 :存放Maven依赖的j…

Python快速入门系列-2(Python的安装与环境设置)

第二章:Python的安装与环境设置 2.1 Python的下载与安装2.1.1 访问Python官网2.1.2 安装Python对于Windows用户对于macOS用户对于Linux用户 2.2 集成开发环境(IDE)的选择与设置2.2.1 PyCharm2.2.2 Visual Studio Code2.2.3 Jupyter Notebook2…

bat文件给多个Android设备安装apk

本文是安装一个apk 1、确保以下3个文件在同一个目录下 1>要安装的apk,这里是mmb.apk 2>设备名单,保存在.txt文件中,一行一个设备名,设备名通过adb devices获取,截图中是两个设备 txt文件中的样式 3>要运行…

基于springboot实现大学外卖管理系统项目【项目源码+论文说明】

基于springboot实现大学外卖管理系统演示 摘要 如今,信息化不断的高速发展,社会也跟着不断进步,现今的社会,各种工作都离不开信息化技术,更离不开电脑的管理。信息化技术也越来越渗透到各小型的企业和公司中&#xff…

AI 资讯 | GPT-4 时代终结!Claude 3 一举成为地表最强 AI 模型,今天就能用上!

AI 的飞速发展,对开发者而言意义重大。为此,我们精心筛选了最新 AI 相关资讯与大家分享交流。 未来,Apifox 也将时刻关注 AI 领域发展动态,及时呈现全面的 AI 资讯,与大家一起把握 AI 机遇。希望 在这些资讯中&#xf…

3.9Code

基于顺序存储结构的图书信息表的图书去重 #include<iostream> #include<stdlib.h> #include<string.h>typedef int status;#define OK 1using namespace std;typedef struct{char no[50];char name[50];float price; }Book;typedef struct{Book* elem;int …

J8 - Inception v1算法

目录 理论知识Inception卷积计算 模型结构模型实现inception 结构GoogLeNet模型打印模型结构 模型效果总结与心得体会 理论知识 GoogLeNet首次出现就在2014年的ILSVRC比赛中获得冠军&#xff0c;最初的版本为InceptionV1。共有22层深&#xff0c;参数量5M。 可以达到同时期VGG…

【C++进阶】哈希的应用 --- 布隆过滤器

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

申请公众号上限是多少

一般可以申请多少个公众号&#xff1f;公众号申请限额在过去几年内的经历了很多变化。对公众号申请限额进行调整是出于多种原因&#xff0c;确保公众号内容的质量和合规性。企业公众号的申请数量从50个到5个最后到2个&#xff0c;对于新媒体公司来说&#xff0c;这导致做不了公…

七、软考-系统架构设计师笔记-数据库设计基础知识

1、数据库基础概念 数据库基本概念 数据(Data)数据库(Database)数据库管理系统(DBMS)数据库系统(DBS) 1.数据(Data) 是数据库中存储的基本对象&#xff0c;是描述事物的符号记录。 数据的种类&#xff1a; 文本、图形、图像、音频、视频等。 2.数据库(Database, DB) 数据库…

【Python+Selenium学习系列5】Selenium特殊元素定位之-鼠标悬停操作

前言 Selenium模拟用户在浏览器中的操作&#xff0c;比如点击按钮。在某些场景下&#xff0c;我们需要模拟鼠标悬停的操作&#xff0c;来触发一些隐藏的元素。本文将介绍Python Selenium实现鼠标悬停操作。 鼠标悬停&#xff0c;即当光标与其名称表示的元素重叠时触发的事件&…

菜鸟笔记-14Python绘图颜色使用

Python中绘图主要依赖于各种库&#xff0c;其中matplotlib是最常用且功能强大的一个。在matplotlib中&#xff0c;你可以使用各种颜色来表示不同的数据点、线条或填充区域。下面我将详细介绍如何在Python中使用matplotlib来设置绘图颜色&#xff0c;并给出具体的例子。 14.1颜…