这个类直译为“交通工具”包括了很宽泛的能自主移动的AI角色。 操作对象抽象为一个质点,包含位置信息、质量、速度等,速度随着施加力的变化而变化。力与速度都有一个限制,因此还需要最大力、最大速度。还需要一个朝向。 位置计算方法 1.每一帧的力(最大不超过最大力) 2.交通工具的质量,来确定加速度 3.加速度与原速度相加,得到新的速度 4.新的速度与一帧的时间相乘,计算出位移 5.原位置加上位移得到新位置
此类通过获取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;
}
}
}
真正控制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");
}
}
Steering类操控行为的基类,包括操控行为共有的变量和方法,操控AI角色的寻找、逃跑、躲避等都可由此类派生 此类为抽象类,每个子类有定义自己的权重,重写操控力的计算方法
public abstract class Steering : MonoBehaviour {
//操控力的权重
public float weight = 1;
//操控力的计算方法
public virtual Vector3 Force()
{
return new Vector3(0, 0, 0);
}
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有