创建游戏中的人类世界:数据驱动的开放世界AI框架

Oasis AI Minecraft:全球首个全AI驱动实时生成游戏的潜力与挑战 Oasis AI Minecraft 是全球首个由 AI 实时生成的开放世界游戏,由 Decart 精心打造。通过 AI 技术实现的动态场景生成和玩家交互,Oasis AI Minecraft 为玩家带来了超越传统游戏的沉浸式体验。本文将深入探讨这款游戏的核心功能、背后的技术原理,以及当前存在的一致性挑战和潜在解决方案。作为AI生成内容在游戏领域的创新尝试,Oasis AI Minecraft展现了其在未来游戏市场的巨大潜力,带领我们开启全新的虚拟探索时代。 阅读详情

 

//原文链接:http://www.gamasutra.com/view/feature/1862/creating_all_humans_a_datadriven_.php?page=3

 

A Gamasutra featured article

 

Creating All Humans: A Data-Driven AI Framework for Open Game Worlds

创建人类世界:数据驱动的开放世界AI框架

 

Populating an entire game world with characters that give an impression of life is a challenging task, and it's certainly no simpler in an open world, where gameplay is less restricted and players are free to roam and experience the world however they choose. The game engine has to be flexible enough to react and create interesting scenarios wherever the player goes. In particular, the demands on the AI are different from a linear game, requiring an approach that, while using established game AI techniques, emphasizes a different aspect of the architecture.

赋予游戏世界生动逼真的人类生活是一项很具挑战性的工作。在开放游戏世界下,游戏范围受到限制但是玩家可以自由的漫游在开放的世界并且时时刻刻体会他们选择的这个虚拟的世界,开放游戏世界下完成这项工作不会带来任何简化。游戏引擎必须担负这样的一项使命:即无论玩家走到哪里,它都必须创建一个生动活泼的场景。特别的这项工作对AI的要求和线性游戏AI的要求不一样,虽然采用的仍然是现存的AI策略,但是整个AI的架构不尽相同。

 

This article discusses the data-driven AI architecture constructed for Pandemic Studios' open world title Destroy All Humans 2. It describes the framework that holds the data-defined behaviors that characters perform, and how those behaviors are created, pieced together, and customized.

这篇文章讨论了数据驱动的AI架构,该架构由Pandemic工作室的开发世界为游戏‘毁灭人类2’构建,它描述了框架如何产生角色所需的行为动画,将其放置在一起,并定制最后呈现在场景中。

The premise of an open world game with sandbox gameplay is to give players the freedom to do what they want, the freedom to create their own game within the world the developers provide. Their play is not linear, which is fantastic for a sense of immersion, but reduces the ability of the game developer to control, limit, and pre-script scenarios that the players encounter.

受限的开放世界游戏的出现就是给予玩家自由在这个世界里创建他们自己想要的游戏,其游戏性是非线性的,无疑带来很高的沉浸感,但是同时降低了游戏开发人员控制,限制,预先制定场景脚本的能力

The AI code needs to be built on a foundation that is flexible enough to respond to any eventuality. It needs to handle a domain of gameplay that is broader in scope than a linear title and react to situations that might not have been anticipated. In effect, the AI needs to have a strong emphasis on breadth of behavior over depth. That is, the architecture must promote the ability to create large numbers of behaviors and make applying them to characters as easy as possible.

这样的AI代码需要构建在这样的基础上:灵活并且能够响应各种偶然事件。它需要处理比通常的线性游戏更大的游戏范围,也就是要处理那些没有预期到的场景。从实质来说就是AI构建要更加注重广度而不是深度,即AI框架必须要能够创建非常广泛的行为并且将其应用于各种各样潜在的场景。

One solution to this challenge is to make the behaviors data-driven. They should be created without requiring changes to code, pieced together and reused as shared components, and substituted out for specialized versions. Ideally, the developer should be able to tweak not only the settings of a behavior, such as how long a timer lasts or how aggressive an enemy is, but also the very structure of the behavior itself. For example, what steps are needed to complete a given task or define how those steps are performed? By allowing our behaviors to fit into multiple situations, be reusable, and be quick to create and customize, we can more effectively create all the actions that the characters will need to give the game life.

解决方法之一就是使行为的定义变成数据驱动的,行为应该的创建应该不影响到编码,应该可以被串接起来并且能够复用。同时能够被泛化的版本替代;理想的说开发者不仅应该把握行为包含的属性例如:持续时间多长,攻击力为多少;同时也要能够改变行为的过程,例如:完成指定的任务需要哪些步骤。通过定义这样的行为,他们易于应该到各种场景,能够复用,并且能够迅速的创建和定制,这样我们就能够更加有效的创建给予游戏中声明丰富行为的开放世界游戏。

 

Behavior Foundation: Performing Tasks with Sub-Tasks

行为基础:将任务分解为子任务

The basis for the behavior system in Destroy All Humans 2 is a hierarchical finite state machine (HFSM), in which the current state of an actor is defined on multiple levels of abstraction. At each level in the hierarchy, the states will potentially use sub-level states to break their tasks into smaller problems (for example, attackenemies is at a high level of abstraction and uses the less-abstract fireweapon below it to perform part of its function). This HFSM structure is a common method used in game AI to frame a character's behaviors. It has several immediate benefits over a flat FSM. (For current information about HFSMs, see Resources)

毁灭人类2中的行为系统的基础是树状的有限状态机hierarchical finite state machine (HFSM),该技术下角色的当前状态是通过多层不同程度的抽象完成的,该行为树状体系中的每一层 其对应属性都会使用其子节点的抽象来构建更高一层的行为状态。例如:攻击敌人行为是一种高层的行为抽象,其子节点则可能定义了开火这样的行为抽象。HFSM架构是游戏AI中架构游戏角色行为AI的一种常见手段,和平展的状态机相比有许多优点。(关于HFSM的更多信息可以参见附录)

 

In our implementation, each state in the HFSM is called a behavior and makes up the basic architectural unit of the system. Everything that characters can do in the game is constructed by piecing together behaviors in different ways that are allowed by the HFSM. A behavior can start more behaviors beneath it that will run as children, each performing a smaller (and more concrete) part of the task of the parent. Breaking each task into smaller pieces allows us to reap a lot of mileage out of the behavior unit-reusing it in other behaviors, overriding it in special cases, dynamically changing the structure, and so forth-and spend more time making the system intuitive and easy to modify.

在我们的实现中,HFSM中的每一个状态被称为行为并且构成了系统的行为基本单位。角色能够完成的所有行为都是通过以不同的路径串接这些基本的行为得到的,通过一个行为的下属子行为角色能够完成更多不同的行为,每一个子行为都进行一种相对于父行为更为具体的任务,将一个任务分解为一系列子任务使得我们能够最大程度的复用行为,创建特殊情况下的行为,动态的改变行为等等。当然这样的系统更具启发性并且更易于改写。

 

Starting children. There are many ways to break a task into smaller pieces, and the correct choice ultimately depends on the type of task. Does the task require maintaining certain requirements, performing consecutive steps, randomly performing an action from a list, or something else? In our implementation, we allow several methods of breaking down a behavior into smaller pieces by allowing different ways to start children behaviors.

启动子行为. 有很多种策略将行为分解成更小的子行为,正确的方法取决于任务的类型,例如任务需要满足特殊的需要么?连续的执行各个子步骤还是随机的执行子步骤,或者其他?我们的实现中,我们通过允许以不同的方式启动一项任务这样将一项任务分解为各项子任务

 

Prioritized children. The first and most common way to start children is as a list of prioritized behaviors. Behaviors that are started as prioritized will all be constructed at once (memory is allocated for them and they are added as children of the parent) and set into a special pending mode. (See Figure 1.)

优先的子行为. 最常见开始子行为的方式是通过列出优先排序后的行为完成的,优先启动的行为马上就会被创建(内存分配后被添加为父行为的子状态节点)然后被设置为一种特殊的悬挂模式(见图1)

FIGURE 1 A combat behavior starts prioritized children, which in turn starts more prioritized children. Pending behaviors are orange and active ones are blue.
图1 一个战斗行为启动了一个优先子状态,该子状态启动了更多的优先子状态
悬挂状态为橙色,活动状态为蓝色

When a behavior is in pending mode, it is not updated; instead, it waits until the behavior itself decides it can activate, based on its own settings. When activated, the behavior will in turn start any children it has. Only active behaviors can have children, so a pending behavior will wait before starting its children.

As a rule, only one active behavior can run beneath a given parent, which creates a problem: what to do when multiple behaviors are able to run. We need to set a priority to determine which sub-task is more important. When starting children as prioritized, we define their priority implicitly based on the order the behaviors are added to the parent. The earlier a behavior is listed, the higher its priority (see Isla in Resources).

当一种行为处于挂起状态的时候,它不会被更新;相反,它会等行为自身通过判断其本身的一些设置决定它本身是否应该被激活,当行为被激活后它可以激活任意的子行为。只有活动的行为才会有子行为,所以挂起的行为会等待被激活然后启动其子行为。作为规定,只有一个活动的状态可以在一个给定的父状态下运行,这也带来了一个问题:当一个父行为对应若干个子行为可以运行的时候应该运行哪个行为呢?我们需要设定一个优先级来决定到底哪一个子行为更加重要,当启动的子行为被优先排序后我们可以隐式的定义优先权为它们被添加到父状态的顺序。行为越早被加入到父状态节点中行为就拥有越高的优先权(参见附录中的ISLA)

This solution avoids the problem that would have resulted had we determined priority strictly by number, such as priority-creep, in which priorities become larger and larger, trying to trump the rest. Here we localize the priority definition, so it's only relative to the small subset of behaviors that are started as siblings.

这种办法避免了严格依照预定义的数字作为优先权的问题,例如优先权怪物问题:优先权的值变得越来越大因为对应的行为要优于某行为。这样我们就限定了优先权的定义,只有节点的一个小子集可以作为优先权限定。

In the example above, we see a hierarchy of behaviors and the children available under each, with fire active as a child of attack, which in turn is active as a child of combat. If the currently pending behavior (dodge) were to determine that it needs to start (when the NPC detects it is being fired upon), it will interrupt its active sibling (attack) and revert it to pending, which in turn will delete all children of attack. Once no other active sibling behaviors are running, dodge may begin.

在上面的例子中,我们看见了行为体系树和它可用的状态,FIRE是ATTACK行为的子行为并被激活,而ATTACK又是COMBAT的子行为,如果当前的挂起状态闪避决定它要被激活(例如NPC检测到了攻击行为),那么它就会打断其兄弟行为 攻击的执行,将其转换到挂起状态,这一操作会导致攻击状态的所有子状态全部被删除,一旦没有其他的兄弟行为正在运行那么 闪避状态就可以转入运行了

 

This method of applying priority implicitly works well in most cases, but sometimes the importance of the tasks cannot be described with a simple linear ordering. To handle cases in which a behavior is doing something important and should not be interrupted by non-critical tasks (even if they're higher priority), we can implement a feature called "can interrupt." Essentially, an active behavior may receive a boost in priority, preventing interruption during specific parts of its execution.

通常这种采用优先排序的隐式策略能够很好的工作,但是有时复杂任务不能通过简单的线性排序完成,为了描述系统正在完成一项复杂的工作而不应被非重要任务打断的时候,我们引入了一种称为“可以打断”的策略。实际上,一个激活的行为可以优先接受一个优先级提高这样就可以避免该任务在执行的时候被打断了。

 

With this boost, priorities can be specified in ways more complex than simple linear ordering. For example, while melee is listed at a higher priority than dodge in Figure 1, it should still be allowed to finish its animation even if dodge decides to start-by giving it a boost in priority while running, we prevent dodge from cutting it off mid-animation.

通过这种优先级提升,优先权的定制就可以更加复杂了而不是原先的线性控制了。例如在图1中‘混战’的优先级要高于‘闪避’,但是闪避仍然可以完成其动画的执行,只要在开始激活的时候给予其优先级提升,这样就可以避免闪避动画被‘混战’中断。

 

Sequential and random children. Other ways to start child behaviors are known as sequential and random. Behaviors that are started sequentially are run in the order that they are listed. If the first can run, it will do so until it completes on its own, followed by the second, and so on. When the last behavior in the sequence finishes, the parent finishes as well. For a group of child behaviors started randomly, only one will be chosen to run, and the parent will complete once its child finishes.

顺序和乱序的子状态. 其他的启动子行为的方法被称为顺序和乱序. 顺序启动的行为并按照其列出的顺序执行完,这样的行为执行成为顺序执行,如果第一个行为可以执行,那么它启动并且完成它的任务,然后第二个执行以此类推,当序列中的最后一个行为执行完毕那么该序列行为也执行完毕。如果一个群组中的子行为任意的开始,只有一个会被选中执行,当该选中任务执行完毕后,改乱序执行也就执行完毕

 

Non-blocking children. Behaviors can also be started as non-blocking, in which case they may activate even if there are already other active behaviors running beneath the parent. They exist outside the prioritized list. These behaviors are useful for performing tasks that work simultaneously with others, such as firing while moving, or playing a voice over on a specific condition, or activating and deactivating effects. Generally, anything performed by a non-blocking behavior must not interfere with any other sibling behaviors that might be running, since a non-blocking behavior will only be interrupted when its parent is deactivated (and never by a sibling behavior).

非阻塞的子行为 行为同样可以有非阻塞的行为,即使已经有其他激活的行为在其父行为下运行,该非阻塞行为也可以运行,非阻塞行为存在于优先队列之外。这样的行为对于执行那些并发的行为是非常有用的,例如行进的时候开火,例如在特定的情况下发出声音,又如激活和阻塞效果。总之,任何非阻塞行为进行任何动作不能妨碍当前正在运行的行为的执行,只有其父行为被阻塞,非阻塞行为才会被阻塞;非阻塞行为永远不会被其兄弟行为阻塞

 

By using various combinations of these methods up and down the tree, we can form decisions and task handling over multiple levels that would be difficult to define in a single behavior.

通过采用这些策略的各种组合,穿梭于该多层决策树,我们可以形成决定和通过多层协调的任务的解决方案,而这一些如果只用单层平展的决策状态机是很难完成的。

 

Building New Puzzle Pieces构建新的解谜部件

From this framework, we have defined the basic unit that will be used to construct HFSMs: the behavior. Now, by making behaviors sufficiently data-driven, we can expose not only their values and settings for modification, but the structure of the actions they perform as well. (See Figure 2.)

从这个框架,我们已经定义了用来创建HFSM的基本单位,而行为就要通过数据驱动的策略来构成,我们不仅可以暴露行为和值的设定以供修改,而且行为的组成也可以拿出来修改

FIGURE 2 When either of this behaviour unit's preconditions are satisfied, it will activate, passing the stimulus source parameter to its two children. Since the children are prioritized, the higher-priority flee child will run whenever it can, allowing cower to activate only when it fails.
图2 当任意两个该单元被激活的前置条件满足的时候,该行为就会被激活,同时将刺激源参数传递给其子状态,由于其子状态是优先排序的,因此当条件满足的时候只有‘逃跑’状态会被激活,当逃跑失效的时候,‘退缩’状态才可能启动

Each behavior is self-contained. Everything about it is determined within the behavior itself: when it can activate, when it can no longer run, what interrupts it, and what it does on activation, deactivation, and update. Most significantly, though, it defines what children it starts. Each of these features of a behavior are set within a .behavior file, one per behavior, which is parsed and read in with the rest of the game data.

每个行为都是自包含的,所有关于该行为的策略制定都是在其内部完成的;什么时候被激活,什么时候停止运行,什么状态能够打断其执行,激活的时候完成什么,阻塞的时候完成什么,更新的时候完成什么;最重要的是它决定了它的哪一个子行为应该启动,所有的行为的这些特性都是通过.behavior文件内部的定义来完成的,每个行为对应一个behavior文件;该文件于游戏的运行的时候被解析并使用。

 

Once a behavior is created in a pending state, its duty from then on is to decide when it can activate, since it contains its own activation requirements. These requirements are defined by attaching a list of precondition objects to the behavior. A precondition is a set of rules that may be evaluated to be true or false after checking conditions from the world. Game events, the health level of the character, and commands issued from a squad leader are all conditions that can contribute to activating a behavior, and a precondition can be configured to query any of them.

一旦一个行为被创建并被挂起,那么自那时起其任务就是要决定它什么时候应该被激活,状态控制文件里包含了它被激活的前置条件;这些条件通过为该行为设置一系列的前置条件而起作用;所谓的潜质条件就是一系列能够在运行时判定真假的规则,在检测游戏条件,游戏事件,角色的健康状态,以及命令发射情况等等,这些做法都可以作为行为被激活的前置条件。当然任何的前置条件也应该被设计为可以查询这些游戏条件。

 

The settings that define a precondition are stored in a separate file and can be reused by other behaviors as well. This allows us to construct a library of preconditions that are easily selected for a new behavior simply by listing them in the behaviors configuration file.

这些前置条件的设置被保存在另外单独的文件中以便于其他行为的复用,这样就使得我们构建一个前置条件库。这样做以后设计前置条件的时候我们只需要在行为配置文件中列出前置条件库中对应的前置条件而已。

 

Once a behavior is activated, it can perform its actual purpose, which in most straightforward cases is data-defined as well. Any behavior can start an asset on the character (play an animation, sound, or effect) or start more children without requiring any code side changes, which gives us tremendous flexibility in being able to quickly flesh out the structure of new behaviors. For more complicated actions, we use code-supported behaviors.

一旦一个行为被激活,那么它就可以完成其使命,行为的目的大多数的情况下也是通过数据来定义的。任何的行为都可以给角色带来一系列的变化(例如播放一段动画,声音,或者是效果),也可以在不改变代码端的情况下引起更多的行为,这样的实际就给我们迅速的设计新的行为组织带来了巨大的便捷.对于更多复杂的行为,我们将采用代码端支持的特殊定义行为法

 

A code-supported behavior has all the configuration settings available to a base-level behavior, but with some extras available that plug into a corresponding module created in code. Fireweapon, pathfollow, and melee are examples of behaviors that have a code side associated with them, performing actions that would be too specific to generalize and make available for all behaviors. In fireweapon we have, for example, settings for "delay between shots" and "shots to fire in a burst," that would be useless on most other behaviors. These code-supported behaviors fit into the tree like any behavior and are typically found as the leaves of an HFSM, used at the bottom level as children of more abstract behaviors. Generally, the role of the higher-level behaviors is to separate out objects and tasks that need performing on those objects, and then start children to make them happen.

代码端支持的特殊性为具有基本级别行为的所有设定,不同之处在于它额外的需要代码端创建的一个相应的特殊的插入模块.武器开火,行进路径,逃跑都是具有代码端支持的特殊行为,这些行为执行时候具有一般行为所不具有的特殊性。例如在‘武器开火’行为中我们具有 开火延迟 突然开火这样对立的突发状态,这些状态对于其他大多数的行为来说是没有意义的。这些特殊的行为也可以整合进原来的行为状态树而且通常作为叶子节点出现,也即作为最具体的行为出现。总而言之更高级别抽象行为的任务就是要分理处这样的行为并决定作用于哪些对象,并且在指定的时候启动这些子行为。

 

However, because the objects we're dealing with aren't defined until the game is actually running (such as the current target of a character during a battle or the last person to damage the player), we need a way to reference and make decisions about those objects within our behaviors. We need a parameter system.

然而,因为行为所处理的对象要到游戏运行的时候才会产生(例如当前的攻击目标,攻击我的玩家),我们需要一种方式来引用这些对象,并且在行为内部制定决策如何决定这些对象,我们需要一种参数系统。

Connecting Objects to Behaviors

将作用对象关联到行为

Giving behaviors a list of settings in their configuration file adds a lot of generalization to the system, but it does not allow objects to be dynamically manipulated at run time, responding to arbitrary situations. For example, the target of fireweapon cannot be known when that behavior is being written, as it will vary. Each behavior must be able to understand and make decisions about arbitrary game objects in the world, decided at run time.

给予行为配置文件一系列设定的做法是的系统的兼容性大大提高,但是它并没有使得行为的作用对象在运行时得到处理,例如 ‘开火’行为的作用对象无法获知,因为该对象在运行的时候是不断变化的。每一个行为必须能够理解并决定在游戏运行时候的任意的游戏对象。

 

The solution we used in Destroy All Humans 2 was to allow parameters to be passed from a parent to its children when the children were created, letting those behaviors query and manipulate the object passed in as a parameter or pass it along to their own children.

我们在游戏 毁灭人类2 中用到的解决策略是当子行为创建的时候允许参数能够从父行为传递到子行为。允许这些被创建的子行为查询或者使用这些游戏对象或者它们将其传递给它们自己的子行为

 

Any behavior that needs to accept a parameter defines a slot for it, which must be filled by whatever parent behavior activates it as a child. From there, the variable in that slot can be used in a number of ways: it can be passed on to its own children, sent an event or message, or, for code-supported behaviors, made available to the code side. Pathfollow will seek to the object passed as its first parameter, for example, while melee will swing in the direction of its first parameter.

任意需要接受参数的行为就定义了一个插槽,这些插槽需要其父行为在创建他们的时候填充。从那时起这些插槽就可以派上不同的用处了:可以传递给自己的子行为,发送一个事件或者行为,或者对于代码支持的行为,这些对象就可以为代码插件所用。 例如寻找路径行为将寻找传送给它的第一个对象,而逃跑则会扔掉传递给他的第一个参数

 

With this addition, the states in our HFSM can essentially send objects along their transitions (in our case, between parent and child), plugging them into other behaviors that expect them and use them as a target of their functionality. It's a way to blend some script-like functionality into the more rigid structure of an HFSM, giving extra flexibility without sacrificing organization.

另外,我们HFSM中的状态能够在状态转移的时候传送游戏对系那个(在我们的例子中在父行为和子行为之间交换游戏对象),也可以将这些游戏对象插入到那些需要这些游戏对象(将这些游戏对象作为其功能目标)的行为中,这是一种将脚本式的功能和严格的HFSM结构融合的一种方法,这种做法给游戏AI带来了额外的灵活性并且不牺牲任何的结构组织代价

 

Between concrete and abstract are partially-implemented behaviors. The ability to bypass parameters opens up a lot more ways to use behaviors, and many uses of parameters became quite common in our implementation. To help us with some of the standard ways in which parameters could be used, a few partially-implemented behaviors were created that would handle some standard tasks on the code side, even though they themselves were not full code-supported behaviors. That is to say they didn't belong as leaves of the HFSM; they were just helper behaviors that were still abstract until they were given the data that configured their actions.

在具体和抽象之间是部分实现的行为,通过传递参数使得我们可以以更多的方式来使用我们的行为,在我们的实现中参数的多种使用方法变得非常普遍,为了帮助处理一些行为标准参数传递方法,一些部分实现的行为被创建并处理代码端的标准任务,即使这些行为不是完全的代码支持的行为;也就是说这些部分实现的行为并不是HFSM的叶子节点,他们只是一种帮助行为,一般情况下这些帮助行为是抽象的,直到给予特定的数据参数配置其行为。

 

The most commonly used partially-implemented behavior was rangetest, which would accept a target parameter that it would track and store throughout its existence, using it to make a number of decisions.

Because parameters are passed as soon as a behavior is created, even before it is activated, we can use them to determine whether we should activate it. In the case of rangetest, extra settings were available to test the range of the passed target (the first parameter) and deactivate it if it left a second range.

最常使用的部分实现的帮助行为是‘范围测试’,它会接受一个作用对象参数并且在其生命周期内保存这些信息,使用这些信息来制定一系列的决策。因为参数是在行为一创建的时候就传递给的,即使在行为被激活之前我们仍可以使用这些帮助行为中的信息来决定是否应该激活这些帮助行为;在范围测试的例子中我们需要额外的设定来激活测试传递对象的范围,同时也可以通过其是否离开了第二个范围来阻塞该帮助行为

 

This functionality proved generally useful. Because the behavior can serve as the parent for both data-defined behaviors and code-supported behaviors, like pathfollow or melee, it is able to break tasks into responses based on properties of objects in the world and provide failcases implicitly when targets are too far away. By nesting rangetest behaviors and applying them to different objects at different times, we can define complex decisions about dynamic objects with just a few simple pieces.

这种特性被证实为是非常有效的,因为这样的帮助行为可以作为数据定义的,以及代码支持的行为的父行为(例如寻径和逃跑),他能够根据当前世界中对象的属性将任务分解为若干的响应,同时在对象距离过于远的时候提供行为失效;通过合理的安排‘范围测试’并且在不同的时候将这些信息作用于不同的对象,我们能够通过非常简单的几个行为对运行时的对象定义非常复杂的决策

 

Protect Behavior保护行为

The behavior protect illustrates this point: when it is activated, it's cued to protect as its first parameter. It then starts a list of prioritized behaviors, the first of which is to stay at all times within a reasonable distance of the character being protected, represented by approach. Approach is implemented as a rangetest behavior that activates when the target is too far away, calling into the movement system to run closer. (See Figure 3.)

所谓的行为保护阐述了这样一个特性:当它被激活的时候,它将保护其第一个参数,然后它会启动一系列优先排序的行为,首先是要全时间驻留在一定范围内使得角色得到保护,这样的行为也被称为接近,‘接近’行为被实现为‘范围测试’行为的繁华,这样当一个目标距离本体太远的时候,它将会唤醒移动系统接近目标 (见图3)

 

Second, a character in protect should engage any nearby enemies, which in our implementation are detected by a query to a target selector module running on the character (modules like these run separately from the behavior system). Combat is started in order to maintain this requirement (another rangetest behavior), and if an enemy is too close, it will activate and start children to engage the target.

If neither approach nor combat are able to start (because their preconditions are not satisfied), wander will activate by default, since it is the lowest priority behavior and has no preconditions.

The character will then patrol randomly around the actor being protected.

第二,收到保护的角色应该能够接近附近的敌人,在我们的实现中,这些游戏对象通过对目标选择器的查询获得(像这样的模块通常独立的运行于行为系统之外)为了维持这种需求,作战行为被启动(另一种范围测试的子行为),并且如果敌人太靠近,它将激活并且启动其子行为与目标对象相交接。如果‘接近’和‘作战’都不能启动(它们的前置条件都不能满足),那么‘巡逻’行为将被激活,因为他优先级最低并且没有前置条件,这样该角色就可以随机的在受保护对象附近进行巡逻

By creating behaviors that accept parameters at runtime, we are able to define a structure entirely in data to perform two very different tasks, while acting on multiple entities involved in those tasks-the person who should be protected and the enemies that pose a threat.

通过在接受运行时的参数来创建行为,我们可以完全依靠数据来定义行为结构从而进行截然不同的任务,例如作用于一个受保护的单位和一个收到威胁的单位

Sharing and Reusing Behaviors

共享和复用行为

A distinct advantage of defining a character's actions hierarchically is the ability to reuse, replace, and remove behaviors from the hierarchy easily and intuitively.

采用树状的集成体系结构来定义角色的行动带来的最显著的好处就是能够方便而直观的从树状体系中复用,替代,去除行为

 

Every behavior in this system (except for the simplest) has its settings defined in its .behavior settings file. However, when a behavior spawns its children, it does not start them using the filename directly; it uses an alias. Any character that starts behaviors will define a list of aliases, mapping each to a .behavior file. By abstracting behavior referencing by one layer, we are able to customize and reuse the behavior components by changing how that mapping is defined.

该系统中的每一个行为(除了最简单的行为)都有其对应的.behavior设置文件.然而当一个行为创建一个子行为,它不会直接的使用文件名来启动相应的行为,它会使用一个别名,任何启动行为的角色都会有一系列的行为别名,这些别名分别对应着不同的.behavior文件定义,通过增加这样的一层抽象层,我们就能够改变映射的定义通过定制和复用行为系统的组件

 

One of the down sides of using a flat FSM instead of an HFSM to drive your characters is the inability to quickly modify an existing behavior into a new one by changing only one aspect of it. To solve this in a FSM, you would need to recreate the entire state machine again, save the one difference.

使用平展的FSM体系而不是HFSM所带来的另一个缺点就是:他不能够在仅仅改动行为的一个方面的情况下迅速的重建这个行为。在FSM中如果你要解决这个问题,那么你不得不重新创建整个状态机来保存这个不同点。

 

We avoided this problem with our implementation by adding the ability to swap out behaviors at any layer in the hierarchy. By changing the mapping of a behaviors alias for a given character, you can swap out the actual behavior that's created when it references that alias, regardless of where the behavior sits in the hierarchy. This feature was commonly applied to give characters customizations on the behaviors that were widely shared, such as giving ninjas a special variant of melee or fireweapon. (See Figure 4.)

通过增加这样的一种功能:即换出行为树体系中的任意一层的能力,我们避免了这个问题.通过改变对应角色的映射行为别名,你可以换出当前实际的行为而不管该行为位于体系中的某一层,这个功能使得定制角色的行为的时候能够大量的共享行为,例如给予忍者一种特殊的‘逃跑’和‘交战’行为 (见图4)

Common combat behaviors map通用战斗行为映射
MapAlias("Combat", "pedestrian_combat.behavior")
MapAlias("Melee", "pedestrian_melee.behavior")
MapAlias("PathFollow", "pedestrian_pathfollow.behavior")
MapAlias("Patrol", "pedestrian_patrol.behavior")
MapAlias("Protect", "pedestrian_protect.behavior")
MapAlias("Approach", "pedestrian_approach.behavior")...

Ninja behaviors map忍者行为映射
INCLUDE("Common Combat Behaviors Map")
OverrideAlias("Melee", "ninja_melee_claw")
OverrideAlias("FireWeapon", "ninja_throw_shuriken")
OverrideAlias("Flee", NONE)
FIGURE 4 A common behaviour map, and a specialized one for ninjas, who have different melee and firing methods, and never flee, are listed.
图4 通用的行为映射,以及针对忍者的行为的泛化,它们有不同的逃跑和开火方法,因此没有列出

Aliases are typically defined in the file associated directly with the actor, but we gain some extra flexibility by allowing aliases to be redefined anywhere in the behavior tree as well. For example, consider the protect behavior described earlier. There are actually two variants of the approach behavior that are used as children within the HFSM, one to follow the character they are meant to protect and another for approaching enemies to engage in combat.

别名通常是在行为关联角色的时候被定义的,但是通过允许在行为继承树中重新定义这些别名我们获得了额外的灵活性。例如考虑前述的保护行为,HFSM中实际上有两种不同的‘接近’行为变种,一种是接近他们要保护的角色,另一种则是接近敌人以进入战斗。

 

Conceptually, these behaviors do the same thing (move the character to a target), but the way they do it is different. For example, the combat variant can strafe around and move in a more aggressive way, while the protect variant simply runs to the target's location of the character it is sent to protect.

We can allow this customization in separate branches with the override alias setting that any behavior can contain. When this setting is present in a behavior, it triggers any child behaviors that it or its descendants activate to instead use the new mapping. For example, we can override approach in the combat branch to use a more aggressive version, while the opposite branch separately overrides it to use a less aggressive version. Now, whenever any of the descendants activate that alias, it will filter up through each parent in the HFSM, checking in turn for a new alias mapping until it finds the ones we assigned.

概念上来讲这两种行为实际上做的是同一件事情(移动并接近目标),但是他们完成的方式是不同的。例如交战时的接近行为应该是迅猛的更具攻击性的接近,而保护的接近行为则是简单的跑到保护对象的附近,我们可以定制这些不同的泛化保护行为并为它们赋予相同的别名,这样当这套设定呈现在行为定义中的时候,这样他就可以激活任意的子行为状态而不是采用一个新的映射.例如,我们可以覆盖交战行为中的一般接近版本而采用更富攻击性的版本,而相反的分支上则采用平缓的移动版本.这样无论哪个后继子行为激活该状态,他会过滤他在HFSM中的每一个父行为,然后检查并寻找专业的一个别名,直到找到

 

Another simple method that was very successful in customizing behaviors was adding the ability to not just customize, but remove entire behaviors from beneath a parent. This was accomplished by mapping a behavior alias to a special "none" keyword, which when encountered would simply not start the behavior. This was very useful in producing variants of enemies that didn't throw grenades or didn't dodge, for example.

另一个非常有用的特性是能够从一个父行为节点下删除一整个行为,实现方法也很简单,只要将该行为映射到一个特殊的'空'行为节点,而该空行为一旦遇到只是简单的忽略而已,这对于创建那些不会进攻,不会逃跑的角色非常有用

AI for the Masses

In a game that features sandbox-style play, the AI needs to provide enough different and interesting characters to interact with in the world, and the size of the world doesn't have to get very big before it becomes unfeasible to hard code them all. Sometimes, even exposing behavior settings isn't enough-the structure of the tasks and subtasks must be exposed as well, in a way that's powerful but also simple to use.

在一个受限的开放游戏环境中进行游戏,AI角色应该能够呈现出不同的有趣的方式来和世界交互,游戏环境不需要很大,但是即使是这样有的时候,即使是这样的暴露使得行为设置仍然不能够完整架构出任务和子任务之间的结构,这样的架构某种意义上来说是强大而易用的。

 

In Destroy All Humans 2, the choices we made regarding AI architecture were intended to promote those traits. It's an adaptable, puzzle piece-like system in which functions are exposed in a generic way. It attempts to skirt the line between behaviors that are entirely hard coded and ones that are entirely script-defined, left to the technical designers to manage.

在毁灭人类2中,我们决定重新分类AI结构是为了突出这些特性,这是一种适用的,解谜式的系统,这样的系统下函数以更泛化的形式暴露,至于说如何决定脚本定义的行为和硬编码的行为之间俄准则,还要靠各自技术人员根据需要把握

 

Instead, a system like Pandemic Australia's packages that complexity and exposes it as individual pieces to be fit together at various levels of abstraction. As a result, we generate extra flexibility in the way those pieces can be reused and expanded, multiplying their usefulness and bringing us a step closer to populating a virtual world with virtual life.

相反的,想PANDEMIC AUSTRALIA的系统封装了复杂性并且暴露了各个层次的行为的抽象体系,结果我们采用了一种新的体系使得这些行为个体能够更好的被复用和繁华,这样就大大提高了这些行为的有用性,使得我们距离真实的虚拟世界又迈出了重要一步。

[EDITOR'S NOTE: This article was independently published by Gamasutra's editors, since it was deemed of value to the community. Its publishing has been made possible by Intel, as a platform and vendor-agnostic part of Intel's Visual Computing microsite.]

Resources附录

Alt, G. "The Suffering: A Game AI Case Study," in The Proceedings of the Nineteenth National Conference on Artificial Intelligence, July 2004.

Atkin, M. et al. "Hierarchical agent control: a framework for defining agent behavior," in The Proceedings of the Fifth International Conference on Autonomous Agents, May 2001. pp. 425-432.

Freed, M. "Managing Multiple Tasks in Complex, Dynamic Environments," in The Proceedings of the Fifteenth National Conferences on Artificial Intelligence, July 1998.

Fu, D. and Houlette-Stottler, R. "The Ultimate Guide to FSMs in Games," in AI Game Programming Wisdom 2. Hingham, Mass.: Charles River Media, 2003.

Isla, D. "Handling Complexity in the Halo 2 AI," in The Proceedings of the 2005 Game Developers Conference, San Francisco, March 2005.

Yiskis, E. "Finite-State Machine Scripting Language for Designers," in AI Game Programming Wisdom 2. Hingham, Mass.: Charles River Media, 2003.

人工智能时代的崛起:从数据驱动到智能涌现 近年来,深度学习、强化学习和 Transformer 结构的突破,使得 AI 在自然语言处理、计算机视觉、医疗、自动驾驶等领域展现出惊人的能力。例如,像 GPT-4、DeepSeek 和 Grok 这样的 AI 语言模型,能够根据庞大的语料库进行文本生成、代码编写、知识问答等任务。这篇文章将探讨人工智能从数据驱动到智能涌现的演变过程,分析当前 AI 模型的核心技术,并展望未来 AI 如何进一步发展,乃至可能迈向通用人工智能(AGI)。的现象,即 AI 具备了超越单一任务的泛化能力。 阅读详情

相关推荐

人工智能的未来:从弱 AI 到通用人工智能(AGI)

从最初的简单自动化程序,到如今的深度学习大模型(如 ChatGPT、DeepSeek、Grok),AI 逐步从弱人工智能(Weak AI)向更智能、更自主的方向发展。AI 的发展将影响就业市场,取代重复性、低技能的工作,同时创造新的高技能岗位。尽管深度学习带来了巨大的进步,但它仍然依赖大量标注数据进行训练,对新环境的泛化能力有限,这也是当前 AI 迈向 AGI 的关键障碍之一。本文将探讨 AI 从弱 AI 进化到 AGI 的可能性,分析目前 AI 技术的局限性,并展望未来 AI 在各个行业的影响。

qq_20245171的博客 1万+

Handling Complexity in the Halo 2 AI

原文:http://www.gamasutra.com/view/feature/130663/gdc_2005_proceeding_handling_.php Developers of game AI are always interested in cramming more complexity into the virtual brains they build. However

wolf96的专栏 1799

Skelerealms:Godot开放世界的数据驱动架构解析

开放世界游戏开发面临的核心挑战,本质是规模增长引发的内存爆炸、调度失控与系统耦合。传统RPG框架依赖节点遍历、全局状态轮询和场景硬加载,难以支撑百万格地形与数百实体的实时演化。Skelerealms提出‘数据即世界、意图即逻辑、分形即加载’三位一体范式,将世界状态统一托管于可版本控制的WorldState,用广播式IntentResolver替代轮询式AI,以意图密度驱动RegionLoader实现动态资源供给。该架构显著降低GC压力与CPU调度开销,支持无缝流式加载与联机状态一致性,为Godot开发者提供

weixin_30647423的博客 493

学霸带你了解开放世界游戏背后的创造与技术

然而,这种设计不仅要求游戏具有宏大的规模和多样的内容,还必须解决技术上的巨大挑战,以确保玩家在这个无尽的世界中能够获得连贯且令人满意的体验。例如,游戏中的副本和战斗区域由设计师精心打造,以提供特定的挑战和奖励,同时程序生成的区域则增加了游戏的随机性和重复可玩性。玩家通过探索世界中的秘密地点和完成挑战,可以解锁新的内容和背景故事,这种机制鼓励玩家全面探索游戏的每个角落,发现游戏中的深层次内容。随着人工智能和程序生成技术的进步,游戏中的环境和角色将能够实时响应玩家的行为,创造出更加生动和多变的体验。

纽雪澳诺加海美德的博客 4144

从创意到实现:GamePlay工作管线的全流程深度剖析

摘要: GamePlay工作管线是游戏开发中从创意到实现的核心流程,涵盖策划、原型开发、脚本实现、资源整合、测试优化等全环节。本文系统剖析了管线各阶段的关键任务:创意阶段需明确玩法目标;原型验证通过快速demo验证可行性;脚本开发将设计转化为可执行逻辑;资源整合确保视听体验与玩法同步;测试调优通过数据驱动打磨细节;跨部门协作依赖工具与规范保障效率。文章结合实例(如跳跃玩法开发、AI关卡生成等)揭示管线痛点和优化策略,强调迭代循环与数据监控对持续运营的重要性。高效GamePlay管线是游戏品质与开发节奏的支柱

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 2137

Aster:程序生成的开放世界游戏

紫ster 程序生成的开放世界游戏 依存关系 OpenTK Serilog Microsoft.Extensions.DependencyInjection ImGUI.NET

David Silver: 从人类数据驱动的AI向经验时代的转变

人类数据只是AI的垫脚石

ys707663989的博客 1187

Galavant:基于HTN的AI的开放世界动作冒险游戏

Galavant:基于HTN的AI的开放世界动作冒险游戏

人工智能与游戏:AI对游戏设计与体验的影响

1.背景介绍 人工智能(Artificial Intelligence, AI)和游戏(Games)是两个广泛的领域,但它们之间存在密切的联系。随着人工智能技术的不断发展,游戏设计和体验也逐渐受到了AI的影响。本文将探讨人工智能在游戏领域的应用,以及它们如何影响游戏设计和体验。 1.1 游戏的发展历程 游戏从古代的棋类游戏(如中国的象棋、印度的चौरासी等)开始,逐渐发展成为现代的数字游戏...

AI天才研究院 2522

MadSand:开放世界沙盒生存(RPG)游戏

狂沙 开放世界的沙盒roguelike 依存关系 libgdx commons-lang jackson-annotations jackson-core jackson-databind 屏幕截图

Survivor:一个用Python编写的自上而下的开放世界生存游戏

幸存者 一个用Python编写的自上而下的开放世界生存游戏。 mapgen基于 (一个用于生成地形的Python库)。 依赖关系是使用管理的。 要自动安装所有依赖项,只需使用pip-sync 。 要更新依赖关系,请运行pip-compile --output-file requirements.txt requirements.in 。 使用生成的文档。 控制项 行动 钥匙 移动 W A S D ,箭头键或数字键盘2 4 6 8 (按住Shift键可将其转到适当的位置) 相互作用 E , Z或数字键盘5 退出游戏 Esc键 静音 中号 切换调试覆盖 \ 学分 我自己创建了该项目中使用的大多数资产。 其余的我从以下来源获得: 音乐。 从下载的。 下载的声音

Unity高自由度游戏开发实战:数据驱动架构与动态世界构建

在游戏开发领域,数据驱动设计是一种将游戏逻辑与具体数据分离的架构思想,其核心原理是通过外部数据(如配置表、脚本化对象)来定义游戏行为,而非硬编码在程序逻辑中。这种模式的技术价值在于极大地提升了项目的可扩展性、可维护性以及内容迭代效率,尤其适用于需要管理海量交互与状态的角色扮演、开放世界等应用场景。通过将游戏实体、交互行为乃至叙事流程都转化为可配置的数据资产,开发者能够灵活地组合与修改游戏内容,从而高效构建出能动态响应玩家选择的虚拟世界。本文以Unity引擎为例,深入探讨如何融合ECS思想与Scriptabl

cunfuxiao7305的博客 364

Game AI with HFSM(PDF)

Game AI with HFSM(PDF) 游戏AI开发的技术文章,很不错的。

走进AI的世界:人工智能达到了什么程度?

人工智能(Artificial Intelligence)是计算机科学的分支,指通过算法和系统模拟人类智能,使机器具备‌感知环境、学习知识、逻辑推理、自主决策及持续进化‌的能力。其本质是通过数学建模与数据驱动,赋予机器‌类人认知能力‌的技术集合。能够通过分析环境信息,自主或在指导下完成目标导向行为的系统,其核心特征包括知识表示、模式识别、决策优化和自我改进。

Sweetie_Kiss的博客 1396

H5 获取手机GPS坐标

只要手机有GPS模块,可以用HTML5的Geolocation接口获取 在HTML5中,geolocation作为navigator的一个属性出现,它本身是一个对象,拥有三个方法: getCurrentPosition watchPosition clearWatch 1.简单 function getLocation(){ if(navigator.geolocation){ //判断是否有这个对象 navigator.geoloc

达拉崩巴斑得贝迪卜多比鲁翁_ 4669

【车辆动力学】专栏目录汇总

车辆动力学知识目录汇总

CrazyRabbit的博客 1714

人类认知逻辑能力和AI人工智能爆炸的思考

随着人工智能(AI)技术的飞速发展,我们正处在一个科技变革的时代。AI 不仅在多个领域取得了显著的成就,还在不断地挑战和拓展人类的认知边界。这引发了广泛的关注和讨论:AI 的发展将如何影响人类社会?它是否会超越人类的认知逻辑能力?本文将从多个角度探讨这些问题,深入分析人类认知逻辑能力与 AI 的关系,以及 AI 发展带来的机遇与挑战。

haixiang9999的博客 853

如何将rvt(BIM)转换为点云格式

1、为什么将BIM转换为点云格式? 如何使设计BIM与真实场景进行配准,分析在建、未建、已建构建的情况,真实场景是通过点云生产的,和点云配准需要相同的格式。 2、如何转换? 实用工具revit,转换过程如下图,这样就可以转换成三角网格形式。 3、FBX还需要进行一次转换,即转换成点云常用的类型,如bin\ply\pcd等格式。 需要软件cloudcompare.exe,软件下载地址百度云 链接:https://pan.baidu.com/s/1pflcKNc04loBnS1yKR39hw 提取码:obaf

self_Name_的博客 4491

从魂系游戏到开放世界:ARPG战斗系统的跨品类设计哲学

本文探讨了ARPG战斗系统从魂系游戏到开放世界的跨品类设计哲学,分析了硬核判定机制与自由探索的兼容性。通过对比Unity和UE4的技术实现,以及自研引擎的优势,揭示了现代游戏设计中战斗系统的模块化架构和AI重塑趋势。

grafana8visual的博客 248

python电子学会三级的零碎笔记

‌示例‌:如果s = ['a', 'b', 'c'],则' '.join(s)+'\n'的结果是'a b c\n',写入文件时所有元素会在一行内显示,每个元素之间用空格分隔,末尾有一个换行符。(2) '\n'.join(s)‌:如果s = ['a', 'b', 'c'],则'\n'.join(s)的结果是'a\nb\nc',写入文件时每个元素会占据文件的一行。(1) ' '.join(s)+'\n'‌:这种方式首先将列表s中的每个元素通过空格连接成一个字符串,然后在字符串末尾添加一个换行符\n。

xzal12的博客 691

DPARSF高级版 vs 基础版怎么选?没有T1数据也能做fMRI分析吗?

本文深度对比了DPARSF高级版与基础版在fMRI分析中的核心差异与适用场景,特别针对无T1数据的情况提供了实战解决方案。高级版依赖T1像实现高精度配准,适合需要精确解剖定位的研究;基础版则无需T1数据,适用于功能连接等相对空间要求不高的分析。文章还提供了版本选择决策树和常见问题解决方案,帮助研究者根据实际需求做出最优选择。

weixin_42526087的博客 132
上一篇: 【ZZ】GPU上并行处理大规模粒子系统
下一篇: FLEX WEB开发调试工具推荐 【CHARLES】
zinking3
博客等级 码龄20年 262粉丝 215原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值