Unity notes - 12 - exercise item weapon module - Second Edition

Unity notes - 12 - exercise item weapon module - Second Edition

Planning - weapons module

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

Script implementation and explanation

Player part

Player status

It also provides a reference to the player as a unique object so that all other objects can obtain the player object

Provide methods of injury, death, etc

public class PlayerDemo : MonoBehaviour
{
    //Provides the current object reference
    public static PlayerDemo Instance { get; private set; }
    public float HP;
    private void Start()
    {
        Instance = this;
        HP = 100;
    }
    /// <summary>
    ///Wounded
    /// </summary>
    ///< param name = "attacknumber" > injury number < / param >
    public void Damage(int attackNumber)
    {
        HP -= attackNumber;
        if (HP <= 0)
        {
            Death();
        }
    }
    /// <summary>
    ///Death
    /// </summary>
    private void Death()
    {
        Destroy(this.gameObject);
    }
}

gun

Boxmagazine magazine

The magazine class provides data such as magazine capacity, total bullets and current bullets. It is hung on the parent empty object of the gun model object

public class BoxMagezineDemo : MonoBehaviour
{
    /// <summary>
    ///Magazine capacity
    /// </summary>
    public int boxMagazine = 50;
    /// <summary>
    ///Number of bullets in the current magazine
    /// </summary>
    public int currentBullet;
    /// <summary>
    ///Total bullets
    /// </summary>
    public int allBullet;
}
GunAnimation - gun animation

The gun animation class provides a series of animation playback functions of the gun

AnimationTool class is an animation and animation tool class, which will be described later. It is hung on the parent empty object of the gun model

public class GunAnimation : MonoBehaviour
{
    /// <summary>
    ///Fire animation
    /// </summary>
    public string fireAnimation="Gunfire";
    /// <summary>
    ///Replace magazine animation
    /// </summary>
    public string updateAmmoAnimation="GunUpdateAmmo";
    /// <summary>
    ///Missing bullet animation
    /// </summary>
    public string lackBulletAnimation="GunLackBullet";
    /// <summary>
    ///Playback tool
    /// </summary>
    public AnimationTool action;

    private void Awake()
    {
        action = new AnimationTool(GetComponentInChildren<Animation>());
    }
}
BulletLight - bullet fire

The muzzle firelight object script provides the function of flashing firelight effect and hangs on the firelight object. The firelight object is the child of the parent empty object of the gun model, that is, the brother of the gun model object

public class BulletLightDemo : MonoBehaviour
{
    private GameObject bulletLight;
    private void Start()
    {
        bulletLight = GetResource();
        
    }
    /// <summary>
    ///The fire flickered
    /// </summary>
    public void DisplayLight()
    {
        Destroy(Instantiate(bulletLight, transform.position, Quaternion.identity),0.20F);
    }
    private GameObject GetResource()
    {
        return Resources.Load<GameObject>("GunTest/Bullet/BulletLight");
    }
}
Gun gun

The parent class of the player's shooting mode provides functions such as shooting and filling the magazine. Note: this script is not hung on the object. What is hung on the object is the shooting mode inherited from this class: SingleGun and AutomaticGun. The shooting mode script is hung on the parent empty object of the gun model object

--------------------------—

Shooting

It is divided into the following two steps: 1. Preparation stage: whether it can shoot; 2. Create bullets;

Preparation stage:

  1. Is there a bullet in the magazine
  2. Is the magazine change animation currently playing
    /// <summary>
    ///Bullet preparation
    /// </summary>
    /// <returns></returns>
    private bool Ready()
    {
        if (boxMagezine.currentBullet <= 0)
        {
            anim.action.Play(anim.lackBulletAnimation);//If there are no bullets, play the animation prompt and return false
            return false;
        }
        if (anim.action.isPlay(anim.updateAmmoAnimation))//If you are changing bullets, return false
            return false;
        return true;
    }

Create bullet

  1. Ready
  2. Create bullet
  3. Play shooting animation and firelight objects

Method of creating bullet object: object. Instance (object template, creation point, initial orientation) method

    /// <summary>
    ///Fire
    /// </summary>
    ///< param name = "direction" > muzzle direction < / param >
    protected virtual void Firing(Vector3 direction)
    {
        //Prepare the bullet
        //Determine whether ready for launch
        if (!Ready()) return;
        //Player gun firing, muzzle direction
        //Create bullet
        //The orientation here can be Quaternion.LookRotation, but since the Z axis here is not the bullet orientation, I can only change it separately
        GameObject Bullet = Instantiate(bullet, transform.TransformPoint(Vector3.right), Quaternion.identity);
        //Since the bullet orientation here is the Y-axis, I want to assign the muzzle direction to the Y-axis direction of the bullet object
        Bullet.GetComponent<Transform>().up = direction;
        //Play shooting animation
        anim.action.Play(anim.fireAnimation);
        //Play firelight object
        bulletLight.DisplayLight();
        //Play audio
        //audioSource.PlayOneShot(audio);
        //The number of bullets in the magazine is reduced by 1
        boxMagezine.currentBullet--;
    }

--------------------------—

Filling magazine

When the total number of bullets is not 0 or the number of bullets in the current magazine is less than the magazine capacity, it is allowed to fill the magazine

Fill the number of bullets in the magazine and subtract the corresponding number from the total number of bullets. If it cannot be filled, fill all the remaining bullets into the magazine and return the total number of bullets to zero

    /// <summary>
    ///Filling magazine
    /// </summary>
    protected void UpdateAmmo()
    {
        if (boxMagezine.allBullet > 0&& boxMagezine.currentBullet < boxMagezine.boxMagazine)
        {
            anim.action.Play(anim.updateAmmoAnimation);//Play the fill magazine animation
            int add = boxMagezine.boxMagazine - boxMagezine.currentBullet;
            if (add <= boxMagezine.allBullet)
            {
                boxMagezine.allBullet -= add;
                boxMagezine.currentBullet += add;
            }
            else
            {
                boxMagezine.currentBullet += boxMagezine.allBullet;
                boxMagezine.allBullet = 0;
            }
        }
        else
        {
            Debug.Log("FullorNone");
            //It indicates that there are no bullets or the magazine is full
        }
    }

--------------------------—

Change firing mode
    /// <summary>
    ///Switch firing mode
    /// </summary>
    private void ChangeFiringMethod()
    {
        if (Input.GetKeyDown(KeyCode.B))
        {
            //Switch mode
            GetComponent<SingleGunDemo>().enabled = !GetComponent<SingleGunDemo>().enabled;
            GetComponent<AutomaticGunDemo>().enabled = !GetComponent<AutomaticGunDemo>().enabled;
        }
    }

--------------------------—

Various resources and descriptions for initializing Gun

Main fields

    /// <summary>
    ///Bullet type
    /// </summary>
    protected GameObject bullet;
    /// <summary>
    ///Magazine
    /// </summary>
    private BoxMagezineDemo boxMagezine;
    /// <summary>
    ///Gun animation script component
    /// </summary>
    private GunAnimation anim;
    /// <summary>
    ///Muzzle firelight object
    /// </summary>
    private BulletLightDemo bulletLight;

initialization

    protected virtual void Start()
    {
        //Initialize magazine
        boxMagezine = GetComponent<BoxMagezineDemo>();
        //Initialize firelight object
        bulletLight = transform.GetChild(1).GetComponent<BulletLightDemo>();
        //Initialize animated objects
        anim = GetComponent<GunAnimation>();
        //Initialize total bullets
        boxMagezine.allBullet = 1000;
        //Obtain bullet resources
        bullet = GetResource();
        //Initial default single point mode
        GetComponent<SingleGunDemo>().enabled = true;
        GetComponent<AutomaticGunDemo>().enabled = false;
    }

Read resources from resource file

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.

    /// <summary>
    ///Get bullet resource file
    /// </summary>
    ///< returns > resource object < / returns >
    private GameObject GetResource()
    {
              return Resources.Load<GameObject>("GunTest/Bullet/PlayerBullet");
    }
SingleGun single shot mode

Hang on the parent empty object of the gun model

/// <summary>
///Single shot mode
/// </summary>
public class SingleGunDemo : GunDemo
{
    /// <summary>
    ///Initialization
    /// </summary>
    protected override void Start()
    {
        //Initialize parent resource
        base.Start();
    }
    private void Update()
    {
        //Call parent class update
        base.Update();
        //Shooting
        Fire();
    }
    /// <summary>
    ///Shoot
    /// </summary>
    private void Fire()
    {
        if (Input.GetKeyDown(KeyCode.O))
        {
            base.Firing(transform.right);
        }
        if (Input.GetKeyDown(KeyCode.R))
        {
            base.UpdateAmmo();
        }
    }
}
AutomaticGun burst mode

Hang on the parent empty object of the gun model

Similar to the single shot mode, the only difference is the selection of GetKey method

/// <summary>
///Continuous mode
/// </summary>
public class AutomaticGunDemo :GunDemo
{
    /// <summary>
    ///Initialization
    /// </summary>
    protected override void Start()
    {
        //Initialize parent resource
        base.Start();
    }
    private void Update()
    {
        //Call parent class update
        base.Update();
        //Shooting
        Fire();
    }
    /// <summary>
    ///Shoot
    /// </summary>
    private void Fire()
    {
        if (Input.GetKey(KeyCode.O))
        {
            base.Firing(transform.right);
        }
        if (Input.GetKeyDown(KeyCode.R))
        {
            base.UpdateAmmo();
        }
    }
}

bullet

Bullet bullet

The parent class of all player bullet types, which provides functions such as ray detection

Definition of various parameters
    /// <summary>
    ///Layers
    /// </summary>
    public LayerMask mask;
    /// <summary>
    ///Radiographic object
    /// </summary>
    protected RaycastHit hit;
    /// <summary>
    ///Hit the target position
    /// </summary>
    public Vector3 targetPos;
Radiographic testing

Radiographic testing method: physics. Raycast (starting point, direction vector, out output detected object information, distance, layer)

Here, the direction vector should be set as the bullet orientation. When I model the bullet, the direction is the y-axis, so it is transform.up, generally transform.forward

After the object is detected, assign the corresponding position to targetPos and store the target position. If it is not detected, the position will move 100 units towards the target

    /// <summary>
    ///Calculate target point
    /// </summary>
    public void BulletHit()
    {
        if (Physics.Raycast(this.transform.position,transform.up, out hit, 100, mask))
        {
            //Detected
            targetPos = hit.point;
        }
        else
        {
            targetPos = transform.position +transform.up* 100;
        }
        //Create special effects at target points
    }
PlayerBullet - player bullet

It inherits the Bullet and provides functions such as the Bullet flying to the target point and judging whether it hit or not

Initialize bullet target point

Call the BulletHit method of the parent class to obtain the target point

    private void Start()
    {
        BulletHit();
    }
Judge whether to hit the enemy

Judge whether the object is an enemy through the label on the object. If so, call the other party's injury method to deduct HP

    /// <summary>
    ///Contact judgment
    /// </summary>
    private void Touch()
    {
        if ((targetPos - transform.position).sqrMagnitude < 0.1f)
        {
            if (hit.collider.tag == "Enemy")//If it's the enemy
            {
                hit.collider.GetComponent<EnemyDemo>().Damage(10);//Buckle blood
                DestroyImmediate(this.gameObject);
            }
            else
            {
                Destroy(this.gameObject);
            }
        }
    }
The bullet flew to the target point

Note that if no unit is detected, hit is null. Therefore, null judgment should be added to prevent abnormalities. The bullet will destroy the object immediately after flying to the target point

    /// <summary>
    ///The bullet flew to the target point
    /// </summary>
    private void Move()
    {
        transform.position = Vector3.MoveTowards(transform.position, targetPos, 50 * Time.deltaTime);
        if (hit.collider != null)
        {
            Touch();
        }
        else
        {
            if ((transform.position - targetPos).sqrMagnitude < 0.1f)
            {
                Destroy(this.gameObject);
            }
        }
    }

Enemy part

Enemy status

Provide methods for enemy injury, death, etc

public class EnemyDemo : MonoBehaviour
{
    [HideInInspector]
    public EnemyProduce produce;
    public float HP;
    private void Start()
    {
        HP = 100;
    }
    /// <summary>
    ///Wounded
    /// </summary>
    ///< param name = "attacknumber" > injury number < / param >
    public void Damage(int attackNumber)
    {
        HP -= attackNumber;
        if (HP <= 0)
        {
            Death();
        }
    }
    /// <summary>
    ///Death
    /// </summary>
    private void Death()
    {
        Destroy(this.gameObject);
        //Set route becomes available
        this.GetComponent<EnemyAI>().wayLine.IsUsable = true;
        //Tell the generator that the unit has died and the current number of survivors is - 1
        produce.aliveCount--;
    }
}

gun

EnemyGun - enemy gun

The enemy has unlimited ammunition and the bullet speed is slow, which is convenient for players to avoid

Definition and initialization of various parameters
    /// <summary>
    ///Bullet resources
    /// </summary>
    private GameObject bullet;
    /// <summary>
    ///Attack timing
    /// </summary>
    private float firingTime;
    /// <summary>
    ///Attack interval
    /// </summary>
    private float attackTime;
    /// <summary>
    ///Initialization
    /// </summary>
    private void Start()
    {
        firingTime = 0;
        attackTime = 1.5F;
        bullet = GetResources();
    }
Obtain bullet resources
    /// <summary>
    ///Obtain bullet resources
    /// </summary>
    /// <returns></returns>
    private GameObject GetResources()
    {
        return Resources.Load<GameObject>("GunTest/Bullet/EnemyBullet");
    }
Attack timing determination

There are two methods:

  1. Each time it is determined that the attack opportunity is greater than the attack interval, the rendered frame time is accumulated to the attack opportunity. If it is greater than the attack interval, attack and return the attack opportunity to zero
  2. Each time it is determined that the attack opportunity is less than the game time. After each attack, increase the attack opportunity by an attack interval
    /// <summary>
    ///Attack timing
    /// </summary>
    private void AttackTime()
    {
        if (firingTime > attackTime)
        {
            Firing();
            firingTime = 0;
        }
        else
        {
            firingTime += Time.deltaTime;
        }
    }
Shooting
/// <summary>
///Shoot
/// </summary>
private void Firing()
{
    GameObject Bullet = Object.Instantiate(bullet, transform.TransformPoint(Vector3.right), Quaternion.identity);
    Bullet.GetComponent<Transform>().up = transform.right;//Based on bullet orientation
}

bullet

EnemyBullet - enemy bullet

Provide bullet flight, trigger and other methods. The enemy bullets here do not use ray detection, and control the low speed

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>().Damage(1);
        }
        Destroy(this.gameObject);
    }
    private void Update()
    {
        transform.Translate(0, Time.deltaTime * 5, 0);
        Destroy(this.gameObject, 5);
    }
}

Tags: C# Unity

Posted on Thu, 30 Sep 2021 16:52:10 -0400 by warik