实现AI角色的自主移动-主要基类

基本操作行为

“操作行为”是指操作控制角色,让他们能以模拟真实的方式在游戏世界中移动,它的工作方式是通过产生一定大小和方向的操控力,使角色以某种方式移动。

“操控行为”包括一组基本“行为”。

  1. 对于单独的AI角色,基本的操控行为包括:
    在这里插入图片描述基本行为中的每一个行为,都产生相应的操控力,将这些操控力以一定的方式组合起来,就能得到更复杂的“行为”,从而实现更高级的目标。
  2. 对于组成小队或群体的多个AI角色,包括基本的组行为如下:
    在这里插入图片描述
    无论整个群体中有多少个体,对于每个个体,计算的复杂度都是有限的,通过这种简单的计算,就可以产生逼真的效果,采用这项技术,两个相似的鸟群,即便是飞过相同的路线,它们的行为也是不同的。

Unity3D操控行为编程的主要基类

编程中主要涉及三个主要基类分别是:

  • Vehicle类 主要作用:将AI角色抽象成一个质点,方便进行物理运算。
  • Steering类 主要作用:各种操控行为的基类,包含操控行为共有的变量和方法,由此衍生出各种行为的派生类。
  • LocomotionController类 主要作用:用于挂载在物体上,控制AI角色移动。

Vehicle类

首先对AI角色做出抽象。它包括很宽泛能自主移动的任何AI角色。
在AI架构模型中,操控AI角色的基类Vehicle吧操作的对象抽象为一个质点,它包含位置(position)、质量(mass)、速度(speed)等信息,而速度随着所施加的力的变化而变化,由于速度意味着是实际物理实体,施加在其身上的力和能达到的速度都是有限制的,因此还需要最大力、和最高速度两个信息,除此之外还有包含一个当前力的朝向信息。

using UnityEngine;

namespace AI.Steering
{
    /// <summary>
    /// 运动体类
    /// </summary>
    public class Vehicle:MonoBehaviour
    {
        /// <summary>
        /// 当前操控力:向量
        /// </summary>
        [HideInInspector]
        public Vector3 currentForce;
        /// <summary>
        /// 最终的合力
        /// </summary>
        [HideInInspector]
        public Vector3 finalForce;
        /// <summary>
        /// 当前角色所具有的操控行为类数组
        /// </summary>
        [HideInInspector]
        public Steering[] steerings;
        /// <summary>
        /// 最大速度
        /// </summary>
        public float maxSpeed = 10;
        /// <summary>
        /// 转向速度
        /// </summary>
        public float rotationSpeed = 5;
        /// <summary>
        /// 质量
        /// </summary>
        public float mass = 1;
        /// <summary>
        /// 合力上限
        /// </summary>
        public float maxForce = 100;
        /// <summary>
        /// 操控力的计算间隔时间,为了达到更高的帧率,操控力不需要每帧更新
        /// </summary>
        public float computerInternal = 0.2f;
        /// <summary>
        /// 是否在二维平面上,如果是计算GameObject的距离时,忽略y值的不同
        /// </summary>
        public bool isPlane = false;

        //初始化 得到当前这个AI角色身上所有属于操控行为类的列表
        void Start()
        {
            steerings = GetComponents<Steering>();
        }
        /// <summary>
        /// 计算出实际操控力:把当前所有影响对象力进行计算 求合力
        /// 同时考虑质量等问题  返回最终的实际操控力
        /// </summary>
        public void ComputeFinalForce()
        {
            //每次计算最终合力 让合力归零
            finalForce = Vector3.zero;
            //1 求当前对象的实际操控力 也就是所有对当前对象产生影响的力 计算合力
            for(int i = 0; i < steerings.Length; i++)
            {
                if (steerings[i].enabled)
                {
                    finalForce += steerings[i].GetForce();
                }
            }
            if (finalForce == Vector3.zero)
                currentForce = Vector3.zero;
            //2 是否是平面(忽略y轴影响)
            if (isPlane)
                finalForce.y = 0;
            //把向量限制在一个特定的长度,不超过合力上限
            finalForce = Vector3.ClampMagnitude(finalForce, maxForce);
            //考虑质量最最终合力的影响  合力=合力/质量
            finalForce /= mass;
        }
        //启用方法
        private void OnEnable()
        {
            InvokeRepeating("ComputeFinalForce", 0, computerInternal);
        }
        //结束时取消调用函数
        private void OnDisable()
        {
            CancelInvoke("ComputeFinalForce");
        }
    }
}

Steering类

所有操控类的基类,包含操控类行为共有的变量和方法,操控AI角色的寻找,逃跑…行为都可由此派生。这样我们就可以在Unity3D中的C#脚本中方便的使用上述派生类来编程。

using UnityEngine;

namespace AI.Steering
{
    /// <summary>
    /// 操控类:各种自动运动的 【共性】
    /// </summary>
    abstract public class Steering:MonoBehaviour
    {
        /// <summary>
        /// 期望操控力
        /// </summary>
        [HideInInspector]
        public Vector3 expectForce;
        /// <summary>
        /// 当前的运动对象(抽象为质点)
        /// </summary>
        [HideInInspector]
        public Vehicle vehicle;
        /// <summary>
        /// 目标
        /// </summary>
        /// 通过监视【属性】窗口赋值
        /// 也可以通过代码赋值
        public Transform target;
        /// <summary>
        /// 速度
        /// </summary>
        public float speed = 5;
        /// <summary>
        /// 表示每个操控力的权重
        /// </summary>
        public int weight = 1;
        /// <summary>
        /// 计算各个操控行为对当前物体的影响 实际操控力
        /// </summary>
        abstract public Vector3 GetForce();
        //初始化
        protected void Start()
        {
            vehicle = GetComponent<Vehicle>();
            if(speed == 0) speed = vehicle.maxSpeed;
        }
    }
}

LocomotionController类

LocomotionController类是Vehicle类的派生类,它能真正的控制AI角色的移动,包括计算每次移动距离,播放动画等。

using UnityEngine;

namespace AI.Steering
{
    //实际操控运动
    public class LocomotionController : Vehicle
    {
        //方法需要反复调用 需要持续判断当前运动
        void Update()
        {
            Rotation();
            Movement();
            PlayAnimation();
        }
        /// <summary>
        /// 转向:当前的操控方向
        /// </summary>
        public void Rotation()
        {
            if (currentForce != Vector3.zero)
            {
                //获得当前操控力的方向的值
                var dir = Quaternion.LookRotation(currentForce);
                //(如果不希望角色y轴旋转)固定y轴
                //var dir = Quaternion.LookRotation(new Vector3(currentForce.x,0,currentForce.z));
                //得到插值 圆滑的旋转
                transform.rotation = Quaternion.Lerp(transform.rotation, dir,rotationSpeed * Time.deltaTime);
            }
        }

        /// <summary>
        /// 移动
        /// </summary>
        public void Movement()
        {
            //1 计算出当前操控方向和速度
            currentForce += finalForce * Time.deltaTime;
            currentForce = Vector3.ClampMagnitude(currentForce, maxSpeed);
            //2 移动
            transform.position += currentForce * Time.deltaTime;
            //不希望角色起飞(固定y轴)
            //transform.position += new Vector3((currentForce * Time.deltaTime).x,0, (currentForce * Time.deltaTime).z);
        }
        /// <summary>
        /// 播放动画
        /// </summary>
        public void PlayAnimation(){ }  
    }
}

Unity3D游戏AI架构

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值