吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3557|回复: 1
收起左侧

[其他转载] [unity] 状态机 委托 AI巡逻与追逐 Auto切换

[复制链接]
wtujoxk 发表于 2018-8-26 21:02
本帖最后由 wtujoxk 于 2018-8-26 21:25 编辑

效果:


主要实现NPC的巡逻和看见玩家后追逐玩家的实例,如果玩家超出了要追逐的范围,就又回到巡逻状态
代码全部添加注释,比较简单
状态类:
[C#] 纯文本查看 复制代码
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();
            }
        }
         
        //[url=home.php?mod=space&uid=190858]@brief[/url] 更新状态
        protected void OnUpdateState(float deltaTime)
        {
            stateTime += deltaTime;
            if (_state != null && _state.OnUpdate != null) _state.OnUpdate(deltaTime);
        }
    }
}


NPC控制类:
[C#] 纯文本查看 复制代码
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;
        }
    }
}


github:https://github.com/yuxianqiang/Unity_StateMachine


发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

yunruifuzhu 发表于 2018-8-26 21:35
应用场景说明下额。。不然都没人看
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 20:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表