zoukankan      html  css  js  c++  java
  • 阶段学习总结-坦克大战案例

    今天学习了一个案例-坦克大战,最终跟着视频做出了一个小demo,学到了许多实际操作,特记录下来,也是复习。

    一.控制移动和旋转

    public class TankMovement : MonoBehaviour
    {
        //移动速度
        public float speed = 5;
        //旋转速度
        public float angularSpeed = 3;
        //刚体组件
        Rigidbody rigidbody;
        //坦克编号,这个脚本用于控制不止一个坦克,但是是从同一个prefab实例化而来,因此通过更改编号使不同按键能控制不同坦克
        public int number = 1;
    
        //闲置发动机音效
        public AudioClip idleAudio;
        //开动坦克发动机音效
        public AudioClip drivingAudio;
    
        private AudioSource audioSource;
        // Start is called before the first frame update
        void Start()
        {
            //获取刚体组件
            rigidbody = GetComponent<Rigidbody>();
            //获取声音源组件
            audioSource = GetComponent<AudioSource>();
        }
    
        // Update is called once per frame
        void Update()
        {
            //获取轴的值
            float h = Input.GetAxis("HorizontalPlayer" + number);
            float v = Input.GetAxis("VerticalPlayer" + number);
            //通过刚体组件给与速度和旋转
            rigidbody.velocity = (transform.forward * v + transform.right * h) * speed;
            rigidbody.angularVelocity = transform.up * h * angularSpeed;
    
            //声音控制,如果物体移动,播放移动发动机声音,否则播放闲置发动机音效
            if(Mathf.Abs(h) > 0.1 || Mathf.Abs(v) > 0.1)
            {
                audioSource.clip = drivingAudio;
                //通过声音源组件的isPlaying()方法判断发动机音效是否已经播放,不做判断的话每一帧都会重新播放音效
                if(audioSource.isPlaying == false)
                    audioSource.Play();
            }
            else
            {
                audioSource.clip = idleAudio;
                if(audioSource.isPlaying == false)
                    audioSource.Play();
            }
        }
    }

    这是一个通过刚体控制物体移动和旋转的脚本,同时能控制声音播放,注意在刚体组件中锁定y轴位置和xz轴旋转,这也是这段脚本的控制方式的缺陷,只能控制平面上物体的运动

    坦克上的刚体组件,可以看到锁定了y轴位置和xz轴旋转

    轴设置,分别添加了player1和player2的轴,可以通过wasd和方向键分别控制两个tank的移动

     

     二.发射炮弹

     同样的,这个脚本同时有控制声音的功能,发射炮弹分为实例化炮弹、赋予炮弹初速度两步,炮弹的方向和发射角度信息通过tank下的一个子物体的位置和方向记录下来

    public class TankAttack : MonoBehaviour
    {
        //炮弹实例
        public GameObject shellPrefab;
        //开火键,为不同的tank可以分别设置不同的开火键
        public KeyCode fireKey = KeyCode.Space;
        //炮弹速度
        public float shellSpeed = 500;
        //炮弹生成位置,这是一个在炮口的空物体,并设置好空物体的旋转,这个物体记录了炮弹的发射方向和角度信息,物体为tank的子物体,始终在炮口处
        private Transform firePosition;
    
        //发射音效
        public AudioClip shootAudio;
        // Start is called before the first frame update
        void Start()
        {
            //获取炮弹生成位置
            firePosition = transform.Find("FirePosition");
        }
    
        // Update is called once per frame
        void Update()
        {
            //当按下发射键时
            if (Input.GetKeyDown(fireKey))
            {
                //生成炮弹
                GameObject go = Instantiate(shellPrefab, firePosition.position, firePosition.rotation);
                //在tank上播放发射音效
                AudioSource.PlayClipAtPoint(shootAudio, transform.position);
                //通过炮弹上的刚体组件赋予炮弹初速度
                go.GetComponent<Rigidbody>().velocity = go.transform.forward * shellSpeed;
            }
        }
    }

    3.炮弹爆炸和销毁

    public class Shell : MonoBehaviour
    {
        //炮弹爆炸特效
        public GameObject shellExplosion;
        //炮弹爆炸音效
        public AudioClip shellExplosionAudio;
        // Start is called before the first frame update
        void Start()
        {
            
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    
        //触发器,这里的碰撞检测采用触发检测
        private void OnTriggerEnter(Collider other)
        {
            //在碰撞位置实例化一个爆炸特效物体,直接播放爆炸特效
            Instantiate(shellExplosion, transform.position, transform.rotation);
            //播放爆炸音效
            AudioSource.PlayClipAtPoint(shellExplosionAudio, transform.position);
            //通过标签检测是否碰撞到的是tank,tank的prefab需要设置好标签
            if(other.tag == "Tank")
            {
                //发送消息给tank上的脚本中的方法,扣除血量
                other.SendMessage("TankDamage");
            }
            //销毁炮弹
            Destroy(this.gameObject);
        }
    }

    这里采用触发检测,避免了碰撞导致的tank有位移等物理效果,需要在炮弹的prefab的collision中将is trigger勾选

     脚本发送了扣血的消息给tank,因此tank上需要再添加扣血的脚本组件

    public class TankHealth : MonoBehaviour
    {
        //坦克血量
        public int hp = 100;
        //坦克爆炸预制件,血量扣完就会发生爆炸
        public GameObject tankExplosion;
        //爆炸音效
        public AudioClip tankExploreAudio;
    
        //总血量,用于计算坦克血量比例
        private int maxHP;
        //用于显示坦克血量的滑动条
        public Slider slider;
        // Start is called before the first frame update
        void Start()
        {
            //初始化最大血量
            maxHP = hp;
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    
        //扣血方法
        void TankDamage()
        {
            //中弹后随机扣除10点以内的血量
            hp -= Random.Range(0, 10);
            //设置滑动条的值,显示剩余血量占比
            slider.value = (float)hp / maxHP;
            //血量扣完
            if(hp <= 0)
            {
                //老三套,实例化爆炸预制件
                Instantiate(tankExplosion, transform.position + Vector3.up, transform.rotation);
                //播放音效
                AudioSource.PlayClipAtPoint(tankExploreAudio,transform.position);
                //销毁当前物体
                Destroy(this.gameObject);
            }
        }
    }

    这里又添加了一个滑动条来显示血量,滑动条及其所在的画布需要设置为tank的子物体以使得滑动条跟随坦克移动

    这里我们发现,坦克和炮弹的爆炸特效物体生成后,播放完效果并未销毁,因此需要在它们的prefab上添加销毁的自制组件

    public class DestroyForTime : MonoBehaviour
    {
        //销毁时间,给与动画播放充足的时间
        public float time = 1.5f;
        // Start is called before the first frame update
        void Start()
        {
            //销毁物体
            Destroy(this.gameObject, time);
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    }
  • 相关阅读:
    margin和pading的百分比值
    Vue中的computed和watch
    JS的自身属性和继承属性
    JS对象的可枚举属性和不可枚举属性
    Dart语言学习
    Practice_Test
    Lesson2 basic python_20200920
    Python 基础语法L1
    小男孩和狗的故事
    智者的故事
  • 原文地址:https://www.cnblogs.com/movin2333/p/14045403.html
Copyright © 2011-2022 走看看