Unity notes - 12 - exercise item weapon module

Unity notes - 12 - exercise item weapon module

plan

If the magazine is loaded with bullets, it can be fired; Otherwise, wait for magazine replacement;

When firing bullets, play sound effects, animation and display sparks;

The player's gun can be single shot or continuous shot;

Player bullet

  1. HP of the enemy will be reduced after hitting the enemy, and HP of different degrees will be reduced according to the position of hitting the enemy
  2. The bullet flies to the target point, destroys it, and creates the corresponding special effects

Enemy bullet

  1. After hitting the player, the player's HP is reduced
  2. The bullet flies to the target point, destroys it, and creates the corresponding special effects
  3. Shoot at the player's head. The flight speed is slow, which is convenient for players to avoid

requirement analysis

Create script: the player Gun gun provides the function of firing and changing magazine

Create script: single shot mode SingleGun, inherited from Gun, and call the corresponding firing method according to the player's input

Create script: automatic Gun in continuous firing mode, inherited from Gun, and call the corresponding firing method according to the player's input

Create script: enemy gun EnemyGun, which provides automatic firing function and unlimited ammunition

-------------------

Create script: Bullet bullet, calculate the target point of attack, execute movement, and create contact effects;

Players detect the environment and enemies; Enemy detection environment;

Create script: player Bullet PlayerBullet, inherited from the Bullet, and HP will be deducted after hitting the enemy

Create script: enemy bullet EnemyBullet, deduct HP after hitting the player

Note: for all the above special effects, sound related will not be realized temporarily

Function disassembly and gradual realization

Player gun

The player's gun script should be implemented: check the magazine, create bullets, and switch the shooting mode

To fire bullets, the gun is roughly divided into the following steps: check the magazine, create bullets, fire bullets, hit the target, and deduct the target HP

Check magazine

If there is a bullet in the magazine, it can be fired, otherwise it can't be fired

Here you need three variables to store: the total number of bullets you have allBullet; Magazine capacity boxMagazine; Number of bullets in the current magazine currentBullet

When your magazine needs to be filled, the corresponding number of bullets will be deducted from the total number of bullets;

When there is no bullet in the magazine, the bullet cannot be fired;

When the total number of bullets returns to zero, the magazine cannot be filled;

Create bullet

Need to obtain: Bullet object template; Muzzle position; Muzzle direction

Bullet object template

It needs to be obtained through the resource path. Write the relative path here. Create a Resources file in Assets. Note that R should be capitalized

Specific methods: resources. Load < GameObject > ("guntest / bullet / playerbullet");

Note that the path here is relative and should be written from the folder in the Resources you created. For example, the path of the player's bullet preform here is:

Assets/Resources/GunTest/Bullet/PlayerBullet, so I should write the path of GunTest/Bullet/PlayerBullet in this method.

Muzzle position

The muzzle position can be obtained by transforming the muzzle position into world coordinates by using the transform.TransformPoint() method

Muzzle direction

Transform.forward generally uses this. I use transform.right because the muzzle direction of the preform is the x-axis when making the model

Create bullet

Use the object. Instance (object template, create point, initial orientation) method

GameObject Bullet = Object.Instantiate(bullet, transform.TransformPoint(Vector3.right), transform.rotation);

The initial orientation is consistent with the muzzle

It should be noted that when making the model, the axis of the bullet should be consistent with the axis of the muzzle. I have set the muzzle as X axis, so the axis of the bullet should also be x axis, otherwise the animation will be very strange

After creation, you need to configure the bullet firing direction and layer.

To launch a bullet, you need to obtain the firing direction (i.e. muzzle direction, which is assigned here first)

Launch bullets, hit the target, reduce HP and other functions will be explained in detail in bullets

Switch firing mode

Here, you only need to press the B key to enable and close the script. It is relatively simple and will not be explained

Complete code

/// <summary>
///Guns
/// </summary>
public class GunDemo : MonoBehaviour
{
    /// <summary>
    ///Bullet type
    /// </summary>
    protected GameObject bullet;
    /// <summary>
    ///Layer, which will not be described here for the time being. Select the default in the Inspector
    /// </summary>
    public LayerMask mask;
    /// <summary>
    ///Magazine capacity
    /// </summary>
    private int boxMagazine=20;
    /// <summary>
    ///Number of bullets in the current magazine
    /// </summary>
    public int currentBullet;
    /// <summary>
    ///Total bullets
    /// </summary>
    public int allBullet;
    /// <summary>
    ///Initialization
    /// </summary>
    protected virtual void Start()
    {
        //Initialize total bullets
        allBullet = 100;
        //Obtain bullet resources
        bullet = GetResource();
        //Initial default single point mode
        GetComponent<SingleGunDemo>().enabled = true;
        GetComponent<AutomaticGunDemo>().enabled = false;
    }
    /// <summary>
    ///Fire
    /// </summary>
    protected virtual void Firing()
    {
        //Prepare the bullet
        //Determine whether the magazine contains bullets
        if (currentBullet > 0)
        {
            //Create bullet
            GameObject Bullet = Object.Instantiate(bullet, transform.TransformPoint(Vector3.right), transform.rotation);
            //Get the script component of the bullet object
            PlayerBulletDemo playerBullet = Bullet.GetComponent<PlayerBulletDemo>();
            //Configure firing direction
            playerBullet.direction =transform.right;
            playerBullet.mask = mask;
            //Fire bullets
            playerBullet.Firing();
            currentBullet--;
            //Create bullets, play audio, play animation
        }
        else
        {
            Debug.Log("No Bullet");
            //It indicates that there are no bullets and the magazine needs to be changed
        }

    }
    /// <summary>
    ///Get bullet resource file
    /// </summary>
    /// <returns></returns>
    private GameObject GetResource()
    {
              return Resources.Load<GameObject>("GunTest/Bullet/PlayerBullet");
    }
    /// <summary>
    ///Replace magazine
    /// </summary>
    protected void UpdateAmmo()
    {
        if (allBullet > 0&&currentBullet<boxMagazine)
        {
            int add = boxMagazine - currentBullet;
            if (add <= allBullet)
            {
                allBullet -= add;
                currentBullet += add;
            }
            else
            {
                currentBullet += allBullet;
                allBullet = 0;
            }
        }
        else
        {
            Debug.Log("FullorNone");
            //It indicates that there are no bullets or the magazine is full
        }
    }
    protected void Update()
    {
        //There is no collimation here for the time being. First use the line to indicate the muzzle direction
        Debug.DrawLine(transform.position,transform.TransformPoint(100*Vector3.right));
        if (Input.GetKeyDown(KeyCode.B))
        {
            //Switch mode
            GetComponent<SingleGunDemo>().enabled = !GetComponent<SingleGunDemo>().enabled;
            GetComponent<AutomaticGunDemo>().enabled=!GetComponent<AutomaticGunDemo>().enabled; 
        }
    }
}

Single shot mode and continuous shot mode

The only difference is whether to use GetKey or GetKeyDown. It's relatively simple and direct to the code

public class SingleGunDemo : GunDemo
{
    /// <summary>
    ///Initialization
    /// </summary>
    protected override void Start()
    {
        base.Start();
    }
    private void Update()
    {
        base.Update();
        if (Input.GetKeyDown(KeyCode.O))
        {
            base.Firing();
        }
        if (Input.GetKeyDown(KeyCode.R))
        {
            base.UpdateAmmo();
        }
    }
}
public class AutomaticGunDemo :GunDemo
{
    /// <summary>
    ///Initialization
    /// </summary>
    protected override void Start()
    {
        base.Start();
    }
    private void Update()
    {
        base.Update();
        if (Input.GetKey(KeyCode.O))
        {
            base.Firing();
        }
        if (Input.GetKeyDown(KeyCode.R))
        {
            base.UpdateAmmo();
        }
    }
}

Bullets and player bullets

bullet

Note: when the player creates bullets from the gun, the shooting direction and layer will be configured

Bullets need to calculate the shooting target points of players. The main method is ray detection to obtain the shooting target points

There is no bullet parabola here. Instantaneous shooting is used for the time being.

Ray detection method: physics. Raycast (ray starting point, direction vector, out output object, distance, layer)

The detected target hit is obtained through radiographic testing, and then the target point is assigned to targetPos

public class BulletDemo : MonoBehaviour
{
    /// <summary>
    ///Layers
    /// </summary>
    public LayerMask mask;
    /// <summary>
    ///Muzzle orientation
    /// </summary>
    [HideInInspector]
    public Vector3 direction;
    /// <summary>
    ///Radiographic object
    /// </summary>
    protected RaycastHit hit;
    /// <summary>
    ///Hit the target position
    /// </summary>
    public Vector3 targetPos;
    /// <summary>
    ///Calculate target point
    /// </summary>
    protected void BulletHit()
    {
        if (Physics.Raycast(this.transform.position, direction, out hit, 100, mask))
        {
            //Detected
            targetPos = hit.point;
        }
        else
        {
            targetPos = transform.position + transform.right * 5;
        }
        //Create special effects at target points
    }
    /// <summary>
    ///Shooting virtual method
    /// </summary>
    public virtual void Firing()
    {

    }
}

Player bullet

If the player shoots with a gun, he can call the fitting method

The bullet will be teleported to the target point to cause damage through the target obtained (lazy here). The corresponding script component will be obtained through the target detected by ray. HP will be deducted and the object will be destroyed if HP is returned to zero

public class PlayerBulletDemo : BulletDemo
{
    public override void Firing()
    {
        BulletHit();
        transform.position = targetPos;
        if (hit.collider!= null)
        {
            if (hit.collider.tag == "Enemy")//If it's the enemy
            {
                Debug.Log("touch it");
                hit.collider.GetComponent<EnemyDemo>().HP -= 10;//Buckle blood
                if (hit.collider.GetComponent<EnemyDemo>().HP <= 0)
                {
                    Destroy(hit.collider.gameObject);
                }
                DestroyImmediate(this.gameObject);
            }
        }
    }
}

Enemy gun

Similar to the player's gun, the bullet will automatically shoot without ray detection. After creation, the bullet will automatically move in the positive direction, and HP will be deducted if it touches the player

Set the attack interval and shoot once every 1.5s

public class EnemyGunDemo : MonoBehaviour
{
    //The enemy has unlimited bullets. The bullets are slow and can be caught by the naked eye
    public LayerMask mask;
    private GameObject bullet;
    private float FiringTime;

    private void Start()
    {
        FiringTime = 0;
        bullet = GetResources();
    }
    private void Firing()
    {
        GameObject Bullet = Object.Instantiate(bullet, transform.TransformPoint(Vector3.right), transform.rotation);
    }
    private GameObject GetResources()
    {
        return Resources.Load<GameObject>("GunTest/Bullet/EnemyBullet");
    }

    private void Update()
    {
        if (FiringTime > 1.5)
        {
            Firing();
            FiringTime = 0;
        }
        else
        {
            FiringTime += Time.deltaTime;
        }
    }
}

Enemy bullet

public class EnemyBulletDemo : MonoBehaviour
{
    //In order to enable players to avoid enemy bullets, they do not use rays, but use triggers and set a slower speed so that players can have a chance to avoid them
    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Player")//If it's a player
        {
            //If you contact the player
            other.GetComponent<PlayerDemo>().HP -= 1;
            //Players deduct blood
            if (other.GetComponent<PlayerDemo>().HP <= 0)
            {
                Destroy(other.gameObject);
            }
        }
        Destroy(this.gameObject);
    }
    private void Update()
    {
        transform.Translate(0, Time.deltaTime * 5, 0);
      //Auto destroy in 5 seconds
        Destroy(this.gameObject, 5);
    }
}

Note: if the bullet model orientation and muzzle orientation are different, remember to adjust the bullet orientation separately

problem

In the above code, whether the magazine should be a separate class. If it is written as above, the single engine and continuous engine do not share a magazine, which is unscientific. Therefore, the magazine should be a separate class

Keywords: C# Unity

Added by saadshams on Tue, 28 Sep 2021 12:29:15 +0300