一、通用的AI架构模型

【与游戏世界的接口】

战略层:群体行为

决策层:个体行为

运动层:移动寻路

【动画系统、物理仿真系统】


二、常用的操纵行为

Seek    靠近

Flee    离开

Arrival    抵达

Pursuit    追逐

Evade    逃避

Wander    随机徘徊

Path Following    路径跟随

Obstacle Avoidance    避开障碍

Group Behavior    组行为

Radar    雷达探测

Separation    分离

Alignment    队列

Cohesion    聚集


三、Unity3d操纵行为主要基类

Vehicle类、AILocomotion类、Steering类


Vehicle类:AI角色抽象成一个质点,包含位置Position、朝向orientation、质量mass、速度velocity等信息。

其他可移动的AI角色都由它派生而来:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//AI角色抽象成一个质点,包含位置Position、朝向orientation、质量mass、速度velocity等信息

public class Vehicle : MonoBehaviour {

    //这个AI角色包含的操控行为列表
    private Steering[] steerings;
    //设置这个AI角色能达到的最大高度
    public float maxSpeed = 10;
    //设置能施加到这个AI角色的力的最大值
    public float maxForce = 100;
    //最大速度的平方,通过预先算出并存储,节省资源
    protected float sqrMaxSpeed;
    //AI角色的质量
    public float mass = 1;
    //AI角色的速度
    public Vector3 velocity;
    //控制转向时的速度;
    public float damping = 0.9f;
    //操纵力的计算间隔时间,为了达到更高的帧率,操纵力不需要每帧更新
    public float computeInterval = 0.2f;
    //是否在二维平面上,如果是,计算两个GameObject的距离时,忽略y值的不同
    public bool isPlanar = true;
    //计算得到的操纵力
    private Vector3 steeringForce;
    //AI角色的加速度
    protected Vector3 acceleration;
    //计时器
    private float timer;


	// Use this for initialization
	protected void Start () {
        steeringForce = new Vector3(0, 0, 0);
        sqrMaxSpeed = maxSpeed * maxSpeed;
        timer = 0;
        steerings = GetComponents<Steering>();
		
	}
	
	// Update is called once per frame
	void Update () {
        timer += Time.deltaTime;
        steeringForce = new Vector3(0, 0, 0);
        //如果距离上次计算操控力的时间大于设定的时间间隔computeInterval;
        //再次计算操控力
        if (timer > computeInterval)
        {
            //将 操纵行为列表 中的 所有操控行为 对应的 操控力 进行带权重的求和
            foreach(Steering s in steerings)
            {
                if (s.enabled)
                    steeringForce += s.Force() * s.weight;
            }
            //使操纵力不大于maxForce
            steeringForce = Vector3.ClampMagnitude(steeringForce, maxForce);
            //力除以质量,求出加速度
            acceleration = steeringForce / mass;
            //重新从0开始计时
            timer = 0;
        }
		
	}
}

AILocomotion类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//Vehicle的派生类,真正控制AI角色的移动

public class AILocomotion : Vehicle {

    //AI角色的角色控制器
    private CharacterController controller;
    //AI角色的Rigidbody
    private Rigidbody theRigidbody;
    //AI角色每次的移动距离
    private Vector3 moveDistance;

	// Use this for initialization
	void Start () {
        //获得角色控制器(如果有的话)
        controller = GetComponent<CharacterController>();
        //获得AI角色的Rigidbody(如果有的话)
        theRigidbody = GetComponent<Rigidbody>();
        moveDistance = new Vector3(0, 0, 0);

        //调用基类的Start()函数,进行所需的初始化
        base.Start();
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}

    //物理相关操作在FixedUpdate()中更新
    private void FixedUpdate()
    {
        //计算速度
        velocity += acceleration * Time.fixedDeltaTime;
        //限制速度,要低于最大速度
        if (velocity.sqrMagnitude > sqrMaxSpeed)
            velocity = velocity.normalized * maxSpeed;
        //计算AI角色的移动距离
        moveDistance = velocity * Time.fixedDeltaTime;
        //如果要求AI角色在平面上移动,那么将y置为0
        if (isPlanar)
        {
            velocity.y = 0;
            moveDistance.y = 0;
        }

        //如果已经为AI角色添加了角色控制器,那么利用角色控制器使其移动
        if (controller != null)
        {
            controller.SimpleMove(velocity);
        }
        //若没有角色控制器,也没有Rigidbody
        //或AI角色拥有Rigidbody,但是要由动力学的方式控制它的移动
        else if (theRigidbody == null || theRigidbody.isKinematic)
            transform.position += moveDistance;
        //用Rigidbody控制AI角色的运动
        else
            theRigidbody.MovePosition(theRigidbody.position + moveDistance);

        //更新朝向,如果速度大于一个阈值(为了防止抖动)
        if (velocity.sqrMagnitude > 0.00001)
        {
            //通过当前朝向与速度方向的插值,计算新的朝向
            Vector3 newForward = Vector3.Slerp(transform.forward, velocity, damping * Time.deltaTime);
            //将Y设置为0;
            if (isPlanar)
                newForward.y = 0;
            //将向前的方向设置为新的朝向
            transform.forward = newForward;
        }

        //播放行走动画
        GetComponent<Animation>().Play("Walk");
    }
}


Steering类


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//Steering类时所有操控行为的基类,寻找、逃跑、追逐、躲避、徘徊、分离、队列、聚集等都可由此派生

public class Steering : MonoBehaviour {
    //表示每个操控力的权重
    public float weight = 1;

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}

    public virtual Vector3 Force()
    {
        return new Vector3(0, 0, 0);
    }
}