• Survival Shooter 学习


    using UnityEngine;
    using System.Collections;
    
    namespace CompleteProject
    {
        /// <summary>
        /// 摄像机跟随
        /// </summary>
        public class CameraFollow : MonoBehaviour
        {
            /// <summary>
            /// 摄像机跟随的目标
            /// </summary>
            public Transform target;            
            /// <summary>
            /// 相机的移动速度
            /// </summary>
            public float smoothing = 5f;        
    
            /// <summary>
            /// 摄像机相对于目标的偏移
            /// </summary>
            Vector3 offset;                     
    
    
            void Start ()
            {
                //计算偏移
                offset = transform.position - target.position;
            }
    
    
            void FixedUpdate ()
            {
                //计算相机要移动到的位置
                Vector3 targetCamPos = target.position + offset;
    
                //移动相机
                transform.position = Vector3.Lerp (transform.position, targetCamPos, smoothing * Time.deltaTime);
            }
        }
    }
    CameraFollow
    using UnityEngine;
    
    namespace CompleteProject
    {
        /// <summary>
        /// 敌人管理
        /// </summary>
        public class EnemyManager : MonoBehaviour
        {
            /// <summary>
            /// 玩家生命
            /// </summary>
            public PlayerHealth playerHealth;       
            /// <summary>
            /// 敌人预设
            /// </summary>
            public GameObject enemy;                
            /// <summary>
            /// 每次孵化敌人的间隔
            /// </summary>
            public float spawnTime = 3f;            
            /// <summary>
            /// 孵化敌人的位置
            /// </summary>
            public Transform[] spawnPoints;          
    
    
            void Start ()
            {
                InvokeRepeating ("Spawn", spawnTime, spawnTime);
            }
    
            /// <summary>
            /// 孵化敌人
            /// </summary>
            void Spawn ()
            {
                //如果玩家当前生命<=0,不处理
                if(playerHealth.currentHealth <= 0f)
                {
                    return;
                }
    
                //随机找一个孵化点
                int spawnPointIndex = Random.Range (0, spawnPoints.Length);
    
                //在这个孵化点孵化敌人
                Instantiate (enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
            }
        }
    }
    EnemyManager
    using UnityEngine;
    using System.Collections;
    
    namespace CompleteProject
    {
        /// <summary>
        /// 玩家攻击
        /// </summary>
        public class EnemyAttack : MonoBehaviour
        {
            /// <summary>
            /// 每次攻击的时间间隔
            /// </summary>
            public float timeBetweenAttacks = 0.5f;     
            /// <summary>
            /// 每次攻击照成的伤害
            /// </summary>
            public int attackDamage = 10;               
    
            /// <summary>
            /// 敌人Animator
            /// </summary>
            Animator anim;                              
            /// <summary>
            /// 玩家
            /// </summary>
            GameObject player;                          
            /// <summary>
            /// 玩家生命
            /// </summary>
            PlayerHealth playerHealth;                  
            /// <summary>
            /// 敌人生命
            /// </summary>
            EnemyHealth enemyHealth;                    
            /// <summary>
            /// 玩家是否在攻击范围内
            /// </summary>
            bool playerInRange;                         
            /// <summary>
            /// 下次攻击的计时器
            /// </summary>
            float timer;                                                            
    
    
            void Awake ()
            {
                player = GameObject.FindGameObjectWithTag ("Player");
                playerHealth = player.GetComponent <PlayerHealth> ();
                enemyHealth = GetComponent<EnemyHealth>();
                anim = GetComponent <Animator> ();
            }
    
    
            void OnTriggerEnter (Collider other)
            {
                //如果碰到玩家
                if(other.gameObject == player)
                {
                    //设置标志位为true
                    playerInRange = true;
                }
            }
    
    
            void OnTriggerExit (Collider other)
            {
                //如果玩家离开
                if(other.gameObject == player)
                {
                    //设置标志位为false
                    playerInRange = false;
                }
            }
    
    
            void Update ()
            {
                //每帧增加计时器的时间
                timer += Time.deltaTime;
    
                //当计时器的时间大于等于每次攻击的时间间隔
                //玩家在攻击范围内
                //敌人的当前血量大于0
                if(timer >= timeBetweenAttacks && playerInRange && enemyHealth.currentHealth > 0)
                {
                    //攻击
                    Attack ();
                }
    
                //如果玩家的生命值小于等于0
                if(playerHealth.currentHealth <= 0)
                {
                    //animator触发PlayerDead动画
                    anim.SetTrigger ("PlayerDead");
                }
            }
    
            /// <summary>
            /// 攻击
            /// </summary>
            void Attack ()
            {
                //重置攻击计时器
                timer = 0f;
    
                //如果玩家当前生命大于0
                if(playerHealth.currentHealth > 0)
                {
                    //伤害玩家
                    playerHealth.TakeDamage (attackDamage);
                }
            }
        }
    }
    EnemyAttack
    using UnityEngine;
    
    namespace CompleteProject
    {
        public class EnemyHealth : MonoBehaviour
        {
            /// <summary>
            /// 敌人初始生命
            /// </summary>
            public int startingHealth = 100;            
            /// <summary>
            /// 敌人当前生命
            /// </summary>
            public int currentHealth;                   
            /// <summary>
            /// 敌人死亡后下沉的速度
            /// </summary>
            public float sinkSpeed = 2.5f;              
            /// <summary>
            /// 被玩家击杀时,玩家获得的得分
            /// </summary>
            public int scoreValue = 10;                 
            /// <summary>
            /// 死亡声音
            /// </summary>
            public AudioClip deathClip;                 
    
    
            Animator anim;                              
            AudioSource enemyAudio;                     
            /// <summary>
            /// 敌人受到伤害时的粒子系统
            /// </summary>
            ParticleSystem hitParticles;                
            CapsuleCollider capsuleCollider;            
            /// <summary>
            /// 敌人是否死亡
            /// </summary>
            bool isDead;                                
            /// <summary>
            /// 敌人是否下沉
            /// </summary>
            bool isSinking;                                            
    
    
            void Awake ()
            {
    
                anim = GetComponent <Animator> ();
                enemyAudio = GetComponent <AudioSource> ();
                hitParticles = GetComponentInChildren <ParticleSystem> ();
                capsuleCollider = GetComponent <CapsuleCollider> ();
    
                //设置当前生命为初始生命
                currentHealth = startingHealth;
            }
    
    
            void Update ()
            {
                //如果敌人在下沉
                if(isSinking)
                {
                    //移动敌人在y轴的位置
                    transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime);
                }
            }
            
            /// <summary>
            /// 受到伤害
            /// </summary>
            /// <param name="amount">伤害数值</param>
            /// <param name="hitPoint">受到伤害的位置</param>
    
            public void TakeDamage (int amount, Vector3 hitPoint)
            {
                //如果敌人死亡,不处理
                if(isDead)
                    return;
    
                //播放受伤声音
                enemyAudio.Play ();
    
                //减少当前血量
                currentHealth -= amount;
                
                //将受伤的粒子系统的位置设置为受到伤害的位置
                hitParticles.transform.position = hitPoint;
    
                //播放粒子系统
                hitParticles.Play();
    
                //如果当前血量<=0
                if(currentHealth <= 0)
                {
                    //调用死亡函数
                    Death ();
                }
            }
    
            /// <summary>
            /// 死亡
            /// </summary>
            void Death ()
            {
                //修改死亡标志位
                isDead = true;
    
               //将碰撞器改为触发器
                capsuleCollider.isTrigger = true;
    
                //触发animator的dead动画
                anim.SetTrigger ("Dead");
                
                //播放敌人死亡声音
                enemyAudio.clip = deathClip;
                enemyAudio.Play ();
            }
    
            /// <summary>
            /// 敌人开始下沉
            /// </summary>
            public void StartSinking ()
            {
                //关闭NavMeshAgent
                GetComponent <NavMeshAgent> ().enabled = false;
    
                //将Rigidbody设置为kinematic
                GetComponent <Rigidbody> ().isKinematic = true;
    
                //将下沉标志位设置为true
                isSinking = true;
    
                //添加玩家的得分
                ScoreManager.score += scoreValue;
    
                //销毁敌人
                Destroy (gameObject, 2f);
            }
        }
    }
    EnemyHealth
    using UnityEngine;
    using System.Collections;
    
    namespace CompleteProject
    {
        /// <summary>
        /// 敌人移动
        /// </summary>
        public class EnemyMovement : MonoBehaviour
        {
            /// <summary>
            /// 玩家的位置
            /// </summary>
            Transform player;               
            /// <summary>
            /// 玩家的生命
            /// </summary>
            PlayerHealth playerHealth;      
            /// <summary>
            /// 敌人生命
            /// </summary>
            EnemyHealth enemyHealth;        
            /// <summary>
            /// NavMeshAgent
            /// </summary>
            NavMeshAgent nav;                   
    
    
            void Awake ()
            {
                player = GameObject.FindGameObjectWithTag ("Player").transform;
                playerHealth = player.GetComponent <PlayerHealth> ();
                enemyHealth = GetComponent <EnemyHealth> ();
                nav = GetComponent <NavMeshAgent> ();
            }
    
    
            void Update ()
            {
                //如果敌人生命和玩家生命都大于0
                if(enemyHealth.currentHealth > 0 && playerHealth.currentHealth > 0)
                {
                    //敌人移动到玩家位置
                    nav.SetDestination (player.position);
                }
                //否则关闭NavMeshAgent
                else
                {
                    nav.enabled = false;
                }
            }
        }
    }
    EnemyMovement
    using UnityEngine;
    using UnityEngine.UI;
    using System.Collections;
    using UnityEngine.SceneManagement;
    
    namespace CompleteProject
    {
        /// <summary>
        /// 玩家生命
        /// </summary>
        public class PlayerHealth : MonoBehaviour
        {
            /// <summary>
            /// 游戏开始时玩家的生命
            /// </summary>
            public int startingHealth = 100;                          
            /// <summary>
            /// 玩家的当前生命
            /// </summary>
            public int currentHealth;                                  
            /// <summary>
            /// 生命滑动条
            /// </summary>
            public Slider healthSlider;                                
            /// <summary>
            /// 玩家受到伤害时的图片
            /// </summary>
            public Image damageImage;                                  
            /// <summary>
            /// 玩家死亡的声音剪辑
            /// </summary>
            public AudioClip deathClip;                                
            /// <summary>
            /// 伤害图片变透明的速度
            /// </summary>
            public float flashSpeed = 5f;                              
            /// <summary>
            /// 伤害图片的颜色
            /// </summary>
            public Color flashColour = new Color(1f, 0f, 0f, 0.1f);        
    
            Animator anim;                          
            AudioSource playerAudio;                                  
            PlayerMovement playerMovement;                            
            PlayerShooting playerShooting;
    
            /// <summary>
            /// 玩家是否死亡
            /// </summary>                               
            bool isDead;
            /// <summary>
            /// 玩家是否受到伤害
            /// </summary>                                                
            bool damaged;                                                    
    
    
            void Awake ()
            {
    
                anim = GetComponent <Animator> ();
                playerAudio = GetComponent <AudioSource> ();
                playerMovement = GetComponent <PlayerMovement> ();
                playerShooting = GetComponentInChildren <PlayerShooting> ();
    
                //设置当前血量为起始血量
                currentHealth = startingHealth;
            }
    
    
            void Update ()
            {
                //如果玩家受到伤害,修改伤害图片的颜色
                if(damaged)
                {
                    damageImage.color = flashColour;
                }
                //没有受到伤害,伤害图片渐隐
                else
                {
                    damageImage.color = Color.Lerp (damageImage.color, Color.clear, flashSpeed * Time.deltaTime);
                }
    
                //设置伤害标志位false
                damaged = false;
            }
    
            /// <summary>
            /// 玩家受到伤害
            /// </summary>
            /// <param name="amount">受到伤害的数值</param>
            public void TakeDamage (int amount)
            {
                //设置伤害标志位true
                damaged = true;
    
                //减少当前血量
                currentHealth -= amount;
    
                //将当前血量应用到血量滑动条上
                healthSlider.value = currentHealth;
    
                //播放受伤的声音
                playerAudio.Play ();
    
                //如果当前血量<=0并且玩家死亡的标志位位true.
                if(currentHealth <= 0 && !isDead)
                {
                    Death ();
                }
            }
    
            /// <summary>
            /// 玩家死亡
            /// </summary>
            void Death ()
            {
                //修改死亡标志位
                isDead = true;
    
                //关闭射击特效
                playerShooting.DisableEffects ();
    
                //触发死亡动画
                anim.SetTrigger ("Die");
    
                //播放死亡声音
                playerAudio.clip = deathClip;
                playerAudio.Play ();
    
                //关闭移动和射击脚本
                playerMovement.enabled = false;
                playerShooting.enabled = false;
            }
    
            /// <summary>
            /// 重新开始
            /// </summary>
            public void RestartLevel ()
            {
                //加载场景
                SceneManager.LoadScene (0);
            }
        }
    }
    PlayerHealth
    using UnityEngine;
    using UnitySampleAssets.CrossPlatformInput;
    
    namespace CompleteProject
    {
        /// <summary>
        /// 玩家移动
        /// </summary>
        public class PlayerMovement : MonoBehaviour
        {
            /// <summary>
            /// 玩家移动速度
            /// </summary>
            public float speed = 6f;            
    
            /// <summary>
            /// 玩家移动方向
            /// </summary>
            Vector3 movement;                   
            /// <summary>
            /// Animator
            /// </summary>
            Animator anim;                      
            /// <summary>
            /// Rigidbody
            /// </summary>
            Rigidbody playerRigidbody;          
    
    #if !MOBILE_INPUT
            /// <summary>
            /// 地面
            /// </summary>
            int floorMask;                      
            /// <summary>
            /// 射线的长度
            /// </summary>
            float camRayLength = 100f;                                    
    #endif
    
            void Awake ()
            {
    #if !MOBILE_INPUT
    
                floorMask = LayerMask.GetMask ("Floor");
    #endif
    
                anim = GetComponent <Animator> ();
                playerRigidbody = GetComponent <Rigidbody> ();
            }
    
    
            void FixedUpdate ()
            {
                //获取水平和垂直的输入
                float h = CrossPlatformInputManager.GetAxisRaw("Horizontal");
                float v = CrossPlatformInputManager.GetAxisRaw("Vertical");
    
                //处理玩家的移动
                Move (h, v);
    
                //处理玩家的旋转
                Turning ();
    
                //处理玩家的动画
                Animating (h, v);
            }
    
            /// <summary>
            /// 移动
            /// </summary>
            /// <param name="h"></param>
            /// <param name="v"></param>
            void Move (float h, float v)
            {
                movement.Set (h, 0f, v);
                
                //设置移动速度
                movement = movement.normalized * speed * Time.deltaTime;
    
                //刚体移动
                playerRigidbody.MovePosition (transform.position + movement);
            }
    
            /// <summary>
            /// 旋转
            /// </summary>
            void Turning ()
            {
    #if !MOBILE_INPUT
                //从鼠标点击的屏幕位置创建射线
                Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);
    
                //接收射线撞击到地面的数据
                RaycastHit floorHit;
    
                //发射射线
                if(Physics.Raycast (camRay, out floorHit, camRayLength, floorMask))
                {
                    //创建一个玩家到撞击点的向量
                    Vector3 playerToMouse = floorHit.point - transform.position;
    
                    //保证这个向量的y为0
                    playerToMouse.y = 0f;
    
                    //根据这个向量创建四元数
                    Quaternion newRotatation = Quaternion.LookRotation (playerToMouse);
    
                    //刚体旋转
                    playerRigidbody.MoveRotation (newRotatation);
                }
    #else
    
                Vector3 turnDir = new Vector3(CrossPlatformInputManager.GetAxisRaw("Mouse X") , 0f , CrossPlatformInputManager.GetAxisRaw("Mouse Y"));
    
                if (turnDir != Vector3.zero)
                {
                    Vector3 playerToMouse = (transform.position + turnDir) - transform.position;
    
                    playerToMouse.y = 0f;
    
                    Quaternion newRotatation = Quaternion.LookRotation(playerToMouse);
    
                    playerRigidbody.MoveRotation(newRotatation);
                }
    #endif
            }
    
            /// <summary>
            /// 播放动画
            /// </summary>
            /// <param name="h">水平输入值</param>
            /// <param name="v">垂直输入值</param>
            void Animating (float h, float v)
            {
                bool walking = h != 0f || v != 0f;
    
                anim.SetBool ("IsWalking", walking);
            }
        }
    }
    PlayerMovement
    using UnityEngine;
    using UnitySampleAssets.CrossPlatformInput;
    
    namespace CompleteProject
    {
        /// <summary>
        /// 玩家射击
        /// </summary>
        public class PlayerShooting : MonoBehaviour
        {
            /// <summary>
            /// 没发子弹造成的伤害
            /// </summary>
            public int damagePerShot = 20;                  
            /// <summary>
            /// 每发子弹的时间间隔
            /// </summary>
            public float timeBetweenBullets = 0.15f;        
            /// <summary>
            /// 射击范围
            /// </summary>
            public float range = 100f;                      
    
            /// <summary>
            /// 发射子弹的计时器
            /// </summary>
            float timer;                                    
            /// <summary>
            /// 射击射线
            /// </summary>
            Ray shootRay;                                   
            /// <summary>
            /// 射击击中点
            /// </summary>
            RaycastHit shootHit;                            
            /// <summary>
            /// 可以受到射击的层
            /// </summary>
            int shootableMask;                              
            /// <summary>
            /// 
            /// </summary>
            ParticleSystem gunParticles;                    
            /// <summary>
            /// 枪的线条渲染器
            /// </summary>
            LineRenderer gunLine;                           
            /// <summary>
            /// 枪的声音
            /// </summary>
            AudioSource gunAudio;                           
            /// <summary>
            /// 枪的灯光
            /// </summary>
            Light gunLight;                                 
            /// <summary>
            /// 
            /// </summary>
            public Light faceLight;                            
            /// <summary>
            /// 效果的显示时间
            /// </summary>
            float effectsDisplayTime = 0.2f;                                                                                                                 
    
    
            void Awake ()
            {
                //获取可以射击的层
                shootableMask = LayerMask.GetMask ("Shootable");
    
                gunParticles = GetComponent<ParticleSystem> ();
                gunLine = GetComponent <LineRenderer> ();
                gunAudio = GetComponent<AudioSource> ();
                gunLight = GetComponent<Light> ();
                //faceLight = GetComponentInChildren<Light> ();
            }
    
    
            void Update ()
            {
                //每帧增加计时器的时间
                timer += Time.deltaTime;
    
    #if !MOBILE_INPUT
                //如果按下发射按键,计时器大于两次发射子弹的间隔时,时间比例不等于0
                if(Input.GetButton ("Fire1") && timer >= timeBetweenBullets && Time.timeScale != 0)
                {
                    //射击
                    Shoot ();
                }
    #else
                if ((CrossPlatformInputManager.GetAxisRaw("Mouse X") != 0 || CrossPlatformInputManager.GetAxisRaw("Mouse Y") != 0) && timer >= timeBetweenBullets)
                {
                    Shoot();
                }
    #endif
                //如果计时器超过特效显示的时间
                if(timer >= timeBetweenBullets * effectsDisplayTime)
                {
                    //关闭射击效果
                    DisableEffects ();
                }
            }
    
    
            public void DisableEffects ()
            {
                gunLine.enabled = false;
                faceLight.enabled = false;
                gunLight.enabled = false;
            }
    
            /// <summary>
            /// 射击
            /// </summary>
            void Shoot ()
            {
                //重置计时器
                timer = 0f;
    
                //播放射击声音
                gunAudio.Play ();
    
                
                gunLight.enabled = true;
                faceLight.enabled = true;
    
                //先停止粒子特效,然后再播放特效
                gunParticles.Stop ();
                gunParticles.Play ();
    
                //设置线条渲染器的第一个位置
                gunLine.enabled = true;
                gunLine.SetPosition (0, transform.position);
    
                //设置 射击射线的 起点和方向
                shootRay.origin = transform.position;
                shootRay.direction = transform.forward;
    
                //发射射线,碰到敌人
                if(Physics.Raycast (shootRay, out shootHit, range, shootableMask))
                {
                    //敌人受到伤害
                    EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();
                    if(enemyHealth != null)
                    {
                        enemyHealth.TakeDamage (damagePerShot, shootHit.point);
                    }
    
                    //设置线条渲染器的第二个位置为射击点的位置
                    gunLine.SetPosition (1, shootHit.point);
                }
                //没有碰到敌人,设置线条渲染器的第2个位置
                else
                {
                    gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);
                }
            }
        }
    }
    PlayerShooting
    using UnityEngine;
    
    namespace CompleteProject
    {
        /// <summary>
        /// 游戏结束管理
        /// </summary>
        public class GameOverManager : MonoBehaviour
        {
            /// <summary>
            /// 玩家生命
            /// </summary>
            public PlayerHealth playerHealth;       
    
            /// <summary>
            /// Animator
            /// </summary>
            Animator anim;                          
    
    
            void Awake ()
            {
                anim = GetComponent <Animator> ();
            }
    
    
            void Update ()
            {
                //如果玩家生命值小于等于0
                if(playerHealth.currentHealth <= 0)
                {
                    //Animator设置GameOver触发器
                    anim.SetTrigger ("GameOver");
                }
            }
        }
    }
    GameOverManager
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    using UnityEngine.Audio;
    #if UNITY_EDITOR
    using UnityEditor;
    #endif
    
    /// <summary>
    /// 暂停管理
    /// </summary>
    public class PauseManager : MonoBehaviour {
        
        public AudioMixerSnapshot paused;
        public AudioMixerSnapshot unpaused;
        
        /// <summary>
        /// Canvas
        /// </summary>
        Canvas canvas;
        
        void Start()
        {
            canvas = GetComponent<Canvas>();
        }
        
        void Update()
        {
            //按esc键 切换游戏状态
            if (Input.GetKeyDown(KeyCode.Escape))
            {
                canvas.enabled = !canvas.enabled;
                Pause();
            }
        }
        
        /// <summary>
        /// 暂停游戏
        /// </summary>
        public void Pause()
        {
            Time.timeScale = Time.timeScale == 0 ? 1 : 0;
            Lowpass ();
            
        }
        
        /// <summary>
        /// 调整声音
        /// </summary>
        void Lowpass()
        {
            if (Time.timeScale == 0)
            {
                paused.TransitionTo(.01f);
            }
            
            else
                
            {
                unpaused.TransitionTo(.01f);
            }
        }
        
        /// <summary>
        /// 退出游戏
        /// </summary>
        public void Quit()
        {
            //调用编辑器的退出
            #if UNITY_EDITOR 
            EditorApplication.isPlaying = false;
            //调用正常的退出
            #else 
            Application.Quit();
            #endif
        }
    }
    PauseManager
    using UnityEngine;
    using UnityEngine.UI;
    using System.Collections;
    
    namespace CompleteProject
    {
        /// <summary>
        /// 玩家分数管理
        /// </summary>
        public class ScoreManager : MonoBehaviour
        {
            /// <summary>
            /// 玩家分数
            /// </summary>
            public static int score;        
    
            /// <summary>
            /// 显示玩家分数的文本
            /// </summary>
            Text text;                      
                                                                                 
    
            void Awake ()
            {
                text = GetComponent <Text> ();
    
                //重置玩家分数
                score = 0;
            }
    
    
            void Update ()
            {
                //更新玩家分数的显示
                text.text = "Score: " + score;
            }
        }
    }
    ScoreManager

    视频:https://pan.baidu.com/s/1geIxFs3

    项目:https://pan.baidu.com/s/1gfDonkf

  • 相关阅读:
    iview的modal点击确定消失(自动关闭)问题,自定义modal页脚
    vue实现组件数据双向绑定
    vue中封装svg-icon组件并使用
    闭包的概念
    vue基本集
    websocket
    99multiplication table
    h5c3增加了哪些新特性
    防抖与节流函数
    网页性能优化小技巧
  • 原文地址:https://www.cnblogs.com/revoid/p/6433593.html
Copyright © 2020-2023  润新知