2D Platformer 学习

using UnityEngine;
using System.Collections;

/// <summary>
/// 玩家控制
/// </summary>
public class PlayerControl : MonoBehaviour
{
    /// <summary>
    /// 是否面向右边
    /// </summary>
    [HideInInspector]
    public bool facingRight = true;            
    /// <summary>
    /// 是否在跳跃状态
    /// </summary>
    [HideInInspector]
    public bool jump = false;                

    /// <summary>
    /// 玩家左右移动的力
    /// </summary>
    public float moveForce = 365f;            
    /// <summary>
    /// 玩家在x轴的最大移动速度
    /// </summary>
    public float maxSpeed = 5f;                
    /// <summary>
    /// 跳跃声音
    /// </summary>
    public AudioClip[] jumpClips;            
    /// <summary>
    /// 跳跃力
    /// </summary>
    public float jumpForce = 1000f;            
    /// <summary>
    /// 嘲讽声音
    /// </summary>
    public AudioClip[] taunts;                
    /// <summary>
    /// 嘲讽阈值
    /// </summary>
    public float tauntProbability = 50f;    
    /// <summary>
    /// 嘲讽延迟
    /// </summary>
    public float tauntDelay = 1f;            

    /// <summary>
    /// 上一次的嘲讽索引
    /// </summary>
    private int tauntIndex;                    
    /// <summary>
    /// 检查玩家是否在地上的go
    /// </summary>
    private Transform groundCheck;            
    /// <summary>
    /// 玩家是否在地上
    /// </summary>
    private bool grounded = false;            
    /// <summary>
    /// Animator
    /// </summary>
    private Animator anim;                                                 


    void Awake()
    {
        groundCheck = transform.Find("groundCheck");
        anim = GetComponent<Animator>();
    }


    void Update()
    {
        //发射射线检测玩家是否在地面
        grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));  

        //如果按下跳跃键且玩家在地上,玩家跳
        if(Input.GetButtonDown("Jump") && grounded)
            jump = true;
    }


    void FixedUpdate ()
    {
        //获取水平的输入
        float h = Input.GetAxis("Horizontal");

        //设置水平方向的移动速度
        anim.SetFloat("Speed", Mathf.Abs(h));

        //如果玩家速度没有到达最大速度,让玩家到达最大速度
        if(h * GetComponent<Rigidbody2D>().velocity.x < maxSpeed)
            GetComponent<Rigidbody2D>().AddForce(Vector2.right * h * moveForce);

        //如果x轴的速度大于最大速度,限制玩家速度为最大速度
        if(Mathf.Abs(GetComponent<Rigidbody2D>().velocity.x) > maxSpeed)
            GetComponent<Rigidbody2D>().velocity = new Vector2(Mathf.Sign(GetComponent<Rigidbody2D>().velocity.x) * maxSpeed, GetComponent<Rigidbody2D>().velocity.y);

        //设置玩家的朝向
        if(h > 0 && !facingRight)
            Flip();
        else if(h < 0 && facingRight)
            Flip();

        //如果玩家跳
        if(jump)
        {
            //播放跳动画
            anim.SetTrigger("Jump");

            //随机播放跳跃声音
            int i = Random.Range(0, jumpClips.Length);
            AudioSource.PlayClipAtPoint(jumpClips[i], transform.position);

            //添加跳跃力
            GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, jumpForce));

            //设置跳跃标志位为false
            jump = false;
        }
    }
    
    /// <summary>
    /// 转向
    /// </summary>
    void Flip ()
    {
        facingRight = !facingRight;

        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }

    /// <summary>
    /// 嘲讽协程
    /// </summary>
    /// <returns></returns>
    public IEnumerator Taunt()
    {
        //计算嘲讽几率
        float tauntChance = Random.Range(0f, 100f);
        //如果嘲讽几率大于阈值
        if(tauntChance > tauntProbability)
        {
            
            yield return new WaitForSeconds(tauntDelay);

            
            if(!GetComponent<AudioSource>().isPlaying)
            {
                tauntIndex = TauntRandom();

                GetComponent<AudioSource>().clip = taunts[tauntIndex];
                GetComponent<AudioSource>().Play();
            }
        }
    }

    /// <summary>
    /// 随机播放嘲讽
    /// </summary>
    /// <returns></returns>
    int TauntRandom()
    {
        int i = Random.Range(0, taunts.Length);

        //如果和上次的嘲讽索引一样,再随机一次
        if(i == tauntIndex)
            return TauntRandom();
        else
            return i;
    }
}
PlayerControl
using UnityEngine;
using System.Collections;

/// <summary>
/// 玩家生命
/// </summary>
public class PlayerHealth : MonoBehaviour
{    
    /// <summary>
    /// 玩家生命
    /// </summary>
    public float health = 100f;                    
    /// <summary>
    /// 玩家能被伤害的时间间隔
    /// </summary>
    public float repeatDamagePeriod = 2f;        
    /// <summary>
    /// 玩家受到伤害的声音数组
    /// </summary>
    public AudioClip[] ouchClips;                
    /// <summary>
    /// 玩家受到伤害时受到的力
    /// </summary>
    public float hurtForce = 10f;                
    /// <summary>
    /// 敌人碰到玩家后,玩家受到的伤害
    /// </summary>
    public float damageAmount = 10f;            

    /// <summary>
    /// 玩家血条
    /// </summary>
    private SpriteRenderer healthBar;            
    /// <summary>
    /// 上一次受到的伤害
    /// </summary>
    private float lastHitTime;                    
    /// <summary>
    /// 血条缩放
    /// </summary>
    private Vector3 healthScale;                
    /// <summary>
    /// 玩家控制
    /// </summary>
    private PlayerControl playerControl;        
    /// <summary>
    /// Animator
    /// </summary>
    private Animator anim;                                                  


    void Awake ()
    {
        playerControl = GetComponent<PlayerControl>();
        healthBar = GameObject.Find("HealthBar").GetComponent<SpriteRenderer>();
        anim = GetComponent<Animator>();

        healthScale = healthBar.transform.localScale;
    }


    void OnCollisionEnter2D (Collision2D col)
    {
        //如果碰到敌人
        if(col.gameObject.tag == "Enemy")
        {
            //如果时间大于 上次受到伤害的时间 + 玩家能被伤害的时间间隔
            if (Time.time > lastHitTime + repeatDamagePeriod) 
            {
                //如果玩家生命>0
                if(health > 0f)
                {
                    TakeDamage(col.transform); 
                    //设置上次受到伤害的时间
                    lastHitTime = Time.time; 
                }
                //如果玩家生命<=,让玩家掉下河
                else
                {
                    //将玩家的碰撞器修改为触发器
                    Collider2D[] cols = GetComponents<Collider2D>();
                    foreach(Collider2D c in cols)
                    {
                        c.isTrigger = true;
                    }

                    //修改玩家及其子物体的 SorintLayer
                    SpriteRenderer[] spr = GetComponentsInChildren<SpriteRenderer>();
                    foreach(SpriteRenderer s in spr)
                    {
                        s.sortingLayerName = "UI";
                    }

                    //关闭玩家控制脚本
                    GetComponent<PlayerControl>().enabled = false;

                    //关闭 gun脚本
                    GetComponentInChildren<Gun>().enabled = false;

                    //播放死亡动画
                    anim.SetTrigger("Die");
                }
            }
        }
    }

    /// <summary>
    /// 受到伤害
    /// </summary>
    /// <param name="enemy"></param>
    void TakeDamage (Transform enemy)
    {
        //让玩家不能跳
        playerControl.jump = false;

        //设置受伤的方向
        Vector3 hurtVector = transform.position - enemy.position + Vector3.up * 5f;

        //给刚体施加力
        GetComponent<Rigidbody2D>().AddForce(hurtVector * hurtForce);

        //减血
        health -= damageAmount;

        //更新血条
        UpdateHealthBar();

        //随机播放受到伤害的声音
        int i = Random.Range (0, ouchClips.Length);
        AudioSource.PlayClipAtPoint(ouchClips[i], transform.position);
    }

    /// <summary>
    /// 更新血条
    /// </summary>
    public void UpdateHealthBar ()
    {
        //设置血条颜色
        healthBar.material.color = Color.Lerp(Color.green, Color.red, 1 - health * 0.01f);

        //设置血条缩放
        healthBar.transform.localScale = new Vector3(healthScale.x * health * 0.01f, 1, 1);
    }
}
PlayerHealth
using UnityEngine;
using System.Collections;

/// <summary>
/// 玩家放置炸弹
/// </summary>
public class LayBombs : MonoBehaviour
{
    /// <summary>
    /// 炸弹是否已放置
    /// </summary>
    [HideInInspector]
    public bool bombLaid = false;        
    /// <summary>
    /// 玩家拥有的炸弹数量
    /// </summary>
    public int bombCount = 0;            
    /// <summary>
    /// 放置炸弹的声音
    /// </summary>
    public AudioClip bombsAway;            
    /// <summary>
    /// 炸弹预设
    /// </summary>
    public GameObject bomb;                

    /// <summary>
    /// 炸弹HUD
    /// </summary>
    private GUITexture bombHUD;                  


    void Awake ()
    {
        bombHUD = GameObject.Find("ui_bombHUD").GetComponent<GUITexture>();
    }


    void Update ()
    {
        //放置炸弹
        if(Input.GetButtonDown("Fire2") && !bombLaid && bombCount > 0)
        {
            bombCount--;
            bombLaid = true;
            AudioSource.PlayClipAtPoint(bombsAway,transform.position);
            Instantiate(bomb, transform.position, transform.rotation);
        }
        bombHUD.enabled = bombCount > 0;
    }
}
LayBombs
using UnityEngine;
using System.Collections;

/// <summary>
/// 玩家的枪
/// </summary>
public class Gun : MonoBehaviour
{
    /// <summary>
    /// 火箭预设
    /// </summary>
    public Rigidbody2D rocket;                
    /// <summary>
    /// 火箭速度
    /// </summary>
    public float speed = 20f;                

    /// <summary>
    /// 玩家控制
    /// </summary>
    private PlayerControl playerCtrl;        
    /// <summary>
    /// Animator
    /// </summary>
    private Animator anim;                              


    void Awake()
    {
        anim = transform.root.gameObject.GetComponent<Animator>();
        playerCtrl = transform.root.GetComponent<PlayerControl>();
    }


    void Update ()
    {
        //按下发射键
        if(Input.GetButtonDown("Fire1"))
        {
            //播放动画
            anim.SetTrigger("Shoot");
            //播放声音
            GetComponent<AudioSource>().Play();

            //玩家朝右
            if(playerCtrl.facingRight)
            {
                //实例化向右的子弹
                Rigidbody2D bulletInstance = Instantiate(rocket, transform.position, Quaternion.Euler(new Vector3(0,0,0))) as Rigidbody2D;
                bulletInstance.velocity = new Vector2(speed, 0);
            }
            //玩家朝左
            else
            {
                //实例化向左的子弹
                Rigidbody2D bulletInstance = Instantiate(rocket, transform.position, Quaternion.Euler(new Vector3(0,0,180f))) as Rigidbody2D;
                bulletInstance.velocity = new Vector2(-speed, 0);
            }
        }
    }
}
Gun
using UnityEngine;
using System.Collections;

/// <summary>
/// 火箭
/// </summary>
public class Rocket : MonoBehaviour 
{
    /// <summary>
    /// 爆炸预设
    /// </summary>
    public GameObject explosion;        


    void Start () 
    {
        //炸弹没有碰到任何东西,默认2秒内销毁
        Destroy(gameObject, 2);
    }

    /// <summary>
    /// 爆炸
    /// </summary>
    void OnExplode()
    {
        //实例化爆炸效果,让爆炸效果在z轴随机旋转
        Quaternion randomRotation = Quaternion.Euler(0f, 0f, Random.Range(0f, 360f));
        Instantiate(explosion, transform.position, randomRotation);
    }
    
    void OnTriggerEnter2D (Collider2D col) 
    {
        //撞到敌人
        if(col.tag == "Enemy")
        {
            //敌人受伤
            col.gameObject.GetComponent<Enemy>().Hurt();
            OnExplode();
            Destroy (gameObject);
        }
        //撞到炸弹收集物
        else if(col.tag == "BombPickup")
        {
            //炸弹爆炸
            col.gameObject.GetComponent<Bomb>().Explode();
            Destroy (col.transform.root.gameObject);
            Destroy (gameObject);
        }
        //其余情况
        else if(col.gameObject.tag != "Player")
        {
            OnExplode();
            Destroy (gameObject);
        }
    }
}
Rocket
using UnityEngine;
using System.Collections;

/// <summary>
/// 自动销毁
/// </summary>
public class Destroyer : MonoBehaviour
{
    /// <summary>
    /// 是否在开始时间就进入自动销毁
    /// </summary>
    public bool destroyOnAwake;            
    /// <summary>
    /// 自动销毁的延迟
    /// </summary>
    public float awakeDestroyDelay;        
    /// <summary>
    /// 是否查找子物体
    /// </summary>
    public bool findChild = false;        
    /// <summary>
    /// 子物体的名称
    /// </summary>
    public string namedChild;                                                    


    void Awake ()
    {
        if(destroyOnAwake)
        {
            if(findChild)
            {
                Destroy (transform.Find(namedChild).gameObject);
            }
            else
            {
                Destroy(gameObject, awakeDestroyDelay);
            }

        }

    }

    /// <summary>
    /// 销毁子物体
    /// </summary>
    void DestroyChildGameObject ()
    {
        if(transform.Find(namedChild).gameObject != null)
            Destroy (transform.Find(namedChild).gameObject);
    }

    /// <summary>
    /// 禁用子物体
    /// </summary>
    void DisableChildGameObject ()
    {
        if(transform.Find(namedChild).gameObject.activeSelf == true)
            transform.Find(namedChild).gameObject.SetActive(false);
    }

    /// <summary>
    /// 销毁物体
    /// </summary>
    void DestroyGameObject ()
    {
        Destroy (gameObject);
    }
}
Destroyer
using UnityEngine;
using System.Collections;

/// <summary>
/// 血条跟随玩家
/// </summary>
public class FollowPlayer : MonoBehaviour
{
    /// <summary>
    /// 相对于玩家的偏移
    /// </summary>
    public Vector3 offset;            
    
    /// <summary>
    /// 玩家
    /// </summary>
    private Transform player;                                                   


    void Awake ()
    {
        player = GameObject.FindGameObjectWithTag("Player").transform;
    }

    void Update ()
    {
        transform.position = player.position + offset;
    }
}
FollowPlayer
using UnityEngine;
using System.Collections;

/// <summary>
/// 收集物的孵化器
/// </summary>
public class PickupSpawner : MonoBehaviour
{
    /// <summary>
    /// 收集物预设
    /// </summary>
    public GameObject[] pickups;                
    /// <summary>
    /// 收集物在空中的时间
    /// </summary>
    public float pickupDeliveryTime = 5f;        
    /// <summary>
    /// 掉落范围左
    /// </summary>
    public float dropRangeLeft;                    
    /// <summary>
    /// 掉落范围右
    /// </summary>
    public float dropRangeRight;                
    /// <summary>
    /// 高于这个阈值,投递炸弹
    /// </summary>
    public float highHealthThreshold = 75f;     
    /// <summary>
    /// 低于这个阈值,投递血药
    /// </summary>
    public float lowHealthThreshold = 25f;        

    /// <summary>
    /// 玩家血量
    /// </summary>
    private PlayerHealth playerHealth;                                                  


    void Awake ()
    {
        playerHealth = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerHealth>();
    }


    void Start ()
    {
        StartCoroutine(DeliverPickup());
    }

    /// <summary>
    /// 派送收集物协程
    /// </summary>
    /// <returns></returns>
    public IEnumerator DeliverPickup()
    {
        yield return new WaitForSeconds(pickupDeliveryTime);

        //随机获得掉落在x轴的位置
        float dropPosX = Random.Range(dropRangeLeft, dropRangeRight);

        //计算掉落位置
        Vector3 dropPos = new Vector3(dropPosX, 15f, 1f);

        //高于阈值,实例化炸弹
        if(playerHealth.health >= highHealthThreshold)
            Instantiate(pickups[0], dropPos, Quaternion.identity);
        //低于阈值,实例化药
        else if(playerHealth.health <= lowHealthThreshold)
            Instantiate(pickups[1], dropPos, Quaternion.identity);
        //随机实例化
        else
        {
            int pickupIndex = Random.Range(0, pickups.Length);
            Instantiate(pickups[pickupIndex], dropPos, Quaternion.identity);
        }
    }
}
PickupSpawner
using UnityEngine;
using System.Collections;

/// <summary>
/// 炸弹收集物
/// </summary>
public class BombPickup : MonoBehaviour
{
    /// <summary>
    /// 收集声音
    /// </summary>
    public AudioClip pickupClip;        

    /// <summary>
    /// Animator
    /// </summary>
    private Animator anim;                
    /// <summary>
    /// 是否着陆
    /// </summary>
    private bool landed = false;                    


    void Awake()
    {
        anim = transform.root.GetComponent<Animator>();
    }


    void OnTriggerEnter2D (Collider2D other)
    {
        //碰到玩家
        if(other.tag == "Player")
        {
            AudioSource.PlayClipAtPoint(pickupClip, transform.position);

            other.GetComponent<LayBombs>().bombCount++;

            Destroy(transform.root.gameObject);
        }
        //碰到地面
        else if(other.tag == "ground" && !landed)
        {
            anim.SetTrigger("Land");
            transform.parent = null;
            gameObject.AddComponent<Rigidbody2D>();
            landed = true;        
        }
    }
}
BombPickup
using UnityEngine;
using System.Collections;

/// <summary>
/// 生命收集物
/// </summary>
public class HealthPickup : MonoBehaviour
{
    /// <summary>
    /// 提供的生命值
    /// </summary>
    public float healthBonus;                
    /// <summary>
    /// 被收集后的声音
    /// </summary>
    public AudioClip collect;                

    /// <summary>
    /// 收集物孵化器
    /// </summary>
    private PickupSpawner pickupSpawner;    
    /// <summary>
    /// Animator
    /// </summary>
    private Animator anim;                    
    /// <summary>
    /// 是否着陆
    /// </summary>
    private bool landed;                                 


    void Awake ()
    {
        pickupSpawner = GameObject.Find("pickupManager").GetComponent<PickupSpawner>();
        anim = transform.root.GetComponent<Animator>();
    }


    void OnTriggerEnter2D (Collider2D other)
    {
        //如果碰到玩家
        if(other.tag == "Player")
        {
            PlayerHealth playerHealth = other.GetComponent<PlayerHealth>();
            //给玩家加血
            playerHealth.health += healthBonus;
            //限制玩家的最大生命
            playerHealth.health = Mathf.Clamp(playerHealth.health, 0f, 100f);

            //更新血条
            playerHealth.UpdateHealthBar();

            pickupSpawner.StartCoroutine(pickupSpawner.DeliverPickup());

            AudioSource.PlayClipAtPoint(collect,transform.position);

            Destroy(transform.root.gameObject);
        }
        //如果碰到地面
        else if(other.tag == "ground" && !landed)
        {
            anim.SetTrigger("Land");

            transform.parent = null;
            gameObject.AddComponent<Rigidbody2D>();
            landed = true;    
        }
    }
}
HealthPickup
using UnityEngine;
using System.Collections;

/// <summary>
/// 炸弹
/// </summary>
public class Bomb : MonoBehaviour
{
    /// <summary>
    /// 爆炸影响的半径
    /// </summary>
    public float bombRadius = 10f;            
    /// <summary>
    /// 爆炸力
    /// </summary>
    public float bombForce = 100f;            
    /// <summary>
    /// 爆炸声音
    /// </summary>
    public AudioClip boom;                    
    /// <summary>
    /// 炸弹引爆的声音
    /// </summary>
    public AudioClip fuse;                    
    /// <summary>
    /// 引爆持续时间
    /// </summary>
    public float fuseTime = 1.5f;
    /// <summary>
    /// 爆炸特效
    /// </summary>
    public GameObject explosion;            

    /// <summary>
    /// 玩家放置炸弹
    /// </summary>
    private LayBombs layBombs;                
    /// <summary>
    /// 收集物孵化器
    /// </summary>
    private PickupSpawner pickupSpawner;    
    /// <summary>
    /// 爆炸粒子系统
    /// </summary>
    private ParticleSystem explosionFX;           


    void Awake ()
    {
        explosionFX = GameObject.FindGameObjectWithTag("ExplosionFX").GetComponent<ParticleSystem>();
        pickupSpawner = GameObject.Find("pickupManager").GetComponent<PickupSpawner>();
        if(GameObject.FindGameObjectWithTag("Player"))
            layBombs = GameObject.FindGameObjectWithTag("Player").GetComponent<LayBombs>();
    }

    void Start ()
    {
        
        //如果炸弹没有父物体,说明炸弹已被放置,开始引爆
        if(transform.root == transform)
            StartCoroutine(BombDetonation());
    }

    /// <summary>
    /// 炸弹引爆协程
    /// </summary>
    /// <returns></returns>
    IEnumerator BombDetonation()
    {
        AudioSource.PlayClipAtPoint(fuse, transform.position);

        yield return new WaitForSeconds(fuseTime);

        Explode();
    }

    /// <summary>
    /// 爆炸
    /// </summary>
    public void Explode()
    {
        
        //玩家可以放置炸弹
        layBombs.bombLaid = false;

        //开始新的投递
        pickupSpawner.StartCoroutine(pickupSpawner.DeliverPickup());

        //获取范围内的敌人
        Collider2D[] enemies = Physics2D.OverlapCircleAll(transform.position, bombRadius, 1 << LayerMask.NameToLayer("Enemies"));

        foreach(Collider2D en in enemies)
        {
            Rigidbody2D rb = en.GetComponent<Rigidbody2D>();
            if(rb != null && rb.tag == "Enemy")
            {
                //秒杀敌人
                rb.gameObject.GetComponent<Enemy>().HP = 0;

                //将敌人推出一段距离
                Vector3 deltaPos = rb.transform.position - transform.position;
                Vector3 force = deltaPos.normalized * bombForce;
                rb.AddForce(force);
            }
        }

        //播放爆炸效果
        explosionFX.transform.position = transform.position;
        explosionFX.Play();

        Instantiate(explosion,transform.position, Quaternion.identity);

        AudioSource.PlayClipAtPoint(boom, transform.position);

        Destroy (gameObject);
    }
}
Bomb
using UnityEngine;
using System.Collections;

/// <summary>
/// 敌人
/// </summary>
public class Enemy : MonoBehaviour
{
    /// <summary>
    /// 移动速度
    /// </summary>
    public float moveSpeed = 2f;        
    /// <summary>
    /// 玩家被击杀需要的次数
    /// </summary>
    public int HP = 2;                    
    /// <summary>
    /// 死亡的动画
    /// </summary>
    public Sprite deadEnemy;            
    /// <summary>
    /// 受到伤害的动画
    /// </summary>
    public Sprite damagedEnemy;            
    /// <summary>
    /// 死亡声音
    /// </summary>
    public AudioClip[] deathClips;        
    /// <summary>
    /// 敌人死亡后生成的 得分物体
    /// </summary>
    public GameObject hundredPointsUI;    
    /// <summary>
    /// 
    /// </summary>
    public float deathSpinMin = -100f;    
    /// <summary>
    /// 
    /// </summary>
    public float deathSpinMax = 100f;    

    /// <summary>
    /// 精灵渲染器
    /// </summary>
    private SpriteRenderer ren;            
    /// <summary>
    /// 检查前方的go
    /// </summary>
    private Transform frontCheck;        
    /// <summary>
    /// 是否死亡
    /// </summary>
    private bool dead = false;            
    /// <summary>
    /// 玩家得分脚本
    /// </summary>
    private Score score;                                                                   

    
    void Awake()
    {
        ren = transform.Find("body").GetComponent<SpriteRenderer>();
        frontCheck = transform.Find("frontCheck").transform;
        score = GameObject.Find("Score").GetComponent<Score>();
    }

    void FixedUpdate ()
    {
        //检测碰撞
        Collider2D[] frontHits = Physics2D.OverlapPointAll(frontCheck.position, 1);

        foreach(Collider2D c in frontHits)
        {
            //如果碰到障碍物
            if(c.tag == "Obstacle")
            {
                //转向
                Flip ();
                break;
            }
        }

        GetComponent<Rigidbody2D>().velocity = new Vector2(transform.localScale.x * moveSpeed, GetComponent<Rigidbody2D>().velocity.y);    

        
        if(HP == 1 && damagedEnemy != null)
            ren.sprite = damagedEnemy;

        if(HP <= 0 && !dead)
            Death ();
    }
    
    /// <summary>
    /// 受到伤害
    /// </summary>
    public void Hurt()
    {
        HP--;
    }
    
    void Death()
    {
        //关闭所有的精灵渲染器
        SpriteRenderer[] otherRenderers = GetComponentsInChildren<SpriteRenderer>();
        foreach(SpriteRenderer s in otherRenderers)
        {
            s.enabled = false;
        }

        //打开自身的渲染器,设置为死亡精灵
        ren.enabled = true;
        ren.sprite = deadEnemy;

        //玩家得分+100
        score.score += 100;

        //死亡标志位设为true
        dead = true;

        GetComponent<Rigidbody2D>().fixedAngle = false;
        GetComponent<Rigidbody2D>().AddTorque(Random.Range(deathSpinMin,deathSpinMax));

        //修改碰撞器为触发器
        Collider2D[] cols = GetComponents<Collider2D>();
        foreach(Collider2D c in cols)
        {
            c.isTrigger = true;
        }

        //播放随机的死亡声音
        int i = Random.Range(0, deathClips.Length);
        AudioSource.PlayClipAtPoint(deathClips[i], transform.position);

        //实例化得分效果        
        Vector3 scorePos;
        scorePos = transform.position;
        scorePos.y += 1.5f;
        Instantiate(hundredPointsUI, scorePos, Quaternion.identity);
    }

    /// <summary>
    /// 转向
    /// </summary>
    public void Flip()
    {
        Vector3 enemyScale = transform.localScale;
        enemyScale.x *= -1;
        transform.localScale = enemyScale;
    }
}
Enemy
using UnityEngine;
using System.Collections;

/// <summary>
/// 移除器
/// </summary>
public class Remover : MonoBehaviour
{
    /// <summary>
    /// 水的飞溅效果
    /// </summary>
    public GameObject splash;


    void OnTriggerEnter2D(Collider2D col)
    {
        //如果碰到玩家
        if(col.gameObject.tag == "Player")
        {
            //禁用摄像机跟随玩家的脚本
            GameObject.FindGameObjectWithTag("MainCamera").GetComponent<CameraFollow>().enabled = false;

            //禁用玩家血条
            if(GameObject.FindGameObjectWithTag("HealthBar").activeSelf)
            {
                GameObject.FindGameObjectWithTag("HealthBar").SetActive(false);
            }

            Instantiate(splash, col.transform.position, transform.rotation);
            Destroy (col.gameObject);
            StartCoroutine("ReloadGame");
        }
        else
        {
            Instantiate(splash, col.transform.position, transform.rotation);
            Destroy (col.gameObject);    
        }
    }

    /// <summary>
    /// 重新加载游戏协程
    /// </summary>
    /// <returns></returns>
    IEnumerator ReloadGame()
    {            
        yield return new WaitForSeconds(2);
        Application.LoadLevel(Application.loadedLevel);
    }
}
Remover

  

using UnityEngine;
using System.Collections;

/// <summary>
/// 玩家得分
/// </summary>
public class Score : MonoBehaviour
{
    /// <summary>
    /// 玩家得分
    /// </summary>
    public int score = 0;                    

    /// <summary>
    /// 玩家控制脚本
    /// </summary>
    private PlayerControl playerControl;    
    /// <summary>
    /// 上一帧的得分
    /// </summary>
    private int previousScore = 0;                     


    void Awake ()
    {
        playerControl = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerControl>();
    }


    void Update ()
    {
        //设置得分文本
        GetComponent<GUIText>().text = "Score: " + score;

        //如果上一帧的得分不等与现在的得分
        if(previousScore != score)
            //播放嘲讽
            playerControl.StartCoroutine(playerControl.Taunt());

        //设置上一帧的额得分为 现在的得分
        previousScore = score;
    }

}
Score
using UnityEngine;
using System.Collections;

/// <summary>
/// 分数阴影
/// </summary>
public class ScoreShadow : MonoBehaviour
{
    /// <summary>
    /// Score Go
    /// </summary>
    public GameObject guiCopy;          


    void Awake()
    {
        //设置阴影的位置
        Vector3 behindPos = transform.position;
        behindPos = new Vector3(guiCopy.transform.position.x, guiCopy.transform.position.y-0.005f, guiCopy.transform.position.z-1);
        transform.position = behindPos;
    }


    void Update ()
    {
        GetComponent<GUIText>().text = guiCopy.GetComponent<GUIText>().text;
    }
}
ScoreShadow
using UnityEngine;
using System.Collections;

/// <summary>
/// 暂停器
/// </summary>
public class Pauser : MonoBehaviour {
    /// <summary>
    /// 是否已暂停
    /// </summary>
    private bool paused = false;
    
    void Update () {
        if(Input.GetKeyUp(KeyCode.P))
        {
            paused = !paused;
        }

        if(paused)
            Time.timeScale = 0;
        else
            Time.timeScale = 1;
    }
}
Pauser
using UnityEngine;
using System.Collections;

/// <summary>
/// 并行背景
/// </summary>
public class BackgroundParallax : MonoBehaviour
{
    /// <summary>
    /// 并行背景数组
    /// </summary>
    public Transform[] backgrounds;                
    /// <summary>
    /// 
    /// </summary>
    public float parallaxScale;                    
    /// <summary>
    /// 
    /// </summary>
    public float parallaxReductionFactor;        
    /// <summary>
    /// 
    /// </summary>
    public float smoothing;                        

    /// <summary>
    /// 摄像机
    /// </summary>
    private Transform cam;                        
    /// <summary>
    /// 上一帧的相机位置
    /// </summary>
    private Vector3 previousCamPos;                                        


    void Awake ()
    {
        cam = Camera.main.transform;
    }


    void Start ()
    {
        previousCamPos = cam.position;
    }


    void Update ()
    {
        float parallax = (previousCamPos.x - cam.position.x) * parallaxScale;

        for(int i = 0; i < backgrounds.Length; i++)
        {
            float backgroundTargetPosX = backgrounds[i].position.x + parallax * (i * parallaxReductionFactor + 1);
            Vector3 backgroundTargetPos = new Vector3(backgroundTargetPosX, backgrounds[i].position.y, backgrounds[i].position.z);
            backgrounds[i].position = Vector3.Lerp(backgrounds[i].position, backgroundTargetPos, smoothing * Time.deltaTime);
        }
        previousCamPos = cam.position;
    }
}
BackgroundParallax
using UnityEngine;
using System.Collections;

/// <summary>
/// 背景道具孵化器
/// </summary>
public class BackgroundPropSpawner : MonoBehaviour
{
    /// <summary>
    /// 背景道具的刚体
    /// </summary>
    public Rigidbody2D backgroundProp;        
    /// <summary>
    /// 左侧的x轴孵化点
    /// </summary>
    public float leftSpawnPosX;                
    /// <summary>
    /// 右侧的x轴孵化点
    /// </summary>
    public float rightSpawnPosX;            
    /// <summary>
    /// 
    /// </summary>
    public float minSpawnPosY;                
    public float maxSpawnPosY;                
    /// <summary>
    /// 最短的孵化时间间隔
    /// </summary>
    public float minTimeBetweenSpawns;        
    /// <summary>
    /// 最长的孵化时间间隔
    /// </summary>
    public float maxTimeBetweenSpawns;        
    /// <summary>
    /// 道具的最小速度
    /// </summary>
    public float minSpeed;                    
    /// <summary>
    /// 道具的最大速度
    /// </summary>
    public float maxSpeed;                                                   

    void Start ()
    {
        //随机种子
        Random.seed = System.DateTime.Today.Millisecond;

        StartCoroutine("Spawn");
    }

    /// <summary>
    /// 孵化协程
    /// </summary>
    /// <returns></returns>
    IEnumerator Spawn ()
    {
        //随机等待时间
        float waitTime = Random.Range(minTimeBetweenSpawns, maxTimeBetweenSpawns);
        yield return new WaitForSeconds(waitTime);

        //随机方向
        bool facingLeft = Random.Range(0,2) == 0;

        float posX = facingLeft ? rightSpawnPosX : leftSpawnPosX;

        //随机y轴位置
        float posY = Random.Range(minSpawnPosY, maxSpawnPosY);

        Vector3 spawnPos = new Vector3(posX, posY, transform.position.z);

        Rigidbody2D propInstance = Instantiate(backgroundProp, spawnPos, Quaternion.identity) as Rigidbody2D;

        if(!facingLeft)
        {
            Vector3 scale = propInstance.transform.localScale;
            scale.x *= -1;
            propInstance.transform.localScale = scale;
        }

        //随机速度
        float speed = Random.Range(minSpeed, maxSpeed);

        speed *= facingLeft ? -1f : 1f;

        propInstance.velocity = new Vector2(speed, 0);

        //重新孵化
        StartCoroutine(Spawn());

        while(propInstance != null)
        {
            if(facingLeft)
            {
                if(propInstance.transform.position.x < leftSpawnPosX - 0.5f)
                    Destroy(propInstance.gameObject);
            }
            else
            {
                if(propInstance.transform.position.x > rightSpawnPosX + 0.5f)
                    Destroy(propInstance.gameObject);
            }
            yield return null;
        }
    }
}
BackgroundPropSpawner
using UnityEngine;
using System.Collections;

/// <summary>
/// 摄像机跟随玩家
/// </summary>
public class CameraFollow : MonoBehaviour 
{
    public float xMargin = 1f;        
    public float yMargin = 1f;        
    public float xSmooth = 8f;        
    public float ySmooth = 8f;        
    public Vector2 maxXAndY;        
    public Vector2 minXAndY;                                


    private Transform player;        


    void Awake ()
    {
        player = GameObject.FindGameObjectWithTag("Player").transform;
    }


    bool CheckXMargin()
    {
        return Mathf.Abs(transform.position.x - player.position.x) > xMargin;
    }


    bool CheckYMargin()
    {
        return Mathf.Abs(transform.position.y - player.position.y) > yMargin;
    }


    void FixedUpdate ()
    {
        TrackPlayer();
    }
    
    
    void TrackPlayer ()
    {
        float targetX = transform.position.x;
        float targetY = transform.position.y;

        if(CheckXMargin())
            targetX = Mathf.Lerp(transform.position.x, player.position.x, xSmooth * Time.deltaTime);

        if(CheckYMargin())
            targetY = Mathf.Lerp(transform.position.y, player.position.y, ySmooth * Time.deltaTime);

        targetX = Mathf.Clamp(targetX, minXAndY.x, maxXAndY.x);
        targetY = Mathf.Clamp(targetY, minXAndY.y, maxXAndY.y);

        transform.position = new Vector3(targetX, targetY, transform.position.z);
    }
}
CameraFollow
using UnityEngine;
using System.Collections;

/// <summary>
/// 设置粒子系统的SortingLayer
/// </summary>
public class SetParticleSortingLayer : MonoBehaviour
{
    /// <summary>
    /// SortingLayer名
    /// </summary>
    public string sortingLayerName;        


    void Start ()
    {
        //设置粒子系统的sortingLayer名
        GetComponent<ParticleSystem>().GetComponent<Renderer>().sortingLayerName = sortingLayerName;
    }
}
SetParticleSortingLayer

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

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

原文地址:https://www.cnblogs.com/revoid/p/6439978.html