问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Unity3D FPS游戏开发:实现武器发射子弹功能

创作时间:
作者:
@小白创作中心

Unity3D FPS游戏开发:实现武器发射子弹功能

引用
CSDN
1.
https://blog.csdn.net/qq_40306845/article/details/143279309

本教程将详细介绍如何在Unity3D中实现一个简单的第一人称射击(FPS)游戏中的武器发射子弹功能。通过本教程,你将学会如何创建子弹模型、编写子弹控制器脚本以及实现连续发射子弹的逻辑。

子弹

子弹发射位置

在Weapon01下面新建一个GameObject用来设置发射子弹的位置,调整Position放在枪口位置。

子弹模型

子弹模型

在下面路径找到子弹模型,然后拖入到项目中,并右键Prefab-unpack(为了避免影响到原本素材中的预制体)。

子弹材质

然后子弹模型本身是没有材质的,和我们之前拖入枪模型的时候一样,找到下面路径的材质,给它附上。

子弹完整代码

思路

思路非常简单,子弹生成后,应该朝着前方移动一定距离,后销毁。

代码

新建C#代码,BulletController,挂载在Bullet01上。设置两个参数,移动速度和移动距离。子弹的移动和物理相关,所以使用FixedUpdate进行更新。

public class BulletController : MonoBehaviour
{
    [Header("子弹数值")]
    public float bulletSpeed=1000;// 移动速度
    public float range = 10000;// 移动距离
    private void FixedUpdate()
    {
        transform.position+=transform.forward *bulletSpeed * Time.fixedDeltaTime;// 每次移动位移
        range -= bulletSpeed * Time.fixedDeltaTime;// 每次移动范围减少
        if (range <= 0)
        {
            Destroy(this.gameObject);// 抵达范围终点,销毁
        }
    }
}

子弹预制体

把子弹命名为Bullet01,然后拖拽到文件夹中生成预制体。默认子弹模型的大小还挺小的,记得缩放Scale到自己能看到的大小,我设置了0.5倍。

发射子弹代码

思路

参数

我们需要实现发射子弹,并且按下左键连续发射子弹,而且还有弹夹数量。会需要如下的参数,发射子弹得有发射位置和子弹的预制体;连续发射子弹得判断发射状态和子弹的间隔时间;弹夹数量得有弹夹总数和当前子弹数。

[Header("子弹数值")]
public Transform shootPoint;// 子弹发射位置
public GameObject bullet;// 子弹预制体
public float shootInterval = 1;// 子弹间隔时间
private bool isFire;// 发射状态
public int bulletNum = 100;// 弹夹
public int currentBulletNum;// 当前子弹的数量

功能

按下左键后,开启发射子弹;松开左键后,停止发射子弹。

private void OpenFire()
{
    if (Input.GetMouseButtonDown(0))
    {
        isFire = true;
        StartCoroutine("Shoot");
    }
    if (Input.GetMouseButtonUp(0))
    {
        isFire = false;
        StopCoroutine("Shoot");
    }
}

发射子弹就是创建子弹,每个子弹生产间隔一段时间。弹夹,产生一个子弹将数量减少,子弹数量为了0的时候将不生产。可以用和上一篇武器瞄准的协程方法,只不过间隔不是帧数而是时间。

IEnumerator Shoot()
{
    while (isFire)
    {
        if (currentBulletNum >0)
        {
            GameObject newBullet = Instantiate(bullet, shootPoint);
            currentBulletNum--;
        }
        yield return new WaitForSeconds(shootInterval);// 间隔一定时间再发射下一个子弹
    }
}

完整代码

WeaponController更新后的完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponController : MonoBehaviour
{
    [Header("武器数值")]
    public Vector3 defaultPosition;// 默认位置
    public Vector3 centerPosition;// 中心位置
    public float positionLerpRatio = 0.5f;// 线性插值参数
    [Header("子弹数值")]
    public Transform shootPoint;// 子弹发射位置
    public GameObject bullet;// 子弹预制体
    public float shootInterval = 1;// 子弹间隔时间
    private bool isFire;// 发射状态
    public int bulletNum = 100;// 弹夹
    public int currentBulletNum;// 当前子弹的数量
    void Start()
    {
        // 自己在Unity中挪位置试出来的
        defaultPosition = new Vector3(0.4F, -0.6F, 1.15F);
        centerPosition = new Vector3(0F, -0.6F, 0.807F);
        currentBulletNum = bulletNum;
    }
    void Update()
    {
        ChangePosition();
        OpenFire();
    }
    private void OpenFire()
    {
        if (Input.GetMouseButtonDown(0))
        {
            isFire = true;
            StartCoroutine("Shoot");
        }
        if (Input.GetMouseButtonUp(0))
        {
            isFire = false;
            StopCoroutine("Shoot");
        }
    }
    IEnumerator Shoot()
    {
        while (isFire)
        {
            if (currentBulletNum >0)
            {
                GameObject newBullet = Instantiate(bullet, shootPoint);
                currentBulletNum--;
            }
            yield return new WaitForSeconds(shootInterval);
        }
    }
    private void ChangePosition()
    {
        // 按下左键
        if (Input.GetMouseButtonDown(1))
        {
            StopCoroutine("ToDefault");
            StartCoroutine("ToCenter");
        }
        // 松开左键
        if (Input.GetMouseButtonUp(1))
        {
            StopCoroutine("ToCenter");
            StartCoroutine("ToDefault");
        }
    }
    IEnumerator ToCenter() {
        while (transform.localPosition!=centerPosition)
        {
            transform.localPosition = Vector3.Lerp(transform.localPosition, centerPosition, positionLerpRatio);
            yield return null;// 等待一帧
        }
    }
    IEnumerator ToDefault()
    {
        while (transform.localPosition != defaultPosition)
        {
            transform.localPosition = Vector3.Lerp(transform.localPosition, defaultPosition, positionLerpRatio);
            yield return null;// 等待一帧
        }
    }
}

效果

(此处可以添加实际运行效果的截图或视频,以增强文章的直观性和说服力)

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号