UnityAI——个体AI角色的操控行为脚本(二)

简介: UnityAI——个体AI角色的操控行为脚本

五、逃避

逃避行为与追逐行为的不同是它试图使AI角色逃离预测位置。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SteeringForEvade :Steering
{
    public GameObject target;
    private Vector3 desiredVelocity;//预期速度
    private Vehicle m_vehicle;//获得被操控的AI角色
    private float maxSpeed;
    void Start()
    {
        m_vehicle = GetComponent<Vehicle>();
        maxSpeed = m_vehicle.maxSpeed;
    }
    public override Vector3 Force()
    {
        Vector3 toTarget = target.transform.position - transform.position;
        float lookaheadTime = toTarget.magnitude / (maxSpeed + target.GetComponent<Vehicle>().velocity.magnitude);//向前预测的时间
        desiredVelocity = (transform.position - (target.transform.position+target.GetComponent<Vehicle>().velocity*lookaheadTime)).normalized * maxSpeed;
        return (desiredVelocity - m_vehicle.velocity);
    }
}

六、随机徘徊

很多时候,我们需要让游戏中的角色随机移动,比如说士兵的巡逻。我们希望这种随机移动看上去是真实的,而不是一直循环某个路径。

利用操控行为来实现随机派啊坏有多种不同的方法,最简单的方式是利用前面提到的靠近行为。在场景中随机放置目标,让角色靠近目标,每隔一定时间就随机改变目标的位置。这个方法很简单,但缺点也很明显,比如角色可能会突然掉头,因为目标可能移动到了角色的后面。

解决这个问题的原理与内燃机的气缸曲轴转动相似。在角色(气缸)通过连杆连接到曲轴上,目标被限定到曲轴圆周上,移向目标。为了看得更随机,每帧给目标附加一个随机的位移。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SteeringForWander : Steering
{
    public float wanderRadius; //徘徊半径
    public float wanderDistance; //徘徊距离
    public float wanderJitter; //每秒加到目标的随即位移的最大值
    public bool isPlanar;
    private Vector3 desiredVelocity;//预期速度
    private Vehicle m_vehicle;//获得被操控的AI角色
    private float maxSpeed;
    private Vector3 circleTarget;
    private Vector3 wanderTarget;
    void Start()
    {
        m_vehicle = GetComponent<Vehicle>();
        maxSpeed = m_vehicle.maxSpeed;
        isPlanar = m_vehicle.isPlanar;
        circleTarget = new Vector3(wanderRadius * 0.707f, 0, wanderRadius * 0.707f);  //选取与安全上的一个点作为初始点
    }
    public override Vector3 Force()
    {
        Vector3 randomDisplacement = new Vector3((Random.value - 0.5f) * 2 * wanderJitter, (Random.value - 0.5f) * 2 * wanderJitter, (Random.value - 0.5f) * 2 * wanderJitter);
        if (isPlanar)
            randomDisplacement.y = 0;
        circleTarget+=randomDisplacement;//将随机位移加到初始点上
        circleTarget = wanderRadius * circleTarget.normalized;//由于新位置很可能不在圆周上,因此需要投影到圆周上
        wanderTarget = m_vehicle.velocity.normalized * wanderDistance + circleTarget + transform.position;//之前计算出的值是相对于AI的,需要转换为世界坐标
        desiredVelocity = (wanderTarget - transform.position).normalized * maxSpeed;
        return (desiredVelocity - m_vehicle.velocity);
    }
}

七、路径跟随

就像赛道上的赛车需要导航一样,路径跟随会产生一个操控力,使AI角色沿着由事先设置的轨迹构成路径的一系列路点移动。

最简单的方式是将当前路点设置为路点列表中的第一个路点,用靠近行为来靠近这个路点,至非常接近这个点;然后靠近列表中的下一个路点,一直到最后一个路点。

在实现这一功能时,需要设置一个"路点半径"参数,这个参数的设置会引起路径形状的变化

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SteeringFollowPath : Steering
{
    public GameObject[] waypoints = new GameObject[4];//由节点表示的路径
    private Transform target;
    private int currentNode;
    private float arriveDistance;
    private float sqrArriveDistacne;
    private int numberOfNodes;
    private Vector3 force;
    private Vector3 desiredVelocity;//预期速度
    private Vehicle m_vehicle;//获得被操控的AI角色
    private float maxSpeed;
    private bool isPlanar;
    public float slowDownDistacne;
    void Start()
    {
        numberOfNodes = waypoints.Length;
        m_vehicle = GetComponent<Vehicle>();
        maxSpeed = m_vehicle.maxSpeed;
        isPlanar = m_vehicle.isPlanar;
        currentNode = 0;
        target = waypoints[currentNode].transform;
        arriveDistance = 1.0f;
        sqrArriveDistacne = arriveDistance * arriveDistance;
    }
    public override Vector3 Force()
    {
        force = new Vector3(0, 0, 0);
        Vector3 dist = target.position - transform.position;
        if (isPlanar)
            dist.y = 0;
        if(currentNode==numberOfNodes-1)
        {
            if(dist.magnitude>slowDownDistacne)
            {
                desiredVelocity=dist.normalized*maxSpeed;
                force=desiredVelocity-m_vehicle.velocity;
            }
            else
            {
                desiredVelocity = dist - m_vehicle.velocity;
                force = desiredVelocity - m_vehicle.velocity;
            }
        }
        else
        {
            if(dist.sqrMagnitude<sqrArriveDistacne)
            {
                currentNode++;
                target = waypoints[currentNode].transform;
            }
            desiredVelocity= dist.normalized * maxSpeed;
            force = desiredVelocity - m_vehicle.velocity;
        }
        return force;
    }
}

八、避开障碍

避开障碍是指操控AI角色避开路上的障碍物,例如在路径上有一颗树,当角色距离树比较近时,就会产生一个"排斥力",使AI角色不至于撞上树。当有好几棵树时,至产生躲避最近的树的操控力,这样,AI角色就会一个一个地躲开这些树。

在这个算法中,首先需要发现障碍物。AI角色唯一需要担心的就是挡在其路线前方的那些物体。算法的分析步骤如下:

1、用角色前进的速度生成一个向亮ahead

ahead=position+normalize(velocity)*MAX_SEE_AHEAD。ahead的长度决定了AI能看到的距离

2、每个障碍物都用一个几何形状表示,这里采用包围球来标识场景中的每个障碍。

一种可能的方法是检测ahead向量与障碍物的包围球是否相交。这里采用简化的方法。

需要一个向量ahead2,ahead2=ahead*0.5

3、接下来进行碰撞检测。只需要比较向量的终点与球心的距离d是否小于球的半径。如果ahead与ahead2中的一个向量在球内,那么说明障碍物在前方。如果监测到了多个障碍物,那么选择最近的那个。

4、计算操控力

avoidance_force=ahead-obstacle_center

avoidance_force=normalize(avoidance_force)*MAX_AVOID_FORCE

采用这种方法的缺点是,当AI角色接近障碍而操控力正在使其原理的时候,即使AI正在旋转,也可能会检测到碰撞。一种改进方法是根据AI角色的当前速度调整ahead向量,计算方法如下:

Dynamic_length=length(velocity)/MAX_VELOCITY

ahead=position+normalize(velocity)*dynamic_length

这时,dynamic_length的范围是0~1,当全速移动时,值是1

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SteeringForCollisionAvoidance :Steering
{
    public bool isPlanar;
    private Vector3 force;
    private Vector3 desiredVelocity;//Ԥ���ٶ�
    private Vehicle m_vehicle;//��ñ��ٿص�AI��ɫ
    private float maxSpeed;
    private float maxForce;
    public float avoidanceForce;
    public float MAX_SEE_AHEAD = 2.0f;//�ܼ���������
    private GameObject[] allColliders;
    void Start()
    {
        m_vehicle = GetComponent<Vehicle>();
        maxSpeed = m_vehicle.maxSpeed;
        isPlanar = m_vehicle.isPlanar;
        maxForce = m_vehicle.maxForce;
        if(avoidanceForce>maxForce)
            avoidanceForce = maxForce;
        allColliders = GameObject.FindGameObjectsWithTag("obstacle");//�洢TagΪobstacle��������Ϊ��ײ��
    }
    public override Vector3 Force()
    {
        RaycastHit hit;
        Vector3 force = new Vector3(0, 0, 0);
        Vector3 velocity = m_vehicle.velocity;
        Vector3 normalizedVelocity = velocity.normalized;
        Debug.DrawLine(transform.position, transform.position + normalizedVelocity * MAX_SEE_AHEAD * (velocity.magnitude / maxSpeed));//����һ�����ߣ���Ҫ���������������ཻ����ײ��
        if (Physics.Raycast(transform.position, normalizedVelocity, out hit, MAX_SEE_AHEAD * velocity.magnitude / maxSpeed))
        {
            Vector3 ahead = transform.position + normalizedVelocity * MAX_SEE_AHEAD * (velocity.magnitude / maxSpeed); //���������ij����ײ���ཻ����ʾ������ײ
            force=ahead-hit.collider.transform.position;//���������ײ����IJٿ���
            force *= avoidanceForce;
            if (isPlanar)
                force.y = 0;
            foreach(GameObject c in allColliders)//�ı���ײ�����ɫ
            {
                if (hit.collider.gameObject == c)
                {
                    c.GetComponent<Renderer>().material.color = Color.black;
                }
                else
                    c.GetComponent<Renderer>().material.color = Color.white;
            }
        }
        else//���ǰ��û�м�⵽��ײ�壬��������ײ��ı���ɫ
        {
            foreach (GameObject c in allColliders)
            {
                c.GetComponent<Renderer>().material.color = Color.white;
            }
        }
        return force;
    }
}
相关文章
|
3月前
|
人工智能 JavaScript 前端开发
多角色AI代理的一次尝试- AI代码助手
本文介绍了一个多角色AI代理系统,用于自动化代码开发过程。系统包括用户接口、需求分析、代码结构设计、代码生成、代码审查和代码执行等角色,通过协调工作实现从需求到代码生成与测试的全流程自动化。使用了qwen2.5 7b模型,展示了AI在软件开发中的潜力。
|
4天前
|
人工智能 大数据
ai时代的到来……脚本也更容易翻到合适自己的……那究竟是照脚本好?还是?
随着DeepSeek的流行,个人和小团体在大数据面前显得脆弱。AI让工作简化,但也会导致失业风险。会使用新技术的人忙碌,其他人可能闲着或落后。未来充满不确定性,信息真假难辨,人们仿佛在演戏,真情实感被掩盖。在AI时代,如何保持真实与秩序成为重要问题。
24 6
|
30天前
|
Web App开发 人工智能 JSON
AutoMouser:AI Chrome扩展程序,实时跟踪用户的浏览器操作,自动生成自动化操作脚本
AutoMouser是一款Chrome扩展程序,能够实时跟踪用户交互行为,并基于OpenAI的GPT模型自动生成Selenium测试代码,简化自动化测试流程。
139 17
AutoMouser:AI Chrome扩展程序,实时跟踪用户的浏览器操作,自动生成自动化操作脚本
|
1天前
|
人工智能 自然语言处理 API
Cline:29.7K Star!一文详解VSCode最强开源AI编程搭子:一键生成代码+自动跑终端+操控浏览器...
Cline 是一款集成于 VSCode 的 AI 编程助手,支持多语言模型,实时检查语法错误,帮助开发者提高编程效率。通过智能化手段,Cline 可以生成代码、执行终端命令、调试 Web 应用,并扩展更多功能。
63 5
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
DiffSensei:AI 漫画生成框架,能生成内容可控的黑白漫画面板,支持多角色和布局控制
DiffSensei 是一个由北京大学、上海AI实验室及南洋理工大学共同推出的AI漫画生成框架,能够生成可控的黑白漫画面板。该框架整合了基于扩散的图像生成器和多模态大型语言模型(MLLM),支持多角色控制和精确布局控制,适用于漫画创作、个性化内容生成等多个领域。
175 18
DiffSensei:AI 漫画生成框架,能生成内容可控的黑白漫画面板,支持多角色和布局控制
|
2月前
|
传感器 人工智能 安全
杨笛一团队:一个弹窗,就能把AI智能体操控电脑整懵了
杨笛一团队最新研究揭示,简单弹窗可操控AI智能体,使其在执行任务时陷入混乱。实验显示,在OSWorld和VisualWebArena环境中,攻击成功率分别达86%和60%以上。该发现强调了AI安全的重要性,提醒我们在享受AI便利的同时需警惕潜在风险。研究指出,弹窗设计中的四个关键要素(注意力钩子、指令、信息横幅、ALT描述符)对攻击成功至关重要,并建议通过安全训练、人类监督和环境感知提升防御能力。
62 13
|
2月前
|
人工智能 智能硬件
SPAR:智谱 AI 推出自我博弈训练框架,基于生成者和完善者两个角色的互动,提升了执行准确度和自我完善能力
SPAR 是智谱团队推出的自我博弈训练框架,旨在提升大型语言模型在指令遵循方面的能力,通过生成者和完善者的互动以及树搜索技术优化模型响应。
74 0
SPAR:智谱 AI 推出自我博弈训练框架,基于生成者和完善者两个角色的互动,提升了执行准确度和自我完善能力
|
2月前
|
人工智能 自然语言处理 安全
谷歌版贾维斯即将问世,最强Gemini 2.0加持!AI自主操控电脑时代来临
谷歌发布的Gemini 2.0标志着AI新时代的到来,被誉为“谷歌版贾维斯”。该系统在自然语言处理、图像识别及自主操控电脑等方面取得重大进展,尤其在多模态数据处理上表现出色,能更准确理解用户需求并执行复杂任务。尽管存在对AI自主操控可能带来的负面影响的担忧,谷歌强调Gemini 2.0旨在辅助而非替代人类工作,且已采取多项措施保障其安全性和可靠性。
60 5
|
4月前
|
人工智能 前端开发 JavaScript
AI+脚本让我的效率翻倍,你也可以试试
本文分享了一名高级软件工程师如何利用 AI 工具(如 VSCode 插件 Codeium、通义灵码,及网页端的通义千问和 GPT-4)提升工作效率的经验。从代码生成、单元测试、脚本生成到文本润色,再到新框架学习,AI 工具在多个方面显著提高了开发效率和代码质量。文章还提供了具体示例和注意事项,帮助读者更好地应用这些工具。
115 1
|
4月前
|
人工智能 缓存 安全
什么是AI网关?AI网关在企业系统中承担什么角色?
AI大模型的快速发展正推动各行业增长,预计未来十年年均增长率达37.3%,2027年前全球企业在AI领域的投资将达8000亿美元。这促使企业进行战略转型,调整AI应用构建与保护方式。为应对AI创新需求,AI网关概念应运而生,它帮助企业随时随地控制和管理应用流量,提供更高的安全性。AI网关不仅支持多AI模型集成,还提供统一端点、应用程序配置与部署、安全与访问管理等核心功能。面对未来挑战,AI网关需支持模型故障转移、语义缓存等功能,确保AI应用的可靠性和效率。开源项目APIPark.COM为企业提供了一站式AI网关解决方案,简化大型语言模型的调用过程,保障企业数据安全。
208 1

热门文章

最新文章