zoukankan      html  css  js  c++  java
  • 练手小游戏(代码篇之敌人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);
        }
    }

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

  • 相关阅读:
    不定长内存池之apr_pool
    FFmpeg介绍及参数详细说明
    Linux下ffmpeg安装与开发配置
    基于Live555,ffmpeg的RTSP播放器直播与点播
    ffmpeg开发指南
    boost::bind的使用方法
    开启Linux VNC远程桌面
    Fedora 启动 SSH服务
    Linux中查看进程及杀死进程命令
    __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )
  • 原文地址:https://www.cnblogs.com/SHOR/p/5874627.html
Copyright © 2011-2022 走看看