Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >游戏AI-实现AI角色的自主移动——操控行为

游戏AI-实现AI角色的自主移动——操控行为

作者头像
祝你万事顺利
发布于 2019-05-28 15:13:27
发布于 2019-05-28 15:13:27
1.3K00
代码可运行
举报
文章被收录于专栏:Unity游戏开发Unity游戏开发
运行总次数:0
代码可运行

Unity操控行为编程的基类:Vehicle类、AILocomotion类和Steering类

1.将AI角色抽象成一个质点——Vehicle类

这个类直译为“交通工具”包括了很宽泛的能自主移动的AI角色。 操作对象抽象为一个质点,包含位置信息、质量、速度等,速度随着施加力的变化而变化。力与速度都有一个限制,因此还需要最大力、最大速度。还需要一个朝向。 位置计算方法 1.每一帧的力(最大不超过最大力) 2.交通工具的质量,来确定加速度 3.加速度与原速度相加,得到新的速度 4.新的速度与一帧的时间相乘,计算出位移 5.原位置加上位移得到新位置

此类通过获取AI角色的操控行为列表,对表中的行为进行带权重的求和,再求得加速度

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Vehicle : MonoBehaviour {

    //操控行为的列表
    private Steering[] steerings;
    //最大速度
    public float maxSpeed = 10f;
    //能施加的最大力
    public float maxForce = 100;
    //最大速度平方
    protected float sqrMaxSpeed;

    public float mass = 1;
    public Vector3 velocity;

    //转向速度
    public float damping = 0.9f;

    //操控力的计算间隔,操控力每隔一段时间进行计算,来提高帧率
    public float computeInterval = 0.2f;

    //是否在平面上
    public bool isPlanar = true;

    //计算得到的操控力
    private Vector3 steeringForce;

    //加速度
    protected Vector3 acceleration;

    private float timer;


    protected void Start () {
        steeringForce = new Vector3(0, 0, 0);
        sqrMaxSpeed = maxSpeed * maxSpeed;
        timer = 0;
        //获得AI角色上的全部操控行为
        steerings = GetComponents<Steering>();
    }


    
    // Update is called once per frame
    void Update () {
        timer += Time.deltaTime;
        steeringForce = new Vector3(0, 0, 0);
        //力量检测时间一定间隔后才重新计算
        if (timer > computeInterval)
        {
            //AI最终被施加的力,就是各个力的权值相乘后的和
            foreach (var item in steerings)
            {
                if (item.enabled)
                {
                    steeringForce += item.Force() * item.weight;
                }
            }
            //ClampMagnitude方法返回一个Vector(maxForce,maxForce,maxForce)与steeringForce中更小的一个
            steeringForce = Vector3.ClampMagnitude(steeringForce, maxForce);
            //F = ma
            acceleration = steeringForce / mass;
            timer = 0;
        }       
    }
}
2.控制AI角色移动——AILocomotion类

真正控制AI角色的移动,计算每次移动的距离播放动画等

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//控制角色移动的类
public class AILocomotion : Vehicle {

    private CharacterController characterController;
    private Rigidbody theRigidbody;
    //每次移动的距离
    private Vector3 moveDistance;

    // Use this for initialization
    void Start () {
        characterController = GetComponent<CharacterController>();
        theRigidbody = GetComponent<Rigidbody>();
        moveDistance = new Vector3(0, 0, 0);
        //调用基类的Start(),对所需进行初始化
        base.Start();
    }

    //物理相关操作在FixedUpdate中进行
    private void FixedUpdate()
    {
        //计算速度
        velocity += acceleration * Time.fixedDeltaTime;
        //限制速度 velocity.sqrMagnitude 即为向量三个值的平方和
        if (velocity.sqrMagnitude > sqrMaxSpeed)
        {
            velocity = velocity.normalized * maxSpeed;
        }
        //计算位移
        moveDistance = velocity * Time.fixedDeltaTime;

        //如果要让AI在平面上移动,将y设置为0;
        if (isPlanar)
        {
            velocity.y = 0;
            moveDistance.y = 0;
        }

        //有角色控制器,直接传速度
        if (characterController != null)
        {
            characterController.SimpleMove(velocity);
        }
        //没有角色控制器和刚体
        //或有刚体但要由动力学方式控制
        else if (theRigidbody == null || theRigidbody.isKinematic)
        {
            transform.position += moveDistance;
        }
        //通过刚体控制
        else
        {
            theRigidbody.MovePosition(theRigidbody.position + moveDistance);
        }
        //更新朝向,如果速度大于一个阈值(防止抖动)
        if(velocity.sqrMagnitude > 0.0001)
        {

            //通过当前朝向和速度方向插值,计算新的朝向
            Vector3 newForward = Vector3.Lerp
                (transform.forward, velocity, damping * Time.fixedDeltaTime);
            //将y值设置为0
            if (isPlanar)
            {
                newForward.y = 0;
            }
            transform.forward = newForward;
        }

        //播放动画
        //gameObject.GetComponent<Animation>().Play("walk");

    }
}
3.各种操控行为的基类——Steering类

Steering类操控行为的基类,包括操控行为共有的变量和方法,操控AI角色的寻找、逃跑、躲避等都可由此类派生 此类为抽象类,每个子类有定义自己的权重,重写操控力的计算方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class Steering : MonoBehaviour {
    //操控力的权重
    public float weight = 1;
    //操控力的计算方法
    public virtual Vector3 Force()
    {
        return new Vector3(0, 0, 0);
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.04.14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
java 设置400错误_Java项目报400错误的原因与解决方法
请求中的语法错误。Reason-Phrase应当标志这个详细的语法错误,比如”Missing Call-ID header field”。
全栈程序员站长
2022/11/09
4.2K0
ajax请求状态码是0_常见错误状态码
会出现这个HTTP请求状态码400,说明这个请求是无效的,并没有进入后台服务器(控制器)里。
全栈程序员站长
2022/11/17
1.1K0
前端面试题-每日练习(4)
所谓的标准模式是指,浏览器按W3C标准解析执行代码;怪异模式则是使用浏览器自己的方式解析执行代码,因为不同浏览器解析执行的方式不一样,所以我们称之为怪异模式。浏览器解析时到底使用标准模式还是怪异模式,与你网页中的DTD声明直接相关,DTD声明定义了标准文档的类型(标准模式解析)文档类型,会使浏览器使用相应的方式加载网页并显示,忽略DTD声明,将使网页进入怪异模式(quirks mode)。
y191024
2023/09/11
1920
前端面试题-每日练习(4)
常见的http状态码信息
常见的http状态码信息 200客户端请求成功 4xx(请求错误、客户端错误) 5xx(服务器错误) 200客户端请求成功 200:客户端请求成功 4xx(请求错误、客户端错误) 400:客户端请求有语法错误,不能被服务器所理解(解决办法传参格式不正确) 400的原因: 前端提交的字段名称或者字段类型和后台的实体类不一样 或者前端提交的参数跟后台需要的参数个数不一致,导致无法封装 前端提交到后台的数据应该是JSON字符串类型,而前端没有将对象转化为字符串类型 解决方法:对照字段名称,类型保证一致
是阿超
2021/12/30
8350
Postman 提交测试的时候提示 Bad Request
首先可以确定的是,你的 API 并没有获得你的请求数据,可以忽略去调试 API,这个问题就是你发送给 API 的数据的问题。
HoneyMoose
2020/11/03
1.9K0
Postman 提交测试的时候提示 Bad Request
json对象与json字符串_字符数组与字符串的区别
有时候在做项目的时候时常将这两个概念弄混淆,尤其是在使用springmvc的时候,后台@RequestBody接受的是一个json格式的字符串,一定是一个字符串。 先介绍一下json对象,首先说到对象的概念,对象的属性是可以用:对象.属性进行调用的。例如:
全栈程序员站长
2022/11/08
2.2K0
java 415_@RequestBody接受参数报415错误「建议收藏」
1) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
全栈程序员站长
2022/09/05
2K0
@RequestBody出现请求415问题
首先之前也遇到过这样的问题,但是稀里糊涂的最后虽然bug修复了,但是不知道是啥原因,今天又遇到了同样的问题。
全栈程序员站长
2022/09/07
1.2K0
接口400错误解析
今天我遇上一个让我很痛心的错误400。对程序员来说,这可能是一个最简单的错误码。因为这个相应并没有进拦截器,更没有进到Controller层。可我在解决这个问题时,质询了很多朋友不解,百度各种方案无效。苦苦耗费我大半天时间。
全栈程序员站长
2022/07/01
4.7K0
接口400错误解析
post请求包含哪些参数(请求方式post和get)
1)、HTTP 协议是以 ASCII 码 传输,建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为三个部分:状态行、请求头、消息主体。 2)、协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须 使用什么编码方式 。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。 3)、数据发送出去,还要服务端解析成功才有意义。一般服务端语言如 php、python 等,以及它们的 framework,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。
全栈程序员站长
2022/07/29
4.4K0
@RequestBody报400分析与解决方案
spring目前来说是java最好的框架,springmvc是其中一个子集, java web开发过程中使用springmvc来实现前端页面或者其他 客户端与后台服务层打交道,目前来说http请求最常用的就是 get和post请求,参数格式也不尽相同,有最原始的请求参数带 在url中,包括后边发展而来的表单提交,以及目前比较流行的 前后端分离使用的json格式参数做数据交互。今天就工作中 遇到的json格式的数据交互问题作出分析和解决方案. 背景 由于刚到新公司时间不太长,难免会接受别人写的 不规范的代码和
叔牙
2020/11/19
2.4K0
关于Json 与 Request Header 的Content-Type 一些关系。
由于最近遇到关于ashx文件ajax解析参数的问题。查询网上很多资料后,已经解决。
全栈程序员站长
2022/09/28
1.5K0
关于Json 与 Request Header 的Content-Type 一些关系。
@RequestBody的使用[通俗易懂]
提示:建议一定要看后面的@RequestBody的核心逻辑源码以及六个重要结论!本文前半部分的内容都是一些基 本知识常识,可选择性跳过。
全栈程序员站长
2022/08/10
12K0
@RequestBody的使用[通俗易懂]
Ajax教程_ajax是服务器端动态网页技术
Ajax是一种异步请求数据的web开发技术,目前主要用于异步,大家都知道,浏览器主线程是单线程的,也就是一次只能干一件事,以Ajax就是让浏览器当主线程完成后去干别的事情,比如发送请求,加载接口数据等等.这个技术通过XMLHttpRequest对象实现,具体的机制大家可以参考浏览器的时间环机制.
全栈程序员站长
2022/09/20
1.5K0
String和JSON互转,String生成JSONObject和JSONArray[通俗易懂]
这个JSON.parse()与eval()都可以实现,但是它们是有区别的: JSON.parse对json字符串要求比eval()更为严格,key名称(例如name)全部必须有双引号。 而eval必须用括号将json字符串括起来才能成功转换,key名称(例如name)有无双引号都可以成功转化。
全栈程序员站长
2022/09/22
1.2K0
java字符串转换为json对象6_Json对象与Json字符串的转化、JSON字符串与Java对象的转换…
$.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符串转换成json对象
全栈程序员站长
2022/11/08
2.7K0
js如何将json字符串转成json对象_前端json字符串转json对象
JSON字符串: var str1 = ‘{ “name”: “cxh”, “sex”: “man” }’; JSON对象: var str2 = { “name”: “cxh”, “sex”: “man” };
全栈程序员站长
2022/11/08
10.8K0
ajax中回调的几个坑
在前端开发中,经常要用ajax去拿后台接口返回的数据,总结几个ajax的回调的常见问题,供大家参考爬坑。
全栈程序员站长
2022/07/21
9730
POST、GET、@RequestBody和@RequestParam区别[通俗易懂]
注解@RequestParam接收的参数是来自HTTP请求体或请求url的QueryString中。
全栈程序员站长
2022/08/11
5.4K0
POST、GET、@RequestBody和@RequestParam区别[通俗易懂]
适用于JavaScript和Node.js的JSON初学者教程
在本教程中,您将学习什么是JSON以及如何在JavaScript和Node.js中使用它。
海拥
2021/08/23
2.9K0
适用于JavaScript和Node.js的JSON初学者教程
推荐阅读
相关推荐
java 设置400错误_Java项目报400错误的原因与解决方法
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验