沙盘引擎 (SEngine)

创意诞生沙盘世界,不止如此想象!

用户工具

站点工具


scripting:extend:character_ai

📚 差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
后一修订版
前一修订版
scripting:extend:character_ai [2023/11/30 21:18] bibiboxsscripting:extend:character_ai [2024/04/05 16:11] (当前版本) bibiboxs
行 4: 行 4:
 **角色作为游戏世界内的关键交互,AI功能(移动、跟随、寻路等)是必不可少的,在引擎中默认提供了几种方式使用。** **角色作为游戏世界内的关键交互,AI功能(移动、跟随、寻路等)是必不可少的,在引擎中默认提供了几种方式使用。**
  
-沙盘引擎默认**只提供AI操控功能**,不提供具体的AI逻辑实现,开发者应根据自身项目需求编写AI逻辑+沙盘引擎默认**只提供基础AI操控功能**,关于具体的世界内AI逻辑,开发者应根据自身项目需求编写。
  
  
行 14: 行 14:
 - `character.Group` 指定角色阵营(用于分辨敌我阵营) - `character.Group` 指定角色阵营(用于分辨敌我阵营)
 - `character.AIDistance` 指定逻辑检测距离 - `character.AIDistance` 指定逻辑检测距离
-- `character.AITarget` 读\写一个`Entity`类型的跟随对象(Character\Vehicle\Model) +- `character.AITarget` 读\写一个`Entity`类型的跟随对象(`Character\Vehicle\Model`) 
-- `character.AITargetPos` 读\写一个`Vector`类型的跟随坐标 +- `character.AITargetPos` 读\写一个`Vector`类型的跟随坐标(与`character.AITarget`二选一) 
-- `character.AIState` 指定一个AI状态(和平、被动、中立、主动) +- `character.AIState` **指定一个AI状态(和平、被动、中立、主动),这也是设定角色AI关键** 
-- `Distance()` 测量两个坐标距离 +- `character.AIForceMode`设置角色AI是为专注模式(即设定`Target`后不会被自动重置或改变,对象销毁除外)
-- `Rayline() 射线检测两个坐标能穿透+
 - …… - ……
  
行 25: 行 24:
 ## 编写逻辑示例 ## 编写逻辑示例
  
-实际开发过程中,大多数AI逻辑并非想象中那么复杂,更多只需要`计时器事件+循环检测逻辑`就可以实现多数需求。+《沙盘引擎》的AI开发过程中,AI部分逻辑我们将其进行了简化处理,大多数AI逻辑并非想象中那么复杂,通常只需要**【计时器事件+循环检测逻辑】**就可以实现多数相关需求。
  
-可以新建一个计时器,每1秒循环执行一次(根据需求自行调整间隔时间,时间间隔越小,理论上越灵敏),在计时器事件内编写循环遍历代码,根据需求+上方AI关键代码组合,就可以实现许多AI逻辑。+> 例新建一个计时器,每1秒循环执行一次(根据需求自行调整间隔时间,时间间隔越小,理论上越灵敏),在计时器事件内编写循环遍历代码,根据需求+上方AI关键代码组合,就可以实现许多AI逻辑。 
 +
 +> **注意:AI逻辑编写时需要相对严谨一些,提前预想到不同情况下的处理预判。**
  
 ```javascript ```javascript
-//示例代码仅供逻辑参考,不保证实时开箱即用性+//Test Code
 var npcs = []; var npcs = [];
  
 //Create NPCs //Create NPCs
-for(let i=0;i<50;i++)+function OnPlayerCompleteplayer )
 { {
-    let veh = Character.Create(0, player.Entity.Pos, player.Entity.Angle); +    let chara = Character.Create(0, Vector(81, 1, 28), 0); 
-    npcs.push(veh);+ player.SetEntity(chara); 
 +     
 +    for(let i=0;i<10;i++) 
 +    { 
 +        let veh = Character.Create(0, player.Entity.Pos, player.Entity.Angle); 
 +        npcs.push(veh); 
 +    }
 } }
 +    
 //Timer AIEvent //Timer AIEvent
 Timer.Create(() => { Timer.Create(() => {
行 49: 行 56:
             npc.AIState = 2; //血量正常,范围内有敌人会攻击             npc.AIState = 2; //血量正常,范围内有敌人会攻击
         }else{         }else{
-            npc.AIState = 1; //血量较低,改为被动,始终不会攻击+            npc.AIState = 1; //血量较低,改为逃离,始终不会攻击
         }         }
                  
行 57: 行 64:
         {         {
             let plr = Player.Find(j);             let plr = Player.Find(j);
-            if(plr.Entity != null && plr.Entity.Health > 0)+            if(plr.Entity != null && plr.Entity.IsSpawned)
             {             {
-                npc.AITargetPos = plr.Pos;+                npc.AITarget = plr.Entity;
                 break;                 break;
             }             }
行 70: 行 77:
  
 ## 玩家同步流限制 ## 玩家同步流限制
-> ==此部分内容可能过时的,目前仅供参考==+AI寻路逻辑一个性能昂贵操作所以在多数情况下需要基于**玩家+网络同步流(Stream)**概念
  
-沙盘引擎采用了【网络+单机】互相兼容的同步逻辑,所以无论在多数情况下仍然有**网络同步流(Stream)**的概念。 +> 网络同步流,可以理解为每个真实玩家(并非角色)的实时观察位置,许多网络同步\AI寻路相关的操作,只有在以此位置为中心的**规范距离内**才得以生效,否则视为**“离开此玩家的实际控制\同步范围”**,部分操作不予生效。
- +
-> 网络同步流,可以理解为每个玩家为中心点,实时更新有效的网络同步范围(比如32x32),只有在这个**合法距离内**部分操作才得以生效,否则视为“离开此玩家控制展示范围”,部分操作不予生效。+
 > >
-> 例如:在《我的世界》中也存在类似的概念,只有玩家在指定(默认10)范围内,附近的僵尸、作物、生物才会进行生长移动计算,超过此距离将不再进行同步。+*例如:在《我的世界》中也存在类似的概念,只有玩家在指定范围内,附近的僵尸、作物、生物才会进行生长移动和实时计算,超过此距离将不再进行同步。*
  
-考虑到此概念,开发者编写、使用AI系统时应该根据实际应用情况注意同步流范围的问题。 +实际AI操作过程中,比如部分大的城市地图,让`NPC-A`从城南寻路到城北,这期间可能有非常复杂的路程情况及干扰,这将被弹出警告并忽略寻路请求,因为这明显超出了**玩家流、CPU合理计算范围**,正确的做法应该是优先引用离玩家更近的NPC,**提前设置好`AIState`,利用此机等待玩家靠近自执行相关逻辑**。
- +
-比如有一个特大的城市地图,让`NPC-A`从城南寻路到城北,这将被弹出警告并忽略,因为这明显超出了玩家流、CPU合理计算范围,正确的做法应该是优先引用离玩家更近的NPC,或者使用强制位移同步参数(详情见`character.MoveTo()`方法解释)。 +
- +
-> 强位移:实际上是将Character强制移到能够AI寻路范围的**最边缘位置**,然后开始正常寻路移动+
  
  
行 88: 行 89:
 ## AI逻辑关系 ## AI逻辑关系
  
-沙盘引擎为AI逻辑提供了一些通用的控制代码,无论是简单还是复杂的AI整体逻辑,都应该通过这些基础AI代码来实现。+沙盘引擎为AI逻辑提供了一些通用的代码,**无论是简单复杂的AI整体逻辑,都应该通过这些基础代码来实现**
  
 AI代码根据情况不同,应该使用不同的API进行调用,且不同代码执行后可能会有一些关系影响,下方将做一些示例规范及解释。 AI代码根据情况不同,应该使用不同的API进行调用,且不同代码执行后可能会有一些关系影响,下方将做一些示例规范及解释。
行 98: 行 99:
 如果`AITarget`功能不能满足需求,或者有针对自定义坐标的AI需求,可以使用`AITargetPos`进行针对坐标的AI指令。 如果`AITarget`功能不能满足需求,或者有针对自定义坐标的AI需求,可以使用`AITargetPos`进行针对坐标的AI指令。
  
-> 值得注意的是,无论是`AITarget`还是`AITargetPos`方法,两者在根本上都属于【设定寻路目标】的功能作用,真正起到AI行为逻辑的是`AIState`属性。+> 值得注意的是,无论是`AITarget`还是`AITargetPos`方法,两者在根本上都属于【设定寻路目标】的功能作用,**真正起到AI行为逻辑的是`AIState`属性**
 > >
-> 无论使用以上哪个方法(实体或Vector),AI逻辑上都认定它们是一个【目标】,例如`AIState==1`、`AITargetPos`设置坐标的情况下,NPC会尝试逃离反向逃离这个目标(坐标点)。+> 无论使用以上种方法*(实体或Vector)*,AI逻辑上都认定它们是一个【目标】,例如`AIState==1`、`AITargetPos`设置坐标的情况下,NPC会尝试逃离反向逃离这个目标位置(坐标点)。
  
 ### AIState状态机制 ### AIState状态机制
  
-除了使用`AITarget\AIMove`等方式移动外,`AIState`是十分关键的**AI逻辑行为**代码,这将直接控制当前Character的**“性格和想法”**。+除了正常使用`AITarget\AIMove`等方式指定目标外,`AIState`是十分关键的**AI逻辑行为**代码,这将直接控制`Character`的**“性格和想法”**。
  
-此状态机制会和`AIDistance`共同搭配使用,在不同状态\行为下的数值可能要动态调整。+**此状态机制会和`AIDistance`搭配使用,在不同状态\行为下的数值可能开发者动态调整。**
  
-| ID   | 行为                         | 机制                                                         | +**==特别注意:每当目标死亡\离开范围角色停止跟随并重置`AITarget`(除非强制模式`AIForceMode`)。==**
-| ---- | ---------------------------- | ------------------------------------------------------------ | +
-| -1   | 静态                         | 无任何行为,不会进行任何寻路<br />如有`AITarget(&Pos)`,并且在**【手持物品】可攻击范围内,将在原地尝试向目标攻击** | +
-| 0    | **和平(默认)(忽略Team)** | 无任何行为,默认正常寻路移动,不会主动攻击或逃脱<br />如有`AITarget(&Pos)`则正常进行跟随,直到两者距离<=`AIDistance`(保持距离) | +
-| 1    | 被动(忽略Team)             | 默认正常寻路移动,不会主动攻击,在无`AITarget(&Pos)`时不会主动逃脱<br />如果任何敌对`Team`实体攻击了自身,将自动切换`AITarget=Enemy`<br />如有`AITarget(&Pos)`则将尝试**反向远离**目标,直到两者距>=`AIDistance` | +
-| 2    | 中立                         | 默认正常寻路移动,如果任何敌对实体攻击了自身,将自动切换为`AIState=3`且`AITarget=Enemy`(因此始执行“主动”行为)<br />其他情况下,不会主动攻击或逃脱 | +
-| 3    | 主动(敌对)                 | 如果`AITarget`不为空,将主动跟随`AITarget`并在`AIDistance`范围时攻击<br />反之,则默认正常寻路移动,即时空闲状态时,也会自动攻击任何在`AIDistance`范围内的实体<br />**注意:此状态下杀死目标后==不会==自动重置到中立等其他状态。** |+
  
-**注意:以上有关==静态(攻击)、中立、主动】==状态下均遵循`对方.Team != 自身.Team`前提条件如果两者`Team`则会忽略为是友军),==将不会进行触发和主动攻击==**+| ID   | 状态             | 机制                                                         | AIDistance                               | Group影响 | 
 +| ---- | ---------------- | ------------------------------------------------------------ | ---------------------------------------- | --------- | 
 +| -1   | 静态             | 无任何移动行为,不会进行任何寻路<br />如果存在`AITarget(&Pos)`并且在**【手持物品】可攻击范围内,将在原地尝试面向目标攻击** | 距离内执行                               | 同组忽略 
 +| 0    | **和平默认)** | 无其他行为,默认**正常寻路(跟随)移动**,不会主动攻击或逃脱(即使被攻击) | 距离内跟随                               | 无        | 
 +| 1    | 逃离             | 默认站在原地,不会主动攻击如果存在`AITarget(&Pos)`则主动反向逃离目标,否则将会反向逃离所有**非同组**的附近象<br />==(如果任何敌对`Group`实体攻击了自身,将自动切换`AITarget=Enemy`)== | 逃离至距离外<br />*检测附近逃离目标范围* | 忽略  | 
 +| 2    | 中立             | 默正常寻路移动(或站在原地),如果任何敌对`Group`实体攻击了自身,将自动切换`AIState`且`AITarget=Enemy`**(因此开始执行“主动”行为)**<br />==具体被攻击后切换的逻辑,由`AINeutral`决定反击或逃离== | 无                                       | 无        | 
 +| 3    | 敌对             | 如果`AITarget`为空,将主动跟随`AITarget`并在`AIDistance`范围时攻击<br />反之,则默认正常寻路移动,即时空闲状态时,也会自动攻击任何在`AIDistance`范围内的实体<br />==(如果中途任何敌对`Group`实体攻击了自身,将自动切换`AITarget=Enemy`)== | 距离内追击<br />*检测附近敌对目标范围  | 同组忽略  |
  
-> 如果确实有关于中立】情况下Team相也触发攻击的需求,可以在合适的地方提前更换`character.Team`,然后再默认触发AI逻辑) +**注意:以上AI状态均遵循【同组==Group影响==】机制(`self.Group != target.Group`如果两者`Group`相同则会忽略(为是友军),==将不会触发行为,并自动清除`AITarget`==**
->+
  
- +**因此,如果希望实某些NPC跟随并攻击指定`Character`,一定要将两方的`character.Group`设定为不同的值,它们才会变成“非友军”。**
- +
-### AIDistance距离机制 +
- +
-在使用AI功能进行对象跟随时,`AIDistance`将在不同状态时起到不同作用。 +
- +
-**==特别注意:由于`AIDistance`的设计机制,如果角色需要进行小范围移动时,可能会出“没有移动”的情况,这很可能是因为`AIDistance`(最小距离)设置过高,导致没有执行本次移动。==** +
- +
-`AIDistance`数值在不同`AIState`下**代表不同的限制意义**+
 > >
-`AIDistance`默认值:`10.0`。 +如果确实于【中立情况下Group相同也触发攻击的需求可以合适的方提前更换`character.Group`,然后再默认触发AI逻辑)。
- +
-| AIState状态 | 机制作用                                                     | +
-| ----------- | ------------------------------------------------------------ | +
-| -1(静态)  | 静态模式,没作用<br />**主动攻击距离取决手持物品的攻击距离(而不是`AIDistance`),当在物品攻击范围内则自动攻击** | +
-| 0(和平)   | 当目标距离<=`AIDistance`时,角色将始终保持安全距离,暂停跟随 | +
-| 1(被动)   | 当两者距离<`AIDistance * ai_character_escapedistance[*GameRule] ` 时,角色将始终保持安全距离,反向逃离<br />此处`ai_character_escapedistance`是一个游戏规则设定详情参考[游戏规则文档](reference/instances)。 | +
-| 2(中立)   | 当两者距离<=`AIDistance`时,角色将始终保持安全距离,暂停跟随 | +
-| 3(主动)   | 当两者距离<=`AIDistance`时,角色将视为允许追击距离,主动追击<br />超过追击距离时则站立(暂停跟随),**主动攻击距离取决于手持物品的攻击距离(而不是`AIDistance`当在【物品攻击范围】内则自动攻击** | +
- +
-**特别注意:引擎默认只提供相对基础可扩展的方式,类似`AITarget(&Pos)`绑定后不会自动解绑(除非调用重置或`Target`对象销毁,开发者要根据项目自行管理`AITarget`周期,避免意料之外的情况**+
  
  
行 151: 行 133:
 `AITargetPos`优先权更高(在值不为`null`时),对于更高级的自定义需求,以及只想让NPC前往某个坐标,那么可以使用`AITargetPos`属性来实现**向坐标移动**。 `AITargetPos`优先权更高(在值不为`null`时),对于更高级的自定义需求,以及只想让NPC前往某个坐标,那么可以使用`AITargetPos`属性来实现**向坐标移动**。
  
-**两种方式搭配`AIDistance+AIState`均可以实现追击\逃跑\中立等功能。**+**两种方式均可搭配`AIDistance+AIState`以实现追击\逃跑\中立等功能,通常更推荐`AITarget`的方式。**
  
  
行 161: 行 143:
 | AIMoveState状态 | 说明                                                         | | AIMoveState状态 | 说明                                                         |
 | --------------- | ------------------------------------------------------------ | | --------------- | ------------------------------------------------------------ |
-| 0(自动)       | 根据距离情况自动选择,当距离目标超过`ai_character_movestate_autodistance(GameRule)`时,将会变为奔跑状态<br />由于`AIState=1`被动的反向逃离特殊性,被动状态下将永远奔跑,除非手动设置`AIMoveState=1` |+| 0(自动)       | 根据距离情况自动选择,当距离目标超过**一定距离**`ai_character_movestate_autodistance(GameRule)`时,将会变为奔跑状态<br />由于`AIState=1`被动的反向逃离特殊性,被动状态下将永远奔跑,除非手动设置`AIMoveState=1` |
 | 1(行走)       | 永远使用行走状态,无论距离多远                               | | 1(行走)       | 永远使用行走状态,无论距离多远                               |
 | 2(奔跑)       | 永远使用奔跑状态,无论距离多远                               | | 2(奔跑)       | 永远使用奔跑状态,无论距离多远                               |
行 171: 行 153:
 由于各类游戏玩法的需求不同,沙盘引擎默认只提供基础的AI操控逻辑代码。 由于各类游戏玩法的需求不同,沙盘引擎默认只提供基础的AI操控逻辑代码。
  
-实际上编写一个生动且智能化的AI并非很容易的事情,尽管【计时器循环】的入口事件起点很简单,但具体怎样安排循环周期的代码?这个需要根据项目玩法提前设计完善。+编写一个生动且智能化的AI并非很容易的事情,尽管【计时器循环】的入口事件起点很简单,但具体怎样安排循环周期的代码?这个需要根据项目玩法提前设计完善。
  
 +*注:一个相对复杂的AI控制代码块,成百上千行的控制代码是正常的。*
  
  
scripting/extend/character_ai.1701350309.txt.gz · 最后更改: 2023/11/30 21:18 由 bibiboxs