• ai 对抗


    使用Javascript和HTML5,观看AI建立自己的军队并相互战斗!飞机,坦克,基地和医务人员每次都进行一场有趣的战斗。部队将撤退并得到修理,喷气机混战,猛oth的坦克统治地面。

     https://github.com/blitzxion/Tanks.js

    https://github.com/ZeroChiLi/TanksPluggableAI

    Unity 有限状态机(Finite State Machine)的理解 与 实现简单的可插拔(Pluggable)AI脚本对象。

    #Unity 有限状态机(Finite State Machine)的理解 与 实现简单的可插拔AI脚本对象。

    参考官方教程:Pluggable AI With Scriptable Objects
    Github完整项目:TanksPluggableAI
    大神Blog:【游戏设计模式】之三 状态模式、有限状态机 & Unity版本实现

      一般的游戏AI都是使用状态机的设计模式来实现的。发现官方有教程,就跟了一遍,这里就总结一下。
      先简单说一下状态模式。就是根据当前状态和对应条件,选则需要转换的下一个状态。例如本文的例子,坦克默认状态是巡逻(状态),在发现有敌人时(条件),转换成追杀(状态),在敌人逃脱或死掉了之后(条件),又变成巡逻(状态)。

      游戏场景:绿色标签为巡逻点。蓝色标签为玩家出生点。红色为AI出生点。(如图玩家被两个AI追杀。)


    AI对象结构
      每个AI对象都有一个状态控制器(StateController)脚本组件,包含一个当前状态(State),且状态包含需要执行动作(Action),还有状态转换的条件(Transition)。


      Unity中文件分类层级如下。其中DefaultEnemyStats是默认AI的一些配置。包括攻击距离,移动速度,旋转速度等等。


    State (状态)
    using UnityEngine;

    [CreateAssetMenu (menuName = "PluggableAI/State")]
    public class State : ScriptableObject
    {
    public Action[] actions; //动作
    public Transition[] transitions; //通过决定,选择下一种动作决定
    public Color sceneGizmoColor = Color.gray; //拿来渲染eyes的Gizmos颜色

    //每一帧更新状态,在StateController的OnUpdate中调用。
    public void UpdateState(StateController controller)
    {
    DoActions(controller); //执行动作
    CheckTransition(controller); //检测转换状态
    }

    //顺序执行动作列表的动作。
    private void DoActions(StateController controller)
    {
    for (int i = 0; i < actions.Length; i++)
    actions[i].Act(controller);
    }

    //检查所有转换状态,并改变状态。
    private void CheckTransition(StateController controller)
    {
    for (int i = 0; i < transitions.Length; i++)
    {
    //这里条件转换只有两个,所以直接用Bool类型来判断。当然也可以有多种条件转换。
    bool decisionSucceeded = transitions[i].decision.Decide(controller);

    if (decisionSucceeded)
    controller.TransitionToState(transitions[i].trueState);
    else
    controller.TransitionToState(transitions[i].falseState);
    }
    }

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    状态名 说明 配置
    Remain State 保持原来状态。不包含任何属性。 略。
    PatrolChaser 巡逻者状态。在巡逻点之间巡逻,如果检测到敌人,转为追杀状态。
    ChaseChaser 追杀者状态。导航到目标一定距离并持续攻击,直到目标死掉,转回巡逻者模式。
    PatrolScanner 同Patrol Chaser。巡逻到敌人,转为追杀。
    ChaseChaser 同Chase Chaser 。追杀敌人,但到目标死掉,转换成警觉模式。
    AlertScanner 警觉模式。其实就是旋转扫描敌人,直到扫描到目标或超过了一定时间。
      通过上表其实可以发现有两个非常相似的动作,只是为了演示Alert Scanner 的。其实是可以优化的,就是修改Transition的结构,不再是只有两种状态选择,而是多种,这样就可以更好的重用状态。

    Action(动作)
    using UnityEngine;

    public abstract class Action : ScriptableObject
    {
    //State直接调用这个方法来执行动作。
    public abstract void Act(StateController controller);
    }
    1
    2
    3
    4
    5
    6
    7
    动作名 说明 原理
    PatrolAction 巡逻动作。从StateController搞来巡逻点列表。在这些巡逻点之间巡逻移动。 设置巡逻点为导航目标点,到达后设置下一个巡逻点为导航点。
    ChaseAction 追随动作。最短距离到达目标。 设置目标为导航目标点,导航过去就是了。
    AttackAction 攻击动作。攻击目标。 射出检测射线(红色的),检测到目标就发炮攻击。
    Decision(决定)
    using UnityEngine;

    public abstract class Decision : ScriptableObject
    {
    //通过这个方法的返回值来判断决定的选择。
    public abstract bool Decide(StateController controller);
    }
    1
    2
    3
    4
    5
    6
    7
    决定名 说明 原理
    LookDecision 检测决定。检测到目标就设置为追踪目标,并且返回True。 射出检测球体射线(绿色的)来检测。
    ActiveStateDecision 活动状态决定。就是判断追踪的目标是否active(激活状态)。 直接返回追踪目标的active的bool值。
    ScanDecision 扫描决定。说是扫描其实并没有扫描,只是在转圈而已。一直转到外部条件改变状态,或者超过了扫描限定的时间。 停止导航。配合Time.deltaTime旋转自己。返回是否超过扫描限定时间。
    Transitions(状态转换)
    //状态转换。通过决定的返回值,选则两种状态中其中一个
    [System.Serializable]
    public class Transition
    {
    public Decision decision;
    public State trueState;
    public State falseState;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    测试结果
    第一种,巡逻->发现目标->追杀->目标死亡->巡逻。(颜色配合下图样例使用。)


    1. 起始 Patrol Chase 状态,巡逻点之间移动,还没有检测到目标,眼里射出的是清澈的绿色。


    2. 发现了目标,转为Chase Chaser 状态,射出了充满愤怒的红色射线,并且一直攻击目标。


    3. 当目标化为灰烬,转回 Patrol Chase 状态。


    第二种,巡逻->发现目标->追杀->目标死亡->旋转扫描目标->{两种情况:1. 发现目标,回到第二步。2. 超过扫描时间,回到第一步(巡逻)。(颜色配合下图样例使用。)


    1. 起始 Patrol Scanner 状态,巡逻,眼里射出的是原谅的绿色。


    2. 发现刚刚杀了蓝孩子的小红,转为 Chase Scanner 状态,追杀之。


    3. 杀掉小红之后,转为 Alert Scanner 状态。旋转扫描周围是否有敌人。


    4. 没有扫到,回到 Patrol Scanner 状态。

  • 相关阅读:
    想要学习设计模式,你得先会看类图,一张图读懂UML
    UML类图中箭头的含义
    DDD学习
    Customize your build
    WaitAll vs WhenAll
    When does a C# Task actually start?
    UE4中多种颜色轮廓线的后期处理
    [UE4]武器碰撞
    动态材质实例(Dynamic Material Instance)
    卷积运算
  • 原文地址:https://www.cnblogs.com/dayspring/p/13228225.html
Copyright © 2020-2023  润新知