FPS游戏开发(3)

闲杂:

想玩游戏的时候就来写博客,其实我个人的感觉写博客就跟写书是一样的吗,写书是将内心的故事呈现给读者,而写博客就是将技术呈现给读者,一方面我们可以将自己的技术分享出来供大家学习,第二个是希望大家可以给我的技术做一些指点,互相学习互相交流,希望能在评论区多多留言,我也可以解决疑难杂症。

故事开始:

在FPS的游戏开发当中设计到枪械的方面,手雷的方面,近战武器,以及一些特殊的道具,所以这些模块值得去深挖和细品,古人云:彩虹风雨后,成功细节中(我也不知道是哪个古人说的)

我的思路,搭建场景,然后给box添加上Rigibody组件(不要给地面也添加该组件,会出现很奇怪的情况,如果想试一试的小伙伴,可以玩一下)
FPS游戏开发(3)_第1张图片
接下来就是Granade,吐槽一下,我的第一版手雷和上面的箱子一样大,由于太过搞笑所以我就弄了手雷2.0,看起来就舒服多了
FPS游戏开发(3)_第2张图片
接下来就是脚本方面了,我的思路是这样的,首先是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);
FPS游戏开发(3)_第3张图片
在官方文档中,讲到了参数和使用方法。我解释一下返回Collider数组的作用,这里是将球形范围内的所有包含Collder组件的物体都存起来,接下来遍历球体内物体上的Rigibody组件,然后可以给含有该组件的物体添加爆炸力度,爆炸力是手雷来提供的,这样就实现了手雷爆炸击飞箱子。
rb.AddExplosionForce(force,transform.position, radius);
FPS游戏开发(3)_第4张图片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上,如图
FPS游戏开发(3)_第5张图片
最后是控制手雷的扔出,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);

    }
}

代码解释:
挂载到相机上,按下鼠标左键时,添加一个向前的力,这样手雷就扔出去了,我后期想加上抛物线,后面在改进,这样就可以实现真正的手雷模拟器(无情)

完整的演示图:

本回合完,预知后事如何,且看下回分解(有赞的观众老爷能不能点一下赞,手写了三篇)

你可能感兴趣的:(游戏)