FPS遊戲開發(3)

閒雜:

想玩遊戲的時候就來寫博客,其實我個人的感覺寫博客就跟寫書是一樣的嗎,寫書是將內心的故事呈現給讀者,而寫博客就是將技術呈現給讀者,一方面我們可以將自己的技術分享出來供大家學習,第二個是希望大家可以給我的技術做一些指點,互相學習互相交流,希望能在評論區多多留言,我也可以解決疑難雜症。

故事開始:

在FPS的遊戲開發當中設計到槍械的方面,手雷的方面,近戰武器,以及一些特殊的道具,所以這些模塊值得去深挖和細品,古人云:彩虹風雨後,成功細節中(我也不知道是哪個古人說的)

我的思路,搭建場景,然後給box添加上Rigibody組件(不要給地面也添加該組件,會出現很奇怪的情況,如果想試一試的小夥伴,可以玩一下)
在這裏插入圖片描述
接下來就是Granade,吐槽一下,我的第一版手雷和上面的箱子一樣大,由於太過搞笑所以我就弄了手雷2.0,看起來就舒服多了
在這裏插入圖片描述
接下來就是腳本方面了,我的思路是這樣的,首先是Granade.cs的腳本

  • 手雷延時爆炸delay
  • 手雷的爆炸半徑
  • 手雷的爆炸力度

這三方面考慮好後就可以開始寫腳本了,代碼如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Granade : MonoBehaviour
{

    public float delay = 3f;
    public float radius = 5f;
    public float force = 700f;

    public GameObject ExplosionEffect;
    public GameObject ExplosionAudio;


    float countDown;

    bool hasExploaded = false;


    void Start()
    {

        countDown = delay;
    }

   
    void Update()
    {
        countDown -= Time.deltaTime;

        if (countDown <=  0f && !hasExploaded)
        {
            Explode();
            hasExploaded = true;
        }
    }

    void Explode()
    {
        Instantiate(ExplosionEffect, transform.position, transform.rotation);
        Instantiate(ExplosionAudio, transform.position, transform.rotation);


        //add force to move
        //該半徑內的所有碰撞器,返回一個數組
        Collider[] collidersToMove = Physics.OverlapSphere(transform.position,radius);

        //遍歷球體內的所有Collider
        foreach (Collider nearbyObject in collidersToMove)
        {
            //獲取球體半徑範圍內的rigibody
            Rigidbody rb = nearbyObject.GetComponent<Rigidbody>();

            if (rb != null)
            {
                //向模擬爆炸效果的剛體施加力
                rb.AddExplosionForce(force,transform.position, radius);
            }
        }

        Destroy(gameObject);

    }

    //Granade Demage
}

代碼分析:
我在此腳本中用了一個特殊的方法,我們知道,當物體被銷燬的時候,身上的腳本以及組件都被銷燬了,所以不能夠將聲音和爆炸的特效掛載到手雷上面,而是應該單獨做成兩個預製體,接下來在手雷爆炸的時候將這兩個預製體加載出來,這樣就解決了這個辦法。
Instantiate(ExplosionEffect, transform.position, transform.rotation);
Instantiate(ExplosionAudio, transform.position, transform.rotation);

然後給Granade添加爆炸力和爆炸範圍
Collider[] collidersToMove = Physics.OverlapSphere(transform.position,radius);
在這裏插入圖片描述
在官方文檔中,講到了參數和使用方法。我解釋一下返回Collider數組的作用,這裏是將球形範圍內的所有包含Collder組件的物體都存起來,接下來遍歷球體內物體上的Rigibody組件,然後可以給含有該組件的物體添加爆炸力度,爆炸力是手雷來提供的,這樣就實現了手雷爆炸擊飛箱子。
rb.AddExplosionForce(force,transform.position, radius);
在這裏插入圖片描述Granade的部分就完成了,接下來就是手雷爆炸特效和手雷音效銷燬,回收的階段,我遇到的問題是特效如果不銷燬就會一直常駐內存,而且特效也會重複播放,所以,我就另外寫了一個腳本來專門管理它,DestroyGameObject(名字起的不是很恰當,後期優化)

代碼如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DestroyGameObject : MonoBehaviour
{

    public float effectTime = 6f;
    public GameObject BigExplosionEffect;
    public GameObject GranadeAudio;

    float currentDown;

    bool hasPerfab = true;

    void Start()
    {
        currentDown = effectTime;
    }

    
    void Update()
    {
        currentDown -= Time.deltaTime;

        if (currentDown <= 0 && hasPerfab)
        {

            if (BigExplosionEffect != null && GranadeAudio != null)
            {
                currentDown = effectTime;
                DestoryExplosinEffect();
                DestoryExlosinAudio();
                hasPerfab = true;
            }
            else
            {
                hasPerfab = false;
                
            }

        }

    }


    void DestoryExplosinEffect()
    {

        GameObject obj = GameObject.Find("BigExplosionEffect(Clone)");

        if (obj != null)
        {
            Destroy(obj);
        }

    }

    void DestoryExlosinAudio()
    {

        GameObject obj = GameObject.Find("GranadeAudio(Clone)");

        if (obj != null)
        {
            Destroy(obj);
        }  

    }
}

代碼解釋:

我先定義了一個計時器,由於我的特效和聲音大概是3秒,加上之前的手雷延時爆炸3秒,所以是6秒之後銷燬,這樣寫是比較簡單的,分開控制,方法也是分開寫的,方便後期的管理。
添加了一個控制條件hasPerfab ,控制它只銷毀一次,之前想一次扔好幾個手雷,但是出現了一些小問題(其實問題蠻大的),我下來解決一下,在下回書中我們在講解。然後將其掛載到場景CheckDestory上,如圖
在這裏插入圖片描述
最後是控制手雷的扔出,ThrowerGranade,代碼如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GranadeThrower : MonoBehaviour
{
    public float throwerForce = 15f;
    public GameObject GranadePrefab;
    private AudioSource audioSource;

    bool isFirst = true;

    void Start()
    {
        audioSource = GetComponent<AudioSource>();
    }

    void Update()
    {
        
        if (Input.GetMouseButtonDown(0))
        {
        	//播放手雷扔出的音效
            audioSource.Play();
            if (isFirst)
            {
                ThrowGranade();
                isFirst = false;
            }
        }

    }

    void ThrowGranade()
    {
        GameObject granade = Instantiate(GranadePrefab,transform.position, transform.rotation);

        Rigidbody rb = granade.GetComponent<Rigidbody>();

        rb.AddForce(transform.forward * throwerForce,ForceMode.VelocityChange);

    }
}

代碼解釋:
掛載到相機上,按下鼠標左鍵時,添加一個向前的力,這樣手雷就扔出去了,我後期想加上拋物線,後面在改進,這樣就可以實現真正的手雷模擬器(無情)

完整的演示圖:
在這裏插入圖片描述

本回合完,預知後事如何,且看下回分解(有讚的觀衆老爺能不能點一下贊,手寫了三篇)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章