IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 第三个项目——PacMan(2) -> 正文阅读

[游戏开发]第三个项目——PacMan(2)

第五步 敌人动画创建

添加上下左右四个动画
在这里插入图片描述
因为敌人需要方向变化的动画,所以需要添加条件来控制动画的转换
在这里插入图片描述
尝试后发现动画转向有延迟
在这里插入图片描述
将Can Transition To 禁用可以让动画在装换时,不会让动画自己转换自己

第六步 敌人AI创建

敌人AI是由三个不同状态组成,因此需要使用到状态机。

状态机的定义
状态机也叫有限状态机(FSM)是表示有限个状态以及这些状态之间的转移和动作等行为的数学模型。
状态机是一个算法思想,其主要用于描述对象在它的生命周期内所经历的状态过程,以及如何响应来自外界的各种事件
状态机的四大概念(组成)
1、状态(State) 一个状态机至少要包含两个状态
2、事件(Event) 事件就是执行某个操作的触发条件
3、动作(Action) 事件发生以后要执行动作
4、变换(Transition) 从一个状态变化为另一个状态

三个状态:路点状态、巡逻状态、A*追踪状态

状态机代码

public class StateMachine<Towner> : MonoBehaviour
{
    private State<Towner> curState = null;

    private Towner owner;//状态机的拥有者

    public void Init(Towner owner,State<Towner> initialState )//初始化
    {
        this.owner = owner;
        ChangeState(initialState);
    }
    //2、负责转换状态
    public void ChangeState(State<Towner> newState)
    {
        print(string.Format("{0}=>{1}", curState == null ? "n/a" : curState.GetType().Name, newState.GetType().Name));
        if (curState != null)
        {
            curState.Exit(owner);//清理
        }
        curState = newState;
        curState.Enter(owner);//初始化
    }
    public void Update()
    {
        curState.Update(owner);
    }
}

状态类代码

public class State<Towner>
{
    public virtual void Enter(Towner e)
    { }
    public virtual void Update(Towner e)
    { }
    public virtual void Exit(Towner e)
    { }
}

代码分析
第一步 声明一个当前状态类(CurState)
第二步 声明一个状态机的拥有者(onwer,游戏中的怪物拥有着不同的状态,所以成为状态机的拥有者)
第三步 对状态机和状态进行初始化

    public void Init(Towner owner,State<Towner> initialState )//初始化
    {
        this.owner = owner;//将当前的状态机拥有者初始化
        ChangeState(initialState);//调用ChangeState方法对状态进行转换
    }

第四步 进行状态转换

 public void ChangeState(State<Towner> newState)
    {
        print(string.Format("{0}=>{1}", curState == null ? "n/a" : curState.GetType().Name, newState.GetType().Name));
        if (curState != null)
        {
            curState.Exit(owner);//清理
        }
        curState = newState;
        curState.Enter(owner);//初始化
    }

解析:
新的状态传入
进行检测有无当前状态
如何没有当前状态,将当前状态变为新状态
如果有当前状态,就将当前状态清理 然后将当状态变为新状态
最后对已经从新状态变为当前状态的状态进行初始化

第五步 对状态进行更新。

路点状态

代码

 class WaypointState : State<Monster>//路点
    {
       private List<Vector2> path;//路径
        private int index;//当前要往哪个路径点走
        public WaypointState(List<Vector2> path)
        {
            this.path = path;
            this.index = 0;
            
        }
        public override void Update(Monster e)//重写State的Update方法
        {
            Vector2 p = Vector2.MoveTowards(e.transform.position, path[index], e.speed * Time.fixedDeltaTime);
            e.gameObject.GetComponent<Rigidbody2D>().MovePosition(p);
            if ((Vector2)e.transform.position == path[index])
            {
           
                index++;
                if (index == path.Count)
                {
                    //e.stateMachine.ChangeState();
                }
                else
                {
                    Vector2 dir = path[index]-path[index-1]; //path[index-1]==e.transform.position
                    e.GetComponent<Animator>().SetFloat("DirX", dir.x);
                    e.GetComponent<Animator>().SetFloat("DirY", dir.y);
                }
            }
            
        }
    }

代码分析
路点的核心就在于存储路径点的路径
首先声明一个List用来存储路径点。然后添加路点
在这里插入图片描述
然后声明一个构造器来初始化。
接着对State类的Update方法进行重写,将路点作为移动的方向,使游戏物体按照路点的位置进行移动。

巡逻状态

代码

 class PatrolState : State<Monster>
    {
        public Vector2 dest;
        private Vector2 curDir;//当前移动的方向,有这个变量就可以防止在-curDir走了
        private Vector2[] dirs = new Vector2[] {Vector2.up,Vector2.down,Vector2.left,Vector2.right };//所有可移动方向

        public override void Enter(Monster e)
        {
            dest = e.transform.position;
            curDir = e.transform.position;
        }
        public override void Update(Monster e)
        {
            Vector2 p = Vector2.MoveTowards(e.transform.position, dest, e.speed * Time.fixedDeltaTime);
            e.gameObject.GetComponent<Rigidbody2D>().MovePosition(p);

            if ((Vector2)e.transform.position == dest)
            {
                List<Vector2> walkable = new List<Vector2>();
                for (int i = 0; i < dirs.Length; i++)
                {
                    //如果是curDir的反方向,提前排除掉
                    if (dirs[i] == -curDir)
                    {
                        continue;
                    }
                    if (e.CanGo(dirs[i])) //判断某个方向是否可以移动
                    {
                        walkable.Add(dirs[i]);
                    }
                }
                int index = Random.Range(0, walkable.Count);
                curDir = walkable[index];
                e.GetComponent<Animator>().SetFloat("DirX", curDir.x);
                e.GetComponent<Animator>().SetFloat("DirY", curDir.y);
                dest += curDir;
            }

            
        }

    }



  private bool CanGo(Vector2 dir)
    {
        RaycastHit2D hit = Physics2D.Linecast(this.transform.position, (Vector2)this.transform.position + dir, 1 << LayerMask.NameToLayer("Map"));

        return hit!= true;
    }


//有路点状态转换为巡逻状态
    if (index >= path.Count)
 {
    PatrolState patrolState = new PatrolState();
    e.stateMachine.ChangeState(patrolState);      
}




代码分析
巡逻的核心就在于生成一个上下左右的数组,对数组进行遍历。在遍历后判断方向然后进行游戏物体的移动。但不同的是巡逻状态比路点状态多一个初始化的重写

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 19:10:32  更:2022-04-22 19:12:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 21:50:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码