Unity——游戏AI实例

简介: Unity——游戏AI实例

上文Unity——模拟AI视觉已经实现了敌人视野探测功能,本文来完善敌人AI。

注意:若要阅读此文,务必在阅读完Unity——模拟AI视觉的基础上阅读


效果预展示:

image.png

AI敌人追击


 

接下来用最简单的方式实现敌人的AI状态机。首先,定义敌人的3个状态——待机、进攻和返回。

 enum AIState
    {
        Idle,   //待机状态
        Attack,  //进攻状态
        Back,    //返回状态
    } 

然后将Update函数改为状态机的模式,直接用switch-case语句实现

  enum AIState
    {
        Idle,   //待机状态
        Attack,  //进攻状态
        Back,    //返回状态
    } 
    AIState state;
 void Update()
    {
        switch (state)
        {
            case AIState.Idle:
                {
                    //待机状态。进行实现检测,若发现玩家则进攻
                    FieldOfView();
                }
                break;
                case AIState.Attack:
                {
                    //进攻状态,若离玩家或起点太远,则返回
                }
                break ;
                case AIState.Back:
                {
                    //返回状态
                }
                break;
        }
     }

状态机的原理比较复杂,但只需要用一个switch-case语句就能实现,或者用if语句编写也可以。之后只要把设计思路按部就班地编写成程序代码即可。

  1. 在待机状态下,要不断进行射线检测。如果射线检测发现了玩家,就可以将玩家的引用保存起来,以便后面进攻时使用。需要注意的是,应当将玩家及其子物体的Tag都改为Player,方便判断。
  2. 在进攻状态下,不断向目标位置移动(利用导航系统)。同时检测当前位置与起点或玩家之间的距离,如果距离过远就返回。
  3. 在返回状态下,先朝起点的位置移动,当移动到位后,再转向正面,回到一开始的朝向。有必要一开始就把初始的位置和朝向记录下来,分别是homePos和homeRot。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AIEnemy : MonoBehaviour
{
    Transform target;   //目标角色
    Vector3 homePos;  //起始位置
    Quaternion homeRot;  //起点的朝向 
    UnityEngine.AI.NavMeshAgent agent;
    public int viewRadius = 4;  //视野距离
    public int viewLines = 30; //射线数量
    public MeshFilter viewMeshFilter;
    List<Vector3> viewVerts;  //定点列表
    List<int> viewIndices;  //定点序号列表
    enum AIState
    {
        Idle,   //待机状态
        Attack,  //进攻状态
        Back,    //返回状态
    } 
    AIState state;   //AI状态机的状态
    void Start()
    {
        Transform view = transform.Find("view");
        viewMeshFilter = view.GetComponent<MeshFilter>();
        agent=GetComponent<UnityEngine.AI.NavMeshAgent>();
        viewVerts = new List<Vector3>();
        viewIndices = new List<int>();
        state = AIState.Idle;
        homePos = transform.position;
        homeRot = transform.rotation;
    }
    void Update()
    {
        switch (state)
        {
            case AIState.Idle:
                {
                    //待机状态。进行射线检测,若发现玩家则进攻
                    FieldOfView();
                    if (target != null)
                    {
                        state= AIState.Attack;  //切换状态
                    }
                }
                break;
                case AIState.Attack:
                {
                    //进攻状态,若离玩家或起点太远,则返回
                    agent.SetDestination(target.position);
                    if(Vector3.Distance(transform.position, target.position) > 10)
                    {
                        target = null;
                        state= AIState.Back;
                    }
                    if (Vector3.Distance(transform.position, homePos)>15)
                    {
                        target = null;
                        state = AIState.Back;
                    }
                }
                break ;
                case AIState.Back:
                {
                    //返回状态
                    agent.SetDestination(homePos);
                    if (!agent.hasPath)
                    {
                        //回到起点,匀速转到正面
                        if(Quaternion.Angle(homeRot,transform.rotation)>0.5f)
                        {
                            //逐步向目标角度转动,每次最多转2°
                            Quaternion q = Quaternion.RotateTowards(transform.rotation, homeRot, 2f);
                                transform.rotation = q;
                        }
                        else
                        {
                            state = AIState.Idle;
                        }
                    }
                }
                break;
        }
     }
        void FieldOfView()
        {
            viewVerts.Clear();
            viewVerts.Add(Vector3.zero);  //加入起点坐标,局部坐标系
            //获得最左边那条射线的向量,相对正前方,角度是-45°
            Vector3 forward_left = Quaternion.Euler(0, -45, 0) * transform.forward * viewRadius;
            //依次处理每条射线
            for (int i = 0; i <= viewLines; i++)
            {
                Vector3 v = Quaternion.Euler(0, (90.0f / viewLines) * i, 0) * forward_left;
                //角色位置+v,就是射线终点pos
                Vector3 pos = transform.position + v;
                //实际发射射线。注意RayCast的参数,重载很多容易搞错
                RaycastHit hitInfo;
                if (Physics.Raycast(transform.position, v, out hitInfo, viewRadius))
                {
                    //碰到物体,终点改为碰到的点
                    pos = hitInfo.point;
                if (hitInfo.transform.CompareTag("Player"))
                {
                    target=hitInfo.transform;
                }
                }
                //将每个点的位置加入列表,注意转为局部坐标系
                Vector3 p = transform.InverseTransformPoint(pos);
                viewVerts.Add(p);
            }
            //根据顶点绘制模型
            RefreshView();
        }
        void RefreshView()
        {
            viewIndices.Clear();
            //逐个加入三角面,每个三角面都以起点开始
            for (int i = 1; i < viewVerts.Count - 1; i++)
            {
                viewIndices.Add(0);
                viewIndices.Add(i);
                viewIndices.Add(i + 1);
            }
            //填写Mesh信息
            Mesh mesh = new Mesh();
            mesh.vertices = viewVerts.ToArray();
            mesh.triangles = viewIndices.ToArray();
            viewMeshFilter.mesh = mesh;
        }
}


相关文章
|
3月前
|
机器学习/深度学习 人工智能 图形学
卓伊凡的第一款独立游戏-详细介绍游戏开发引擎unity-以及详细介绍windows和mac的安装步骤【01】
卓伊凡的第一款独立游戏-详细介绍游戏开发引擎unity-以及详细介绍windows和mac的安装步骤【01】
346 9
|
3月前
|
人工智能 算法 数据库
给AI装上一个'超级大脑':信息检索如何改变RAG系统的游戏规则
从传统检索方法到现代向量检索,通过一个购物助手的故事,直观展示了不同检索技术的原理与应用。学会这些技巧,让你的AI不再是「记忆只有金鱼长度」的大模型!
200 24
|
3月前
|
机器学习/深度学习 人工智能 算法
当AI提示词遇见精密算法:TimeGuessr如何用数学魔法打造文化游戏新体验
TimeGuessr融合AI与历史文化,首创时间与空间双维度评分体系,结合分段惩罚、Haversine距离计算与加权算法,辅以连击、速度与完美奖励机制,实现公平且富挑战性的游戏体验。
|
11月前
|
存储 人工智能 运维
【01】做一个精美的打飞机小游戏,浅尝阿里云通义灵码python小游戏开发AI编程-之飞机大战小游戏上手实践-优雅草央千澈-用ai开发小游戏尝试-分享源代码和游戏包
【01】做一个精美的打飞机小游戏,浅尝阿里云通义灵码python小游戏开发AI编程-之飞机大战小游戏上手实践-优雅草央千澈-用ai开发小游戏尝试-分享源代码和游戏包
566 48
【01】做一个精美的打飞机小游戏,浅尝阿里云通义灵码python小游戏开发AI编程-之飞机大战小游戏上手实践-优雅草央千澈-用ai开发小游戏尝试-分享源代码和游戏包
|
4月前
|
人工智能 JSON 程序员
别再和AI玩文字游戏:JSON提示工程让AI乖乖按表填空
厌倦了和AI玩猜谜游戏吗?JSON提示工程来拯救你!用咖啡订单的方式和AI对话,让每次交互都精准到位,告别模糊不清的回复,迎接可预测的AI输出时代。
|
3月前
|
小程序 PHP 图形学
热门小游戏源码(Python+PHP)下载-微信小程序游戏源码Unity发实战指南​
本文详解如何结合Python、PHP与Unity开发并部署小游戏至微信小程序。涵盖技术选型、Pygame实战、PHP后端对接、Unity转换适配及性能优化,提供从原型到发布的完整指南,助力开发者快速上手并发布游戏。
|
8月前
|
人工智能 自然语言处理 前端开发
DeepSite:基于DeepSeek的开源AI前端开发神器,一键生成游戏/网页代码
DeepSite是基于DeepSeek-V3模型的在线开发工具,无需配置环境即可通过自然语言描述快速生成游戏、网页和应用代码,并支持实时预览效果,显著降低开发门槛。
1531 93
DeepSite:基于DeepSeek的开源AI前端开发神器,一键生成游戏/网页代码
|
4月前
|
C# 图形学 开发者
【Unity3D实例-功能-镜头】俯视角
本文介绍了Unity中常用的俯视角镜头实现方法,涵盖模型添加、角色Tag设置、摄像机脚本编写及测试运行,帮助开发者快速掌握俯视角在策略与模拟类游戏中的应用技巧。
322 0
|
4月前
|
人工智能 定位技术 C#
【Unity3D实例-功能-移动】通过鼠标点击进行角色移动
本文介绍了如何在Unity中实现鼠标点击控制角色移动的功能。通过安装导航网格、设置地图与角色、烘焙路径及编写脚本,带领读者一步步构建角色自动寻路系统,增强游戏交互体验。
203 0
|
5月前
|
C# 图形学 开发者
【Unity3D实例-功能-移动】复杂移动(Blend Tree方式)
本文介绍了使用Unity中Blend Tree实现角色移动控制的完整教程,涵盖动画器设置、Blend Tree创建、CharacterController组件添加及代码控制,帮助开发者实现流畅自然的角色动画效果。
137 0

热门文章

最新文章