[Unity] Third-person shooter game development process fire design (TPS.S.P2)

[Unity] Third-person shooter game development process fire design (TPS.S.P2)


In this chapter, we will design the basic firearm functions.

firearms firing

The weapon I choose now is 416, so the data will be some data of 416.

firing process

The first step is to find the muzzle. We've done the aiming point before, now we just need to let the bullet emerge from the muzzle and fly to the aiming point.
Naturally, this shooting logic depends on your ideas. Whether it is a ray shooting or a solid bullet; whether it is flying out of the scope or the muzzle; whether it is based on the aiming point or the actual direction of the muzzle as the flight direction.

Preparations before firing

Since we are generating a physical bullet from the muzzle, we need to prepare the bullet entity and the position of the muzzle.

Physical bullet preparation

First of all, although our bullets are solid, we don't need a model for them. We just want to visualize the ballistics. So our bullet design is like this:
1. Collider and rigid body are used to ensure that it can collide with other objects;
2. It has a trajectory.
Let's talk about ballistics here. There is a TrailRenderer (trailer renderer) in Unity. We add this component to the bullet.
This red curve represents the width change of our trail over the lifetime. There are also things such as color changes, survival time, materials, etc.
insert image description here
Our trailing tail is pulled in the editor and found to be pink, which means that no material has been added to it. Let's create one for it. Create a material, Shader selects Legacy Shaders/Particles/Additive, this material represents that its property is a particle effect. Set the color
insert image description here
OK, let's add this material for the trail
insert image description here
and let's make it a prefab. The muzzle is simply setting an empty object to mount on the muzzle.

fire logic

This code I'm hanging on the gun.
We first get the attribute

	[Header("Firing")]
    [Tooltip("是否为全自动")]
    [SerializeField]
    private bool automatic;
    [Tooltip("子弹飞行速度")]
    [SerializeField]
    private float _ammoSpeed;

    [Header("BaseSettings")]
    [Tooltip("枪口")]
    [SerializeField]
    private Transform muzzle;
    [Tooltip("瞄准点")]
    [SerializeField]
    private Transform targetpoint;
    [Tooltip("子弹")]
    [SerializeField]
    private GameObject _ammo;

    private PlayerInputsMassage _inputMessage;
    [Tooltip("子弹的对象池")]
    private ObjectPool<GameObject> ammoPool;

Here I consider using an object pool to manage bullets.
There are still many problems with the object pool, and you can use common methods to deal with them. The problem that will appear in the object pool is the ballistic display. Before I find a solution to this problem, I do not recommend you to use the object pool.
Then create an object pool in Start. Before creating an object pool, you must first design a class for bullets to do collision-related things.
Here we design an event as a collision event. Then you can add the corresponding method in Gun to let the bullet execute.

public UnityEvent destroyEvent = new UnityEvent();

    public bool isDestroy;
    private void OnEnable()
    {
    
    
        isDestroy = false;
    }
    private void OnTriggerEnter(Collider other)
    {
    
    
        if (!other.CompareTag("Gun") && !isDestroy)
        {
    
    
            isDestroy = true;
            destroyEvent?.Invoke();
        }
    }
		_inputMessage = FindObjectOfType<PlayerInputsMassage>();
        ammoPool = new ObjectPool<GameObject>(
            () =>
            {
    
    
                var ammo = Instantiate(_ammo, muzzle);
                ammo.AddComponent<AmmoBehavier>().destroyEvent.AddListener(() =>
                {
    
    
                    ammoPool.Release(ammo);
                }
                );
                return ammo;
            },
            (go) =>
            {
    
    
                go.SetActive(true);
                go.transform.position = muzzle.position;
            },
            (go) =>
            {
    
    
                go.SetActive(false);
            },
            (go) => {
    
     Destroy(go); }
            );

Next we write a Fire method.
Here we use the get of the object pool instead of the usual generation. Generation is handled by the object pool.

public void Fire()
    {
    
    
        Quaternion rotation = Quaternion.LookRotation(targetpoint.position - muzzle.position);
        GameObject ammo = ammoPool.Get();
        ammo.transform.rotation = rotation;
        ammo.GetComponent<Rigidbody>().velocity = ammo.transform.forward * _ammoSpeed;
    }

Next, we set up a very useful thing: EventHandler
can be considered as a class dedicated to handling events. We will use it to write many cross-script codes, which will be very convenient to call.

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

public static class EventHandler
{
    
    
    public static event Action WeaponFire;
    public static void CallWeaponFire()
    {
    
    
        WeaponFire?.Invoke();
    }
}

In this way, the fire event is written. We only need to write each code that needs to handle the content related to fire as a method, then add it to this event, and then trigger this method by the fire button. Let's briefly demonstrate it next (note that our firing method and trigger are written in the Gun here, but when it comes to switching firearms, we will separate them)

private void OnEnable()
    {
    
    
        EventHandler.WeaponFire += Fire;//在该脚本启用时添加该方法
    }

    private void OnDisable()
    {
    
    
        EventHandler.WeaponFire -= Fire;//在该脚本停用时撤销该方法
    }

In this way, the registration of the method is achieved, and the next step is the call. The call can be placed anywhere. I just wrote it in the hope of separating the movement of the character from the shooting. Otherwise, the character's control script will be very bloated.

private void Update()
    {
    
    
        if(_inputMessage.fire&&_inputMessage.aim)
        {
    
    
            EventHandler.CallWeaponFire();
        }
    }

The content of this chapter is here for the time being. Since some problems have not been resolved, this chapter may be more likely to be revised later.

Guess you like

Origin blog.csdn.net/weixin_52540105/article/details/128207612