筆記30 Unity跑酷類型遊戲

街區

在這裏插入圖片描述

添加霧

在這裏插入圖片描述

玩家跑步代碼。爲了進行街區的製作,先讓玩家跑起來

  public int Hp = 1;
    // 速度
    public float Speed = 4;
   
    void Start()
    {        
    }

    void Update()
    {
        if(Hp <= 0)
        {
            //什麼也不做了
            return;
        }
        //跑步(向前方*速度*轉換成每秒)
        transform.Translate(transform.forward*Speed*Time.deltaTime);
    }

代碼:街區GroundControl

    //地形預設體的數組
    public GameObject[] GroundPres;

    //玩家位置
    private Transform playerTrans;

    void Start()
    {
        //在這裏得到。=得到玩家.位置
        playerTrans = GameObject.FindWithTag("Player").transform;
    }

    // Update is called once per frame
    void Update()
    {
        //如果玩家離開了當前地面,當前地面位置前進80米
        //因爲地面Z軸長度是40米,只要大於20米,即算離開。
        //爲了畫面銜接更好,所以別20米大點。
        if(playerTrans.position.z - transform.position.z > 25)
        {
            //往前方前進80米
            transform.position += Vector3.forward * 80;
            //銷燬當前地形,創建新地形
            Destroy(transform.GetChild(0).gameObject);
            //隨機創建新的地形。創建(什麼東西(隨機一個),位置(和當前點的位置一樣),旋轉(不旋轉))
            //創建出來之後,要當做當前點的子物體,所以在後面直接添加“.transform(拿到).SetParent設置父物體(transform當前點)”
            Instantiate(GroundPres[Random.Range(0, GroundPres.Length)], transform.position, Quaternion.identity).transform.SetParent(transform);
        }
    }

出現的一個小Bug

在這裏插入圖片描述

聲音控制器+代碼AudioManager

在這裏插入圖片描述

//單例
    public static AudioManager Instance;

    //播放器有兩個
    public AudioSource MusicPlayer;
    public AudioSource SoundPlayer;

    //單例寫在Awake這裏
    void Awake()
    {
        Instance = this;
    }

    //方法有兩個。一個是播放音樂
    public void PlayMusic(string name)
    {
        //如果音樂播放器沒在播放
        if(MusicPlayer.isPlaying == false)
        {
            //就讀取一個聲音片段,聲音判斷是通過R加載上來的
            AudioClip clip = Resources.Load<AudioClip>(name);
            MusicPlayer.clip = clip;
            MusicPlayer.Play();
        }
    }
    //另一個是停止的方法
    public void StopMusic()
    {
        MusicPlayer.Stop();
    }

    //播放音效
    public void PlaySound(string name)
    {
        //加載聲音片段
        AudioClip clip = Resources.Load<AudioClip>(name);
        SoundPlayer.PlayOneShot(clip);
    }

玩家

玩家左右變換跑道

未使用動畫插件,切換較生硬(不好)

 //靠左邊跑
        if(Input.GetKeyDown(KeyCode.A) && isGround == true)
        {
            //如果它在中間、右側跑道(即X軸大於等於0),纔可以靠左邊跑
            if (transform.position.x >= 0)
            {            
                //transform.position.x -= 2;是會爆紅的。因爲,Vector3是可讀可寫,xyz是隻讀。所以,這裏需要使用座標轉換。
				//拿到當前座標
                Vector3 v = transform.position;
                //減
                v.x -= 2;
                //再賦值回來
                transform.position = v;
            }
        }
        //靠右邊跑
        if (Input.GetKeyDown(KeyCode.D) && isGround == true)
        {
            //如果它在中間、左側跑道(即X軸小於等於0),纔可以靠右邊跑
            if (transform.position.x <= 0)
            {
                //拿到當前座標
                Vector3 v = transform.position;
                //加
                v.x += 2;
                //再賦值回來
                transform.position = v;
            }
        }

使用動畫插件,切換自然+代碼

在這裏插入圖片描述

    /*
    是否在動畫當中(因爲,下面利用插件左右移動時,給的動畫時間是0.5秒,
    如果在未到0.5秒(即未到指定位置,未播完動畫),便按了其他按鍵,會導致位置不準確
    所以添加判斷:是否在動畫中
    */
    private bool isAni = false;
  
  
        //靠左邊跑
        if(Input.GetKeyDown(KeyCode.A) && isGround == true)
        {
            //如果它在中間、右側跑道(即X軸大於等於0),纔可以靠左邊跑
            if (transform.position.x >= 0 && isAni == false)
            {
                //播放音效
                AudioManager.Instance.PlaySound("變換跑道");

                //設定動畫狀態
                isAni = true;
                //目標位置。target的x = 當前位置的x減2
                float targetx = transform.position.x - 2;
                //創建動畫。一個動畫,就是一個Tween。增加了很多方法,此處用X軸移動(DOMoveX)
                //DOMoveX(目標位置,動畫時間)
                Tween tween = transform.DOMoveX(targetx, 0.5f);
                /*
                 此處,應該講動畫的狀態設置爲false。
                 法一:在下面寫一個結束方法,在這裏“Invoke("AniEnd", 0.5f);”。
                 意思是,0.5秒以後,調用動畫結束方法。
                 法二:在下面寫一個結束方法,onComplete完成委託。TweenCallback委託(AniEnd方法)
                 兩種方法,法二的優點是不需要知道動畫播放時間,
                 所以如果動畫的播放時間是隨機的,該方法便是極好用的了。
                 */
                tween.onComplete = new TweenCallback(AniEnd);
            }
        }
        //靠右邊跑
        if (Input.GetKeyDown(KeyCode.D) && isGround == true)
        {
            //如果它在中間、左側跑道(即X軸小於等於0),纔可以靠右邊跑
            if (transform.position.x <= 0 && isAni == false)
            {
                //播放音效
                AudioManager.Instance.PlaySound("變換跑道");

                //設定動畫狀態
                isAni = true;
                //目標位置。target的x = 當前位置的x加2
                float targetx = transform.position.x + 2;
                //創建動畫。一個動畫,就是一個Tween。增加了很多方法,此處用X軸移動(DOMoveX)
                //DOMoveX(目標位置,動畫時間)
                Tween tween = transform.DOMoveX(targetx, 0.5f);
                //完成委託
                tween.onComplete = new TweenCallback(AniEnd);
            }
        }

地面檢測出現的小問題

在這裏插入圖片描述

障礙物

在這裏插入圖片描述

金幣

創建金幣,注意它所屬的位置

在這裏插入圖片描述

金幣特效

第一組粒子

在這裏插入圖片描述
在這裏插入圖片描述

第二組粒子

在這裏插入圖片描述

代碼:金幣CoinCollider

// 拿到金幣特效
    public GameObject CoinEffect;

    void Start()
    {        
    }
    //金幣是一直旋轉的
    private void Update()
    {
        //注意金幣是形變後得到的,所以要查看此時向上的是什麼軸,此處是Y軸。
        //每秒旋轉80度
        transform.Rotate(Vector3.forward, 80 * Time.deltaTime);
    }


    //如果玩家進來了
    private void OnTriggerEnter(Collider other)
    {
        if(other.tag == "Player")
        {
            //實例化特效。實例化(實例化什麼,位置,旋轉)
            Instantiate(CoinEffect, transform.position, Quaternion.identity);
            //播放碰到金幣的音效
            AudioManager.Instance.PlaySound("金幣");
            //銷燬自己
            Destroy(gameObject);
        }
    }

自動銷燬金幣特效+代碼AudioDestroy

在這裏插入圖片描述

// 金幣特效是的粒子發射時間最長是0.5秒,所以,默認給它0.5秒
    public float DestroyTime = 0.5f;

    void Start()
    {
        Destroy(gameObject, DestroyTime);
    }

    void Update()
    {
        
    }

代碼:玩家PlayerControl

 public int Hp = 1;
    // 速度
    public float Speed = 4;

    /*是否在動畫當中(因爲,下面利用插件左右移動時,給的動畫時間是0.5秒,
    如果在未到0.5秒(即未到指定位置,未播完動畫),便按了其他按鍵,會導致位置不準確
    所以添加判斷:是否在動畫中*/
    private bool isAni = false;
    //是否接觸地面(因爲,此遊戲限定在空中不可以切換跑道)
    private bool isGround = false;

    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Hp <= 0)
        {
            //什麼也不做了
            return;
        }
        //跑步(向前方*速度*轉換成每秒)
        transform.Translate(transform.forward*Speed*Time.deltaTime);

        //判斷有沒有踩到地面有兩種方法,此處使用射線檢測
        //創建射線。此處應注意,這個模型的transform.position是緊貼地面的,所以要將射線的起始點上移一點點。
        //方向:Vector3.down向下
        Ray ray = new Ray(transform.position + Vector3.up * 0.05f, Vector3.down);
        RaycastHit hit;
        //射線檢測。(檢測誰ray, 檢測結果out hit, 射線長度0.1f)
        bool res = Physics.Raycast(ray, out hit, 0.1f);
        //畫出射線(無用,刪除即可)。把上面小括號裏射線的相關數據複製一下,添加長度,顏色
        //Debug.DrawRay(transform.position + Vector3.up * 0.05f, Vector3.down * 0.1f, Color.red);
        if(res = true && hit.collider.tag == "Ground")
        {
            isGround = true;
        }
        else
        {
            isGround = false;
        }
       
        //靠左邊跑
        if(Input.GetKeyDown(KeyCode.A) && isGround == true)
        {
            //如果它在中間、右側跑道(即X軸大於等於0),纔可以靠左邊跑
            if (transform.position.x >= 0 && isAni == false)
            {
                //播放音效
                AudioManager.Instance.PlaySound("變換跑道");

                //設定動畫狀態
                isAni = true;
                //目標位置。target的x = 當前位置的x減2
                float targetx = transform.position.x - 2;
                //創建動畫。一個動畫,就是一個Tween。增加了很多方法,此處用X軸移動(DOMoveX)
                //DOMoveX(目標位置,動畫時間)
                Tween tween = transform.DOMoveX(targetx, 0.5f);
                /*
                 此處,應該講動畫的狀態設置爲false。
                 法一:在下面寫一個結束方法,在這裏“Invoke("AniEnd", 0.5f);”。
                 意思是,0.5秒以後,調用動畫結束方法。
                 法二:在下面寫一個結束方法,onComplete完成委託。TweenCallback委託(AniEnd方法)
                 兩種方法,法二的優點是不需要知道動畫播放時間,
                 所以如果動畫的播放時間是隨機的,該方法便是極好用的了。
                 */
                tween.onComplete = new TweenCallback(AniEnd);
            }
        }
        //靠右邊跑
        if (Input.GetKeyDown(KeyCode.D) && isGround == true)
        {
            //如果它在中間、左側跑道(即X軸小於等於0),纔可以靠右邊跑
            if (transform.position.x <= 0 && isAni == false)
            {
                //播放音效
                AudioManager.Instance.PlaySound("變換跑道");

                //設定動畫狀態
                isAni = true;
                //目標位置。target的x = 當前位置的x加2
                float targetx = transform.position.x + 2;
                //創建動畫。一個動畫,就是一個Tween。增加了很多方法,此處用X軸移動(DOMoveX)
                //DOMoveX(目標位置,動畫時間)
                Tween tween = transform.DOMoveX(targetx, 0.5f);
                //完成委託
                tween.onComplete = new TweenCallback(AniEnd);
            }
        }

        //跳躍
        if(Input.GetKeyDown(KeyCode.Space) && isGround == true)
        {
            //給剛體一個向上的力
            GetComponent<Rigidbody>().AddForce(200f * Vector3.up);
            //播放跳躍音效
            AudioManager.Instance.PlaySound("跳");
        }
    }
    //動畫結束
    void AniEnd()
    {
        //保障x永遠是-2、0、2個值中的一個,使代碼更嚴謹。
        //思路:判斷結果是1.8,就直接改成2

        isAni = false;
    }
    
    //
    private void OnCollisionEnter(Collision collision)
    {
        if(collision.collider.tag == "Obs")
        {
            Hp--;
            if(Hp <= 0)
            {
                //停止背景音樂(自己填的第一條代碼)
                AudioManager.Instance.StopMusic();
                //播放死亡音效。(我出現的問題:死亡音效發生二重唱!)
                AudioManager.Instance.PlaySound("死亡2");
                //播放死亡動畫
                GetComponent<Animation>().Play("die");
            }
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章