练手小游戏(代码篇之敌人AI

Posted Sooda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了练手小游戏(代码篇之敌人AI相关的知识,希望对你有一定的参考价值。

诶呀~又没有更新微博,去拔牙了,疼死了,休息了几天过来接着写代码~

首先是Base。写了一个框架,照别人扒的。

Base分三部分,AILocomotion(AI移动),Steering(行为基类),Vehicle(角色模型基类)

首先是Steering

/// <summary>
/// 角色行为基类
/// </summary>
public class Steering : MonoBehaviour {

    /// <summary>
    /// 操控权重
    /// </summary>
    public float weight = 1;
    
    void Start () { 
    
    }
    
    
    void Update () {
    
    }

    /// <summary>
    /// 计算操控力。由子类去实现
    /// </summary>
    /// <returns></returns>
    public virtual Vector3 Force()
    {
        return Vector3.zero;
    }
}

其次是角色行为基类

/// <summary>
/// 角色模型基类
/// </summary>
public class Vehicle : MonoBehaviour {

    /// <summary>
    /// 行为列表
    /// </summary>
    private Steering[] steerings;

    /// <summary>
    /// 操控力
    /// </summary>
    private Vector3 steeringForce;

    /// <summary>
    /// 最大的力
    /// </summary>
    public float maxForce;

    /// <summary>
    /// 角色质量
    /// </summary>
    private float mass = 1; 

    /// <summary>
    /// 加速度
    /// </summary>
    protected Vector3 acceleration;

    /// <summary>
    ///控制力计算间隔时间
    /// </summary>
    private float computeInterval = 0.2f;

    /// <summary>
    /// 计时器
    /// </summary>
    private float timer;

    /// <summary>
    /// 位移速度
    /// </summary>
    public Vector3 speed;
    /// <summary>
    /// 最大速度
    /// </summary>
    public float maxSpeed = 10;
    /// <summary>
    /// 最大速度的平方
    /// </summary>
    public float sqrtMaxSpeed;
    /// <summary>
    /// 转向速度
    /// </summary>
    public float damping = 0.9f;
    /// <summary>
    /// 是否是平面
    /// </summary>
    public bool isPanar = false;


    protected void Start () {
        steeringForce = Vector3.zero;
        timer = 0;
        steerings = GetComponents<Steering>();
        sqrtMaxSpeed = maxSpeed * maxSpeed;
    }

    void Update () { //每过computeInterval的时间就处理一下当前所有行为力的合力
        timer += Time.deltaTime;
        steeringForce = Vector3.zero;

        if (timer > computeInterval)
        {
            foreach (Steering s in steerings)
            {
                if (s.enabled)
                {
                    steeringForce += s.Force() * s.weight;
                }
            }
            steeringForce = Vector3.ClampMagnitude(steeringForce, maxForce);
            acceleration = steeringForce / mass; //加速度 = 力 / 质量
            timer = 0;
        }
    }
}

最后是AI移动类

/// <summary>
/// 角色移动类
/// </summary>
public class AILcomotion : Vehicle {

    /// <summary>
    /// AI角色控制器
    /// </summary>
    private CharacterController mController;
    private Rigidbody mRigidbody;

    /// <summary>
    /// 每次移动的距离
    /// </summary>
    private Vector3 mMoveDistance;

    void Start () {
        mController = GetComponent<CharacterController>();
        mRigidbody = GetComponent<Rigidbody>();
        mMoveDistance = Vector3.zero;
        base.Start();
    }
    
    void FixedUpdate () {
        speed = speed + acceleration * Time.fixedDeltaTime;
        if (speed.sqrMagnitude > sqrtMaxSpeed)
        {
            speed = speed.normalized * maxSpeed; //float 转 Vector3
        }
        //计算角色移动距离
        mMoveDistance = speed * Time.fixedDeltaTime;

        if (isPanar)
        {
            speed.y = 0;
        }
        
        if (mController)
        {
            mController.SimpleMove(speed);
        }
        else if (mRigidbody == null || mRigidbody.isKinematic) //如果Rigidbody为空或受物理影响修改位置
        {
            transform.position += mMoveDistance;
        }
        else
        {
            mRigidbody.MovePosition(mRigidbody.position + mMoveDistance);
        }

        if (speed.sqrMagnitude > 0.0001f)
        {
            Vector3 newForward = Vector3.Slerp(transform.forward, speed, damping * Time.fixedDeltaTime);
            if (isPanar)
            {
                newForward.y = 0;
            }
            transform.forward = newForward;
        }
    }
}

之后就是各个行为的实现比如一个抵达行为

/// <summary>
/// 抵达
/// </summary>
public class Arrive : Steering {

    /// <summary>
    /// 靠近的目标
    /// </summary>
    public GameObject target;

    /// <summary>
    /// 减速半径
    /// </summary>
    public float slowDownDistance;

    /// <summary>
    /// 预期速度
    /// </summary>
    private Vector3 mDesiredVelocity;

    /// <summary>
    /// AI角色
    /// </summary>
    private Vehicle mVehicle;

    void Start()
    {
        mVehicle = GetComponent<Vehicle>();
    }

    public override Vector3 Force()
    {
        //与目标之间的距离
        Vector3 toTarget = target.transform.position - transform.position;
        if (mVehicle.isPanar)
        {
            toTarget.y = 0;
        }

        if (toTarget.magnitude < slowDownDistance)
        {
            //计算预期速度
            mDesiredVelocity = toTarget - mVehicle.speed;
        }
        else
        {
            //计算预期速度
            mDesiredVelocity = toTarget.normalized * mVehicle.maxSpeed;
        }

        if (mVehicle.isPanar)
        {
            mDesiredVelocity.y = 0;
        }
        //返回操控向量
        return (mDesiredVelocity - mVehicle.speed);
    }
}

目前还没有学习行为树的写法,目前就是把各个行为都放到角色上运行,有点臃肿。

以上是关于练手小游戏(代码篇之敌人AI的主要内容,如果未能解决你的问题,请参考以下文章

没有墙壁时的敌人与墙壁的碰撞检测

状态机游戏AI设计

练手小游戏(一个开始

FSM(状态机)HFSM(分层状态机)BT(行为树)的区别

转载pythonpython练手项目

新风口下:嵌入式AI学习中较好的练手项目(附代码资料/学习视频/学习规划)...