zoukankan      html  css  js  c++  java
  • AI概念分析

    设计的本质是抽象变化。

    关于Composites的用法又有了新的认识:在Task返回值的时候尽量要与真实情况相符合,就像Selector下的子节点一旦成功Selector就返回,说明Selector是一种选择的方式,而Sequence下的子节点一旦失败就返回,说明它就是用来一步一步执行的。所以在选择使用的时候尽量按照规矩来,减少强制性的返回结果,这样显得更和谐,别人读程序也更好懂。

     

    上面是整个AI系统中的工具。

     

    Pawn Action

    也是要在AIController中运行的,有两个特点,Action Tree是动态创建的,2是执行结束后就被释放了。

    用处:将一些行为封装成起来可以供很多不同的目标使用。

    使用方法:创建一个基于PawnAction_BlueprientBase的类,在其中有5个事件驱动,常用的就是EventActionStart/Tick/Finished,如何判定是要执行Finish呢,有一个节点使用:Finish,并且还可以返回Result。那现在类是有了,将一些AI事件放在这里写,如何去实现呢,这个类只能在有特定的Compontent的下执行,是ActionsComp,这个组件存在于AIController中,所以类的实现在其中写,首先要创建一个Action,用节点CreatActionInstance,创建出来只是将其放在栈中,还需要将其从栈中调出,至于何时调出根据需求,调出有两个节点可以使用,PushAction和PerformAction。当然最后要将AICON帮到目标身上才能触发。

    当然,还有abortAction打断节点。

     

    SaveGame

    将游戏记录存下来应该是在游戏进行的最高逻辑中写,GameInstance。

    GameInstance中有一个Init初始化事件,这是最适合写存档的地方。

    创建一个基于SaveGame的类,这个类的主要作用是存储数据。所以不需要写任何逻辑,只需要将需要存储的变量添加上就Ok。等待别的地方对变量赋值。

    接下来在GameInstance中写逻辑,复写一个Event Init的函数,链接LoadGameformSlot节点,意思是从Slot中载入游戏,Solt中放有什么呢,我们要把游戏的档案放在Slot中,这样就会一开始的时候从Slot中调用档案了,节点的返回值就是游戏的档案,这里的游戏档案就是SaveGame的类,这里做一个类型转换,如果第一次进入游戏,这是还没有存过档,那么一定会转换失败,失败之后就要创建一个档案了,CreatSaveGameObject,创建一个存储游戏的对象,并将其付给刚创建的类的引用,使其实例化。如果之前想打开之前有过的存档,那么就会转化成功,成功之后将打开的游戏档案再付给引用,将其实例化。这是进入和创建游戏档案的逻辑。

     

    下面要写的是如何将数据存在游戏档案中,更新数据一定要对对象更新,不能对引用更新,所以在Instance中的引用是被实例化了的,故可以对其更新数据,进行数据赋值,赋值形式根据需求自定,这里我只做了一个很简单的赋值。

     

    或许很疑惑这里为什么还有一个Instance中的函数,理论上说我们已经完成了将数据存入档案,一开始调用档案的事情了。但是别忘了,调用档案,是从Slot中调用的,所以我们还必须要将档案在存储进Slot中的,否则调用的还是上一次放在Slot中的档案。那既然是要把改变好的档案放在Slot中,那还是要在Instance中放的,因为只有Instance中有被实例化的档案引用。但是存储的驱动有不能再Instance中,故写成函数,由其他地方调用。这样才完成了游戏存档。

    梳理一下思路,基于SaveGame的类就是一本游戏档案,其中只有变量。类是创建好了,那么下面要创建出对象,CreatSaveGameObject,那这个创建的逻辑要在Instance中写了,并将创建好的提升为变量,供其它使用。UE的机制是不能直接打开存档,而是要从Slot中打开档案,要想打开档案就要用LoadGameformSlot,要是第一次开游戏的话需要创建,第二次就直接打开已有的存档就OK了,即使是打开了,也需要将打开的存档提升为变量,以备更新信息时用。故有了Instance中的逻辑。那么既然要从Slot中打开游戏档案,那么我们在将数据存档的时候就要将档案放在Slot中,那么最后就是更新数据了,这里很简单的信息交互就不说了。

     

    Sensing

    Register登记,注册    perception感知    stimuli刺激

    这里存在两个感知系统,其中AIPerception是老的感知系统,也是比较完善的,虽然会被淘汰,但那时还是需要了解的,新的系统是PawnSensing。先说AIPerpection.

    AIPerception

    首先在AIController中添加一个AIPerception,并在Detail面板中找到AIPerception对其进行编辑,Configuration布局,结构。Dominant主要的,显性的。

    添加一个elements,例如添加一个Hearing,对Sense面板进行修改达到自己要的效果,Implementation工具,Affiliation加入,入会,联系Detevtion by Affiliation探测的目标——敌人,中立,朋友。MaxAge听完之后多久忘掉,还有一个LoSHearingRange多远听不到了

    如果是视觉的话还有一个视觉角度。

    设置好之后会发现在Variables中的Components有一个AIPerception,在Detail面板中有事件可以进行编辑,

     

    一般用到前两个,当感知更新时执行事件,那这个检测的任务就交给了引擎,较于之前的方法,我们就不需要进行监测了,那执行的事件很明了就是要更新黑板上的数据。这里的两个驱动有不同的地方,就是没有Target的驱动是可以对多个AI,后者只是针对一个。

    事件执行后,我们仍要进行判定,判断是一旦受到刺激就执行事件,还是守到某种特定的刺激执行特定的事件。这里用到节点GetSenseClassForStimulus(获得产生刺激的感知类)之后跟判定ClassIsChildOf。

     

    Array的遍历主要是想获得Srimulus(刺激)进行判定。先是获得元素的Perception,接着将其Break获得Stimulus数组,再进行遍历,将元素Break进行判定。

     

    第二种就是对其单个感知的改变进行判定,获得发生刺激的感知类,之后判断是不是继承自需要的感知类。

    如此结束了么,这里有这么个问题就是这个感知系统的弊端,AIPerception负责接收刺激,还必须有人发出刺激,这就是AIPerceptionStimuliSource组件的作用。在目标中添加此组件,在Detail面板中的AIPercetion勾选Auto Register as Source才可以产生将刺激发出的作用,并在Register as Source for Senses中添加需要发出的刺激。还有一点需要注意,对于听觉而言,动画中的声音对于场景中的Actor是听不到的,所以即使发出了听觉刺激还是没有声音的,这里就要让场景中的Actor也可以拥有一个声音的刺激。利用节点MakeNoise,和PawnMakeNoise。两者有一点不同,NoiseMaker(声音制造者)NoiseInstigator(声音煽动者)。

    制作一个声音刺激,什么时候发出呢,当然是要跟动画声音的产生同步的,在动画中创建一个Notify。如此才算完成。

     

    Pwan Sensing

    在前面阐述过。

  • 相关阅读:
    HDU 1813 Escape from Tetris
    BZOJ 2276 Temperature
    BZOJ 4499 线性函数
    BZOJ 3131 淘金
    HDU 5738 Eureka
    POJ 2409 Let it Bead
    POJ 1286 Necklace of Beads
    POJ 1696 Space Ant
    Fox And Jumping
    Recover the String
  • 原文地址:https://www.cnblogs.com/wbx-Blog/p/7147633.html
Copyright © 2011-2022 走看看