1. 触发器和消息的区别
触发器和消息类似,目的是为了避免轮询,区别在于:
(1)消息有明确的源对象和目的对象。触发器只有源对象,目的对象是随着场景状况的不同而不同的。比如:
消息 游戏对象A发消息给游戏对象B,要求B做出某种行为(中间可能经过消息路由器)。
触发器 游戏每一帧 会调用TriggerSystem.Update(),其内部会遍历所有已注册的触发器,并调用当前所有对该触发器感兴趣的游戏对象的处理函数Handle()。
(2)生命周期不同,触发器具有持久性。比如:
消息 一个消息发出后(不管是普通消息还是延迟消息),如果该消息被目的对象处理了,则该消息被小号。
触发器 一个触发器被注册后,只要该触发器没有过期,则它一直会有机会被感兴趣的对象处理。
(由于触发器可以长时间存在,因此有些原本需要频繁发消息才能达到的功能,可以用触发器完成。比如:“敌方NPC-A在某半径范围内只要看到玩家B就会跟踪玩家B”这个功能,给玩家B注册一个触发器并设置半径范围。每帧TriggerSystem.Update()里会判断该触发器和其他所有对象的距离,如果该触发器和A的距离满足触发器半径范围,那么该触发器对A来说就是一个感兴趣的触发器,A就会处理这个触发器。如果下一帧还是感兴趣的,那么还会处理)
(3)普通消息一经发出,立马会在该轮堆栈中被直接处理掉。而触发器则是注册后,必须等到TriggerSystem.Update()里被感兴趣的对象处理。
2. 触发器的定义
struct TriggerRecordStruct
{
EnumTriggerType
eTriggerType;//触发器类型,游戏对象对不同的触发器处理方式不同
unsigned long
nTriggerID;// Registration ID assigned by the TriggerSystem.
unsigned long
idSource;// ID of source gameobject of trigger.
Vector
vPos;// Position in world of trigger.(eg:gameobject's position)
float
fRadius;// Distance from source that trigger affects.
unsigned long
nTimeStamp;// When trigger occured.
unsigned long
nExpirationTime;// When trigger expires.
bool
bDynamicSourcePos;// Lookup position of trigger source every update.
}
注1:idSource 是创建了这个触发器消息的游戏对象的ID,这个源可以是开了枪的游戏角色,或者是爆炸了的一颗地雷。响应触发器消息的智能体必须知道究竟是谁产生了这个消息,从而可以开枪还击或快速逃离爆炸地点。每一个触发器消息子啊游戏世界中都有其位置和范围半径,它只会影响到其范围半径之内的智能体。大多数的触发器消息是静态的,但是有些确是持续移动的。如果bDynamicSourcePos为真,则表明这个触发器消息是移动的,每一个时间周期都必须刷新它的位置。
注2:触发器消息只生存一段特定的时间片段,如果生存时间为0,那么意味着这个触发器消息永远存在。例如:如果智能体到达某处会拉动一个控制杆,那么控制杆就可以注册一个永不过期的触发器消息,直到他被拉动时,这个触发器消息才被删除。(如果不使用触发器,那么智能体无论何时都必须每帧检测是否位于控制杆的Region内,这无疑增加了智能体逻辑的复杂性。)
3. 触发器系统
class CTriggerSystem
{
unsigned long
RegisterTrigger(EnumTriggerType _eTriggerType, unsigned long _nPriority,
unsigned long _idSource, const Vector& _vPos, float _fRadius,
float _fDuration, bool _bDynamicSourcePos);//按优先级排序
void
RemoveTrigger(unsigned long nTriggerID);
void
Update();
};
4. 智能体的层次分组
可以通过智能体的分组来提高触发器系统过滤的效率。
原本TriggerSystem.Update()是遍历所有的智能体,把每一个智能体和所有当前注册中的触发器进行比较过滤,来执行该智能体对某触发器的处理函数。
如果把智能体分组的话,比如把智能体按地域分组,那么TriggerSystem.Update()遍历所有的智能体智能体组,把每一个智能体组和所有当前注册中的触发器进行比较,那么就可以排除一些距离很远的组。
5. 触发所有可能性
触发器和消息类似,目的是为了避免轮询,区别在于:
(1)消息有明确的源对象和目的对象。触发器只有源对象,目的对象是随着场景状况的不同而不同的。比如:
消息 游戏对象A发消息给游戏对象B,要求B做出某种行为(中间可能经过消息路由器)。
触发器 游戏每一帧 会调用TriggerSystem.Update(),其内部会遍历所有已注册的触发器,并调用当前所有对该触发器感兴趣的游戏对象的处理函数Handle()。
(2)生命周期不同,触发器具有持久性。比如:
消息 一个消息发出后(不管是普通消息还是延迟消息),如果该消息被目的对象处理了,则该消息被小号。
触发器 一个触发器被注册后,只要该触发器没有过期,则它一直会有机会被感兴趣的对象处理。
(由于触发器可以长时间存在,因此有些原本需要频繁发消息才能达到的功能,可以用触发器完成。比如:“敌方NPC-A在某半径范围内只要看到玩家B就会跟踪玩家B”这个功能,给玩家B注册一个触发器并设置半径范围。每帧TriggerSystem.Update()里会判断该触发器和其他所有对象的距离,如果该触发器和A的距离满足触发器半径范围,那么该触发器对A来说就是一个感兴趣的触发器,A就会处理这个触发器。如果下一帧还是感兴趣的,那么还会处理)
(3)普通消息一经发出,立马会在该轮堆栈中被直接处理掉。而触发器则是注册后,必须等到TriggerSystem.Update()里被感兴趣的对象处理。
2. 触发器的定义
struct TriggerRecordStruct
{
}
注1:idSource 是创建了这个触发器消息的游戏对象的ID,这个源可以是开了枪的游戏角色,或者是爆炸了的一颗地雷。响应触发器消息的智能体必须知道究竟是谁产生了这个消息,从而可以开枪还击或快速逃离爆炸地点。每一个触发器消息子啊游戏世界中都有其位置和范围半径,它只会影响到其范围半径之内的智能体。大多数的触发器消息是静态的,但是有些确是持续移动的。如果bDynamicSourcePos为真,则表明这个触发器消息是移动的,每一个时间周期都必须刷新它的位置。
注2:触发器消息只生存一段特定的时间片段,如果生存时间为0,那么意味着这个触发器消息永远存在。例如:如果智能体到达某处会拉动一个控制杆,那么控制杆就可以注册一个永不过期的触发器消息,直到他被拉动时,这个触发器消息才被删除。(如果不使用触发器,那么智能体无论何时都必须每帧检测是否位于控制杆的Region内,这无疑增加了智能体逻辑的复杂性。)
3. 触发器系统
class CTriggerSystem
{
};
4. 智能体的层次分组
可以通过智能体的分组来提高触发器系统过滤的效率。
原本TriggerSystem.Update()是遍历所有的智能体,把每一个智能体和所有当前注册中的触发器进行比较过滤,来执行该智能体对某触发器的处理函数。
如果把智能体分组的话,比如把智能体按地域分组,那么TriggerSystem.Update()遍历所有的智能体智能体组,把每一个智能体组和所有当前注册中的触发器进行比较,那么就可以排除一些距离很远的组。
5. 触发所有可能性
![人工智能游戏编程真言学习笔记之 <wbr>通用触发器系统 人工智能游戏编程真言学习笔记之 <wbr>通用触发器系统](https://i-blog.csdnimg.cn/blog_migrate/6a8e54182a217aecd53054a7a0098d6f.jpeg)