人工智能游戏编程真言学习笔记之 通用触发器系统

来源:互联网 发布:网络诽谤报警流程 编辑:程序博客网 时间:2024/05/21 10:01
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();
};
人工智能游戏编程真言学习笔记之 <wbr>通用触发器系统


4. 智能体的层次分组
可以通过智能体的分组来提高触发器系统过滤的效率。
原本TriggerSystem.Update()是遍历所有的智能体,把每一个智能体和所有当前注册中的触发器进行比较过滤,来执行该智能体对某触发器的处理函数。
如果把智能体分组的话,比如把智能体按地域分组,那么TriggerSystem.Update()遍历所有的智能体智能体组,把每一个智能体组和所有当前注册中的触发器进行比较,那么就可以排除一些距离很远的组。

5. 触发所有可能性
人工智能游戏编程真言学习笔记之 <wbr>通用触发器系统