AI运动层的一套基于加速度的基本移动方案

来源:互联网 发布:sony walkman mac 编辑:程序博客网 时间:2024/06/05 00:57


移动组件:

using UnityEngine;using System.Collections;using System.Collections.Generic;public class MoveComponent : MonoBehaviour{    #region 字段    public float maxSpeed = 10;                                                               // 最大速度    public float maxForce = 100;                                                              // 最大推力    public float mass = 1;                                                                    // 对象质量    public Vector3 velocity;                                                                  // 速度向量    public float damping = 0.9f;                                                              // 旋转速率    public float computeInteval = 0.2f;                                                       // 计算间隔    public float completeDisatnce = 3f;                                                       // 到达距离    private Vector3 acceleration;                                                             // 加速度    private float timer = 0;                                                                  // 计时器    private Vector3 steeringForce = Vector3.zero;                                             // 推力    private Dictionary<MoveType, MoveBase> moveDic = new Dictionary<MoveType, MoveBase>();    // 移动字典    public List<MoveType> arriveRemove = new List<MoveType>();                                // 移动完成需要删除的移动    #endregion    void Awake()    {        moveDic[MoveType.Seek] = null;        moveDic[MoveType.Arrive] = null;        moveDic[MoveType.Flee] = null;        moveDic[MoveType.FollowPath] = null;        moveDic[MoveType.Pursuit] = null;        moveDic[MoveType.CollisionAvoidance] = null;    }    void Update()    {        timer += Time.deltaTime;        if(timer > computeInteval)        {            //得到当前帧的推力            steeringForce = Vector3.zero;            //遍历当前激活的移动并添加推力*权重            foreach(var v in moveDic)            {                if(v.Value != null)                {                    steeringForce += v.Value.Force() * v.Value.Weight;                }            }            //移除完成的移动            foreach (var v in arriveRemove)            {                moveDic[v] = null;            }            arriveRemove.Clear();            //限制最大力            steeringForce = Vector3.ClampMagnitude(steeringForce, maxForce);            //加速度=推力/质量            acceleration = steeringForce / mass;            timer = 0;        }    }    void FixedUpdate()    {        //增加加速度        velocity += acceleration * Time.fixedDeltaTime;        //控制最大速度        if (velocity.sqrMagnitude > maxSpeed * maxSpeed)            velocity = velocity.normalized * maxSpeed;        //移动        transform.position += velocity * Time.fixedDeltaTime;        //插值旋转        if(velocity.sqrMagnitude > 0.01f)        {            //计算当前前方到目标方向的插值            Vector3 newForward = Vector3.Slerp(transform.forward, velocity, damping * Time.fixedDeltaTime);            transform.forward = newForward;        }    }    #region 接口    public void SeekTo(Transform target)    {        if(moveDic[MoveType.Seek] != null)        {            if ((moveDic[MoveType.Seek] as MoveSeek).target == target)                return;        }        moveDic[MoveType.Seek] = new MoveSeek(this, target);    }    public void ArriveTo(Transform target, float slowDistance)    {        if (moveDic[MoveType.Arrive] != null)        {            if ((moveDic[MoveType.Arrive] as MoveArrive).target == target)                return;        }        moveDic[MoveType.Arrive] = new MoveArrive(this, target, slowDistance);    }    public void FleeTo(Transform target,float fearDistance)    {        if (moveDic[MoveType.Flee] != null)        {            if ((moveDic[MoveType.Flee] as MoveFlee).target == target)                return;        }        moveDic[MoveType.Flee] = new MoveFlee(this, target, fearDistance);    }    public void PursuitTo(Transform target)    {        if(moveDic[MoveType.Pursuit] != null)        {            if ((moveDic[MoveType.Pursuit] as MovePursuit).target == target)                return;        }        moveDic[MoveType.Pursuit] = new MovePursuit(this, target);    }    public void FollowPath(List<Transform> path)    {        if(moveDic[MoveType.FollowPath] != null)        {            if ((moveDic[MoveType.FollowPath] as MoveFllowPath).path == path)                return;        }        moveDic[MoveType.FollowPath] = new MoveFllowPath(this, path);    }    public void OpenCollisionAvoidance(float seeAheadDistance)    {        moveDic[MoveType.CollisionAvoidance] = new MoveCollisionAvoidance(this, seeAheadDistance);    }    #endregion}public enum MoveType{    Seek,    Arrive,    Flee,    Pursuit,    FollowPath,    CollisionAvoidance}



移动方式基类:

using UnityEngine;using System.Collections;public class MoveBase  {    public float Weight = 1;                 //移动优先级    protected Vector3 disiredVelocity;       //目标速度    protected MoveComponent move;            //移动脚本    public MoveBase(MoveComponent move)    {        this.move = move;    }    public virtual Vector3 Force()    {        return Vector3.zero;    }}


靠近:

using UnityEngine;using System.Collections;public class MoveSeek : MoveBase {    public Transform target;    public MoveSeek(MoveComponent move, Transform target) : base(move) { this.target = target; }     public override Vector3 Force()    {        //完成目标移除        if (Vector3.Distance(target.transform.position, move.transform.position) < move.completeDisatnce)        {            move.arriveRemove.Add(MoveType.Seek);            move.velocity = Vector3.zero;            return Vector3.zero;        }        //要到达的速度        disiredVelocity = (target.transform.position - move.transform.position).normalized * move.maxSpeed;        //加速度:当速度=要到达的速度,加速度为0        return disiredVelocity - move.velocity;    }}


缓速到达:

using UnityEngine;using System.Collections;public class MoveArrive : MoveBase {    public Transform target;    //减速范围    float slowDistance;    public MoveArrive(MoveComponent move, Transform target, float slowDistance) : base(move) { this.target = target; this.slowDistance = slowDistance; }    public override Vector3 Force()    {        if (Vector3.Distance(target.transform.position, move.transform.position) > move.completeDisatnce)        {            Vector3 toTarget = target.transform.position - move.transform.position;            Vector3 returnForce;            float distance = toTarget.magnitude;            if (distance > slowDistance)            {                //目标速度                disiredVelocity = toTarget * move.maxSpeed;                //加速度:当速度=要到达的速度,加速度为0                returnForce = disiredVelocity - move.velocity;            }            else            {                //当进入减速范围时 目标速度 = 长度向量-速度向量 逐渐缩小                disiredVelocity = toTarget - move.velocity;                returnForce = disiredVelocity - move.velocity;            }            return returnForce;        }        else        {            //完成目标移除            move.arriveRemove.Add(MoveType.Arrive);            move.velocity = Vector3.zero;            return Vector3.zero;        }    }}


逃离:

using UnityEngine;using System.Collections;public class MoveFlee : MoveBase {    public Transform target;    float fearDistance;    public MoveFlee(MoveComponent move, Transform target, float fearDistance) : base(move) { this.target = target; this.fearDistance = fearDistance; }    public override Vector3 Force()    {        if(Vector3.Distance(move.transform.position,target.position) > fearDistance)        {            //完成目标移除            move.arriveRemove.Add(MoveType.Flee);            move.velocity = Vector3.zero;            return Vector3.zero;        }        //反方向加速度向量        disiredVelocity = (move.transform.position - target.position).normalized * move.maxSpeed;        return disiredVelocity - move.velocity;    }}


路径移动:

using UnityEngine;using System.Collections;using System.Collections.Generic;public class MoveFllowPath : MoveBase {    public List<Transform> path = new List<Transform>();    private float slowDistance = 5f;    private Transform target;    private int index = 0;    public MoveFllowPath(MoveComponent move, List<Transform> path) : base(move) { this.path = path; target = path[index]; }    public override Vector3 Force()    {        Vector3 returnForce = Vector3.zero;        Vector3 distance = target.position - move.transform.position;        //最后一点        if (index == path.Count - 1)        {            if (Vector3.Distance(target.position, move.transform.position) < move.completeDisatnce)            {                //完成目标移除                move.arriveRemove.Add(MoveType.FollowPath);                move.velocity = Vector3.zero;                return Vector3.zero;            }            if (distance.magnitude > slowDistance)            {                disiredVelocity = distance.normalized * move.maxSpeed;            }            else            {                disiredVelocity = distance - move.velocity;            }            returnForce = disiredVelocity - move.velocity;        }        else        {            if(Vector3.Distance(target.position,move.transform.position) < move.completeDisatnce)            {                index++;                target = path[index].transform;            }            disiredVelocity = distance.normalized * move.maxSpeed;            returnForce = disiredVelocity - move.velocity;        }        return returnForce;    }}


拦截:

using UnityEngine;using System.Collections;public class MovePursuit : MoveBase {    public Transform target;    public MovePursuit(MoveComponent move, Transform target) : base(move) { this.target = target; }    public override Vector3 Force()    {        if(target.GetComponent<MoveComponent>()==null)        {            move.arriveRemove.Add(MoveType.Pursuit);            return Vector3.zero;        }        if (Vector3.Distance(target.transform.position, move.transform.position) > move.completeDisatnce)        {            Vector3 toTarget = target.transform.position - move.transform.position;            //两个对象的前方向量夹角            float relativeDirection = Vector3.Dot(move.transform.forward, target.transform.forward);            //追踪向量和对象前方向量的夹角>0并且两个对象前方夹角<18            if(Vector3.Dot(toTarget,move.transform.forward) > 0 && relativeDirection < -0.95f)            {                //差不多在一直线上                disiredVelocity = (target.transform.position - move.transform.position).normalized * move.maxSpeed;                return disiredVelocity - move.velocity;            }            //预期到达目标的前方位置的时间            float lookheadTime = toTarget.magnitude / (move.maxSpeed + target.GetComponent<MoveComponent>().velocity.magnitude);            //预期目标位置 = 目标位置 + 目标速度*预期到达时间            disiredVelocity = (target.transform.position + target.GetComponent<MoveComponent>().velocity * lookheadTime - move.transform.position).normalized * move.maxSpeed;            return disiredVelocity - move.velocity;        }        else        {            //完成目标移除            move.arriveRemove.Add(MoveType.Pursuit);            move.velocity = Vector3.zero;            return Vector3.zero;        }    }}


避障:

using UnityEngine;using System.Collections;public class MoveCollisionAvoidance : MoveBase {    private float maxSeeAhead = 2.0f;    public MoveCollisionAvoidance(MoveComponent move, float maxSeeAhead) : base(move) { this.maxSeeAhead = maxSeeAhead;  }    public override Vector3 Force()    {        RaycastHit hit;        Vector3 returnForce = Vector3.zero;        //方向:速度向量 距离:视线 * 时间        if(Physics.Raycast(move.transform.position,move.velocity,out hit,maxSeeAhead * move.velocity.magnitude /move.maxSpeed))        {            //发生碰撞的视线前方向量            Vector3 ahead = move.transform.position + move.velocity * maxSeeAhead * (move.velocity.magnitude /move.maxSpeed);            //用视线向量-碰撞物体的中心点 得到 碰撞物体中心指向视线向量的向量 用这个向量来偏移            returnForce = ahead - hit.collider.transform.position;            returnForce *= move.maxForce;            returnForce.y = 0;        }        return returnForce;    }}




0 0