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

Unity notes - 12 - exercise item weapon module - Second Edition ...
Planning - weapons module
requirement analysis
Script implementation and explanation
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); } }

30 September 2021, 16:52 | Views: 7826

Add new comment

For adding a comment, please log in
or create account

0 comments