关于FSM(有限状态机)的学习2

以下内容参照《unity3d 人工智能编程》--Aung Sithu Kyaw,Clifford Peters ,Thet Naing Swe编著</span>

最近在研究此书,花费几天时间,略有收获,所以写下此编文章,计划是3章,这是第一章,受个人能力限制,这个只是我的粗陋之见。

首先贴下此书源码下载地址,http://hzbook.com/Books/8580.html,请大家尊重知识产权,如果有需要自行购买(非广告)。

本文主要讲述的是有限状态机的框架第二篇是人工智能所要实现的行为,部分代码没有注释,但应该不影响阅读


这个是继承AdvanceFSM的子类,前文,已经说过了,这个是坦克人工智能所实现的行为

using UnityEngine;
using System.Collections;

public class NPCTankController : AdvancedFSM  {
    //子弹预制
    public GameObject bullet;
    //生命值
    private int health;
    /// <summary>
    /// 重写初始化方法
    /// </summary>
    protected override void Initialize()
    {
        health = 100;

        elapsedTime = 0.0f;
        shootRate = 2.0f;

        GameObject objPlayer = GameObject.FindGameObjectWithTag("Player");
        playerTransform = objPlayer.transform;

        if (!playerTransform)
        {
            print("没有添加Player标签");
            return;
        }
        //获得子类的坦克炮塔以及炮塔下的旋转点,由于每个人的设计不同,可以相应的改变
        turret = gameObject.transform.GetChild(0).transform;
        bulletSpwanPoint = turret.GetChild(0).transform;
        //开始实现有限状态机
        ConstructFSM();
    }

    protected override void FSMUpdate()
    {
        //更新计时器
        elapsedTime += Time.deltaTime;
    }

    /// <summary>
    /// 有限状态机
    /// </summary>
    private void ConstructFSM()
    {
        //获得巡逻点的
        pointList = GameObject.FindGameObjectsWithTag("WandarPoint");

        //给巡逻点赋值
        Transform[] waypoints = new Transform[pointList.Length];
        int i = 0;
        foreach (GameObject  obj in pointList )
        {
            waypoints[i] = obj.transform;
            i++;
        }

        //把对应的状态的键和值加入字典
        //巡逻
        PatrolState patrol = new PatrolState(waypoints);
        //发现玩家,并追逐玩家
        patrol.AddTransition(Transition.SawPlayer, FSMStateID.Chasing);
        //死亡
        patrol.AddTransition(Transition.NoHealth, FSMStateID.Dead);

        //追逐
        ChaseState chase = new ChaseState(waypoints);
        //丢失玩家,转为巡逻
        chase.AddTransition(Transition.LostPlayer, FSMStateID.Patrolling);
        //接近玩家并且能攻击玩家
        chase.AddTransition(Transition.ReachPlayer, FSMStateID.Attacking);
        //死亡
        chase.AddTransition(Transition.NoHealth, FSMStateID.Dead);

        //进攻
        AttackState attack = new AttackState(waypoints);
        //丢失玩家,转为巡逻
        attack.AddTransition(Transition.LostPlayer, FSMStateID.Patrolling);
        //发现玩家,并追逐玩家
        attack.AddTransition(Transition.SawPlayer, FSMStateID.Chasing);
        //死亡
        attack.AddTransition(Transition.NoHealth, FSMStateID.Dead);

        //死亡
        DeadState dead = new DeadState();
        dead.AddTransition(Transition.NoHealth, FSMStateID.Dead);

        //添加转移和状态
        AddFSMState(patrol);
        AddFSMState(chase);
        AddFSMState(attack);
        AddFSMState(dead);
    }

    //碰撞检测
    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Bullet")
        {
            health -= 30;
            if (health <= 0)
            {
                SetTransition(Transition.NoHealth);
            }
        }
    }

    /// <summary>
    /// 设置状态转移
    /// </summary>
    /// <param name="t"></param>
    public  void SetTransition(Transition t)
    {
        PerformTransition(t);
    }

    public  void ShootBullet()
    {
        if (elapsedTime >= shootRate)
        {
            Instantiate(bullet, bulletSpwanPoint.position, bulletSpwanPoint.rotation);
            elapsedTime = 0.0f;
        }
    }
}


巡逻状态

using UnityEngine;
using System.Collections;
using System.Collections .Generic ;
public class PatrolState : FSMState {

    public PatrolState (Transform [] wp)
    {
        wayPoints = wp;
        stateID = FSMStateID.Patrolling;
        curSpeed = 1.0f;
        curRotSpeed = 1.0f;
    }

    /// 该方法用于检查当前状态是否需要转移到另外一个状态
    public override void Reason(Transform player, Transform npc)
    {
        //转换状态
        if (Vector3.Distance(npc.position, player.position)<=300.0f)
        {
            npc.GetComponent<NPCTankController>().SetTransition(Transition.SawPlayer);
        }
    }
    /// 该方法为currentState变量执行实际的任务
    public override void Act(Transform player, Transform npc)
    {
        //寻找下一个巡逻点
        if (Vector3.Distance(npc.position, destinationPos) <= 100.0f)
        {
            FindNextPoint();
        }
        //旋转炮塔
        Quaternion targetRotation = Quaternion.LookRotation(destinationPos - npc.position);
        npc.rotation = Quaternion.Slerp(npc.rotation, targetRotation, Time.deltaTime * curSpeed);
        //移动
        npc.Translate(Vector3.forward * Time.deltaTime * curSpeed);
    }
   
}


追逐状态

using UnityEngine;
using System.Collections;

public class ChaseState : FSMState  {
    private Transform[] waypoints;

    public ChaseState(Transform[] wp)
    {
        this.waypoints = wp;
        stateID = FSMStateID.Chasing;

        curRotSpeed = 1.0f;
        curSpeed = 100.0f;

        FindNextPoint();
    }
    public override void Reason(Transform player, Transform npc)
    {
        destinationPos = player.position;

        float dist = Vector3.Distance(npc.position, destinationPos);
        if (dist <= 200.0f)
        {
            npc.GetComponent<NPCTankController>().SetTransition(Transition.ReachPlayer);
        }
        else if (dist >= 300.0f)
        {
            npc.GetComponent<NPCTankController>().SetTransition(Transition.LostPlayer);
        }
    }

    public override void Act(Transform player, Transform npc)
    {
        destinationPos = player.position;

        Quaternion targetRotation = Quaternion.LookRotation(destinationPos - npc.position);
        npc.rotation = Quaternion.Slerp(npc.rotation, targetRotation, Time.deltaTime * curRotSpeed);

        npc.Translate(Vector3.forward * Time.deltaTime * curSpeed);
    }
}


进攻状态

using UnityEngine;
using System.Collections;

public class AttackState : FSMState  {
    //初始化相关属性
    public AttackState(Transform[] wp)
    {
        wayPoints = wp;
        stateID = FSMStateID.Attacking;
        curRotSpeed = 1.0f;
        curSpeed = 100.0f;

        FindNextPoint();
    }

    public override void Reason(Transform player, Transform npc)
    {
        float dist = Vector3.Distance(npc.position, player.position);
        if (dist >= 200.0f && dist <= 300.0f)
        {
            Quaternion targetRotation = Quaternion.LookRotation(destinationPos - npc.position);
            npc.rotation = Quaternion.Slerp(npc.rotation, targetRotation, Time.deltaTime * curRotSpeed);

            npc.Translate(Vector3.forward * Time.deltaTime * curSpeed);

            npc.GetComponent <NPCTankController >().SetTransition (Transition.SawPlayer );
        }
        else if (dist >= 300.0f)
        {
            npc.GetComponent<NPCTankController>().SetTransition(Transition.LostPlayer);
        }
    }

    public override void Act(Transform player, Transform npc)
    {
        destinationPos = player.position;

        Transform turret = npc.GetComponent<NPCTankController>().turret;
        Quaternion turretRotation = Quaternion.LookRotation(destinationPos - turret.position);
        turret.rotation = Quaternion.Slerp(turret.rotation, turretRotation, Time.deltaTime * curRotSpeed);

        npc.GetComponent<NPCTankController>().ShootBullet();
    }
}



using UnityEngine;
using System.Collections;

public class DeadState : FSMState  {
    public DeadState()
    {
        stateID = FSMStateID.Dead;
    }

    public override void Reason(Transform player, Transform npc)
    {
        
    }

    public override void Act(Transform player, Transform npc)
    {
        //死亡状态什么都不做,如果有死亡动作,可以写个方法播放
    }
}

此篇结束,下一文是我就这次学习的总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值