• 练手小游戏(代码篇之敌人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);
        }
    }

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

  • 相关阅读:
    B.Icebound and Sequence
    Educational Codeforces Round 65 (Rated for Div. 2) D. Bicolored RBS
    Educational Codeforces Round 65 (Rated for Div. 2) C. News Distribution
    Educational Codeforces Round 65 (Rated for Div. 2) B. Lost Numbers
    Educational Codeforces Round 65 (Rated for Div. 2) A. Telephone Number
    Codeforces Round #561 (Div. 2) C. A Tale of Two Lands
    Codeforces Round #561 (Div. 2) B. All the Vowels Please
    Codeforces Round #561 (Div. 2) A. Silent Classroom
    HDU-2119-Matrix(最大匹配)
    读书的感想!
  • 原文地址:https://www.cnblogs.com/SHOR/p/5874627.html
Copyright © 2020-2023  润新知