Homemade Unity Games tankhero-2d (2) Making enemy tanks
I am making such a tank game, which is modeled after this game (http://game.kid.qq.com/a/20140221/028931.htm). Only for the purpose of learning unity. Most of the pictures were painted by themselves, and a few were from the Internet. You can get the project source on my GitHub page (Https://github.com/bitzhuwei/TankHero-2D).
This article mainly records some of the key points of making enemy tanks (Tank1).
Originally made enemy tanks is very simple, as long as the Tankhero copy, change the map is almost. However, given the brevity and reusability of the code, this article took some thought in refactoring.
About customizing mouse arrows
The previous article describes how to customize the mouse arrows. Here's a leak. After a previous study, you can already display a custom mouse style, but the original mouse arrow still exists , what to do? Easy, just make a full- transparent png image of 1*1 pixels and assign it to the default cursor. In effect, let the default mouse style be transparent.
Enemy Tank model
This model is still made with PPT . smartart+ "Shape" solves the problem. Refer to the previous article for specific tips.
Enemy tank structure
As shown, copy one from Tankhero using duplicate and rename to Tank1. TANK1 is the enemy tank we're going to do. Its turret, base, shell start point these structures are the same.
Refactoring Tank Movement Code
Player tanks and enemy tanks have a lot in common, such as the structure of a tank object. There are also some features (moving, rotating, firing, etc.) that are both similar and different. Specifically, the player tank is directed by the mouse keyboard, the enemy tank is to be directed by the AI. The conductors are different, but the effect of the command is to move the rotating cannon, which can be handled with the same code. So I'm here to abstract a movement class that specializes in preserving command information, which separates the conductors from the performers.
Playermovement receives the information entered by the user and saves the field to the base class. Tank1movement uses AI to obtain command information and to store the fields in the base class.
In this way, in other places (different types of tanks turret, base) can be used movement m = this. Getcomponentxxx<playermovement> (); This unified way to get information on translation, rotation, destination, destination, etc.
Let's take a detailed introduction.
Rotation of the base and wheel rolling
The base part of the two tanks, only the wheel rolling part is different. The scripts used for both are tankbaserotation and wheelmovement.
The Wheelmovement code has nothing to change, except that the wheels array elements in the inspector are different.
In Tankbaserotation, this code appears:
1 Private movement Movementscript; 2 3 void Awake () 4 {5this . Getcomponentinparent<movement> (); 6 }
With the movementscript you can get the tank's movement direction movementscript.basedirection , you can update the angle of rotation of the tank base.
1 voidUpdate () {2 if(Movementscript = =NULL) {return; }3 4 varAngle = Mathf.atan2 (MOVEMENTSCRIPT.BASEDIRECTION.Y, movementscript.basedirection.x) *mathf.rad2deg;5 if(Mathf.abs (Angle- This. targetangle) >0.01f)6 {7 This. Targetangle =angle;8 This. targetrotation = Quaternion.euler (0,0, angle);9 }Ten One This. transform.rotation =Quaternion.slerp ( A This. Transform.rotation, -Quaternion.euler (0,0, Angle), -Rotationspeed *time.deltatime); the}
Turret Rotation and weapon management This eliminates the need to write two sets of rotating base scripts for two of tanks. The addition of new tanks in the future still requires only this one script.
Tankhero and TANK1 have different turret rotation centers (Rotation center) and weapons (weapons), but they use the same scripts (Tankheadrotation and Weaponmanager). The following code is also available in both scripts.
1 Private movement Movementscript; 2 3 void Awake () 4 {5This . Getcomponentinparent<movement> (); 6 }
The position of the target ( firetarget ) is preserved in the Movementscript, and it is easy to rotate the turret.
1 voidUpdate () {2 if( This. Movementscript = =NULL) {return; }3 4 vary = This. MOVEMENTSCRIPT.FIRETARGET.Y- This. transform.position.y;5 varx = This. Movementscript.firetarget.x- This. transform.position.x;6 if(Mathf.abs (y) > Quaternion.kepsilon | | Mathf.abs (x) >Quaternion.kepsilon)7 {8 This. Targetangle = Mathf.atan2 (y, x) *mathf.rad2deg;9 varAngle = This. Targetangle- This. transform.rotation.eulerangles.z;Ten This. Transform. Rotatearound ( This. Rotationcenter.position,NewVector3 (0,0,1), angle); One } A}
Tankhero is to play the home mouse cannon, enemy tanks are automatic artillery. Use Autofire to mark whether the tank is automatically fired.
1 voidUpdate () {2Passedinterval + = Time.deltatime *Ten;3 if(Passedinterval >=currentweaponconfig.interval)4 {5 if( This. autofire | | Input.getbutton ("Fire1"))6 {7Passedinterval =0;8 varBullet = Instantiate (Currentbullet, Bulletstartposition.position, This. transform.rotation) asTransform;9bullet.renderer.enabled =true;Ten varBulletfly = bullet. Getcomponent<bulletfly>(); OneBulletfly.undying =false; ABulletfly.velocity =currentweaponconfig.velocity; -Bulletfly.shooter = This. Gameobject; -Bulletfly.targetposition =Movementscript.firetarget; the } - } -}
Weapon Systems
With the new tank, we need to design a new weapon for it. Just duplicate the normalbulletweapon, then adjust the parameters of the enemy tank weapon in the Weaponconfig Assembly (the speed of the cannon is slower, or the enemy is too powerful). Assign the new weapon enemynormalbulletweapon to the TANK1 turret.
The shell is still the original one, just change a decal.
Multiple shells
Played (http://game.kid.qq.com/a/20140221/028931.htm) will find a variety of shells. Its speed and attack form are different.
That is, when different types of shells collide with something, something different happens. So I abstracted the script that controls the projectile flight and wrote the Trigger collision event in the specific subclass to handle the different shells.
Note: If you add void update () in the subclass (Normalbulletfly), then unity does not call the parent class (Bulletfly) Update method. This applies to awake and so on. That is, the unity engine finds only those event functions that are farthest from Monobehaviour at the inheritance level, and then no longer cares about the same name function on the other layers.
Why is it the farthest? Because of a gameobject, it has normalbulletfly this component, meaning that this gameobject has an instance of type Normalbulletfly. Naturally, Unity will select the Update method in this type of method table . The method table of its parent class is only available if it does not exist in the normalbulletfly.
Of course there are only 1 shells so far, so there are only 1 specific normalbulletfly scripts. This way, no matter how many kinds of shells in the future, only a bullet prefab can be.
Summarize
The movement of the tanks and the attack of the shells, I have all been reconstructed. The purpose of refactoring is to merge duplicate code (translation, rotation, cannon, fly) into one place, with different codes (user input vs AI control, different attack modes) written separately as different scripts. The technology of reconstruction is object-oriented design.
You can get the project source on my GitHub page (Https://github.com/bitzhuwei/TankHero-2D).
Please give me a lot of advice ~
Homemade Unity Games tankhero-2d (2) Making enemy tanks