Unity 状态机 委托 AI巡逻与追逐 Auto切换

效果:

 

这个状态类是在网上Down来的,觉得实现方式不错,就分享了……
主要实现NPC的巡逻和看见玩家后追逐玩家的实例,如果玩家超出了要追逐的范围,就又回到巡逻状态
代码全部添加注释,比较简单
状态类:

 

using System;
using UnityEngine;
 
///@brief
///文件名称:State
///功能描述:
///数据表:
///作者:YuXianQiang
///日期:#CreateTime#
///R1:
///修改作者:
///修改日期:
///修改理由:
 
namespace HuangDong.Yu
{
    public class State
    {
        //brief 进入
        public Action OnEnter;
        //brief 离开
        public Action OnLeave;
        //brief 更新状态
        public Action<float> OnUpdate;
    }
 
    public class StateMachine : MonoBehaviour
    {
        //brief 状态时间
        public float stateTime { get; private set; }
 
        private State _state;
        public State state
        {
            //得到当前状态
            get { return _state; }
            //设置当前状态
            set
            {
                //退出上一次的状态
                if (_state != null && _state.OnLeave != null) _state.OnLeave();
                stateTime = 0;
                _state = value;
                //开始当前的状态
                if (_state != null && _state.OnEnter != null) _state.OnEnter();
            }
        }
         
        //brief 更新状态
        protected void OnUpdateState(float deltaTime)
        {
            stateTime += deltaTime;
            if (_state != null && _state.OnUpdate != null) _state.OnUpdate(deltaTime);
        }
    }
}


NPC控制

 

 

using System;
using System.Collections.Generic;
using UnityEngine;
 
///@brief
///文件名称:NPCControl
///功能描述:
///数据表:
///作者:YuXianQiang
///日期:#CreateTime#
///R1:
///修改作者:
///修改日期:
///修改理由:
 
namespace XianQiang.Yu
{
    //NPC的控制类,继承自StateMachine
    //类实现了游戏开始时,NPC开始按规定路线巡逻
    //当视野中出现玩家,则开始追逐玩家
    //玩家和NPC的距离拉开后,NPC自动返回规定路线巡逻
    //这样就实现了状态的切换
    public class NPCControl : StateMachine
    {
        //brief 玩家
        public GameObject player;
        //brief NPC
        public GameObject npc;
        //brief 路径
        public Transform[] wayPoints;
        //brief 当前路径点
        private int currentWayPoint = 0;
        //brief 跟随路径点移动,如果有多种状态,继续添加
        private State follow = new State();
        //brief 追着玩家跑,如果有多种状态,继续添加
        private State chase = new State();
        //brief 临时状态
        private State tempState;
        void Start()
        {
            follow.OnEnter = StartFollow; //跟随路径
            //follow.OnLeave = StopFollow;//这里没有使用退出状态,可根据需要自行添加
 
            chase.OnEnter = StartChase; //追逐玩家
            //chase.OnLeave = StopChase; //这里没有使用退出状态,可根据需要自行添加
 
            follow.OnUpdate = FollowUpdate; //跟随路径状态
            chase.OnUpdate = ChaseUpdate; //追逐状态
 
            tempState = follow; //初始为跟随路径点移动
        }
 
        void Update()
        {
            //更新状态
            OnUpdateState(Time.deltaTime);
            state = tempState;
        }
 
        /// <summary>
        /// brief 满足条件,更换状态
        /// </summary>
        /// <param name="obj"></param>
        private void ChaseUpdate(float obj)
        {
            if (Vector3.Distance(npc.transform.position, player.transform.position) >= 30)
                tempState = follow;
        }
 
        /// <summary>
        /// brief 满足条件,更换状态
        /// </summary>
        /// <param name="obj"></param>
        private void FollowUpdate(float obj)
        {
            RaycastHit hit;
            if (Physics.Raycast(npc.transform.position, npc.transform.forward, out hit, 15F))
                if (hit.transform.gameObject.tag == "Player")
                    tempState = chase;
        }
 
        /// <summary>
        /// brief 追逐玩家移动方法
        /// </summary>
        private void StartChase()
        {
            Vector3 vel = npc.GetComponent<Rigidbody>().velocity;
            Vector3 moveDir = player.transform.position - npc.transform.position;
 
            npc.transform.rotation = Quaternion.Slerp(npc.transform.rotation,
                Quaternion.LookRotation(moveDir), 5*Time.deltaTime);
 
            npc.transform.eulerAngles = new Vector3(0, npc.transform.eulerAngles.y, 0);
            vel = moveDir.normalized*10;
 
            npc.GetComponent<Rigidbody>().velocity = vel;
        }
 
        /// <summary>
        /// brief 跟随路径点移动的方法
        /// </summary>
        private void StartFollow()
        {
            Vector3 vel = npc.GetComponent<Rigidbody>().velocity;
            Vector3 moveDir = wayPoints[currentWayPoint].position - npc.transform.position;
 
            if (moveDir.magnitude < 1)
            {
                currentWayPoint++;
                if (currentWayPoint >= wayPoints.Length)
                {
                    currentWayPoint = 0;
                }
            }
            else
            {
                vel = moveDir.normalized*10;
                npc.transform.rotation = Quaternion.Slerp(npc.transform.rotation,
                    Quaternion.LookRotation(moveDir), 5*Time.deltaTime);
                npc.transform.eulerAngles = new Vector3(0, npc.transform.eulerAngles.y, 0);
            }
            npc.GetComponent<Rigidbody>().velocity = vel;
        }
    }
}

Unity 2018.1.0f2
github:https://github.com/yuxianqiang/Unity_StateMachine

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值