For AI, my initial idea is very simple, first he must move, and is moving in the map, know how to turn after hitting the wall, and then know how to shoot, the other is not, based on this idea, I first created a Mytank class, used to manage the player's tank activities, and then create the Aitank class, Aitank class inherits Mytank class, in this case, on the Aitank class, only need to increase the AI on it, the specific state machine implementation, put on the Mytank class can be.
First of all to analyze the Mytank this class, starting from the finite state machine.
The state of a tank has the following several:
Protected enum State { Idle, leftwalk, rightwalk, upwalk, downwalk, fire };
They are: Stand, go left, go right, go up, go down, fire.
Then it is to achieve each state separately, the first is the steering:
protected void Updaterotate (state state) {switch (state) {case State.leftwalk: This.transform.rotation = quaternion.identity; This.transform.Rotate (Vector3.forward * m_fangle); M_curangle = Vector3.left; Break Case State.RightWalk:this.transform.rotation = quaternion.identity; This.transform.Rotate (Vector3.forward *-m_fangle); M_curangle = Vector3.right; Break Case State.UpWalk:this.transform.rotation = quaternion.identity; M_curangle = Vector3.up; Break Case State.DownWalk:this.transform.rotation = quaternion.identity; This.transform.Rotate (Vector3.forward * m_fangle * 2); M_curangle = Vector3.down; Break } }
Then walk and fire:
public virtual void Updatestate () { Debug.Log (m_sname + ": updatestate ()"); Switch (m_curstate) {case state.idle: Break ; Case State.leftwalk: this.transform.position + = vector3.left * Time.deltatime * m_fmovespeed; break; Case State.upwalk: this.transform.position + = vector3.up * Time.deltatime * m_fmovespeed; break; Case State.downwalk: this.transform.position + = Vector3.down * Time.deltatime * m_fmovespeed; break; Case State.rightwalk: this.transform.position + = vector3.right * Time.deltatime * m_fmovespeed; break; Case State.fire: dofire (); break; } }
Where the Dofire function is implemented as follows:
protected virtual void Dofire () { Gameobject bullet = Instantiate (M_gbullet) as Gameobject; Bullet.name = m_sname + "Bullet"; Bullet. Getcomponent<cbullet> (). m_vdirection = M_curangle; Bullet. Getcomponent<cbullet> (). m_fmovespeed = M_fmovespeed + 1.0f; Bullet.transform.position = new Vector3 (this.transform.position.x, this.transform.position.y,0); Destroy (bullet, 5.0f); }
The reason for designing a virtual function is that Aitank needs to override this function.
Then you need to listen to each button, I set to, press A,w,s,d as the direction key, release to stop moving, and then press K to fire, so in the update function should be implemented:
void Update () { setcurstate (state.idle); Steering if (Input.getkey (KEYCODE.A)) { updaterotate (state.leftwalk); Setcurstate (State.leftwalk); } if (Input.getkey (KEYCODE.W)) { updaterotate (state.upwalk); Setcurstate (State.upwalk); } if (Input.getkey (KEYCODE.S)) { updaterotate (state.downwalk); Setcurstate (State.downwalk); } if (Input.getkey (KEYCODE.D)) { updaterotate (state.rightwalk); Setcurstate (State.rightwalk); } if (Input.getkeydown (KEYCODE.K)) { setcurstate (state.fire); } Updatestate (); }
Where setcurstate This function is used to set the current state, and the last state is also stored for ease of use.
protected void Setcurstate (state curstate) { if (curstate! = m_curstate) m_laststate = m_curstate; M_curstate = curstate; }
Finally, some of the collision detection functions, for example, hit the enemy's bullets on the health of the loss of one, health value of 0 to announce the end of the game.
void Ontriggerenter2d (collider2d other) {Debug.Log (M_sname + "Ontriggerenter:" + other.gameObject.name); Was hit if (Other.gameObject.name = = "Aibullet") {Destroy (other.gameobject); if (camera.main.getcomponent<ccamera> (). Reducemyleft () > 0) {gameobject temp = instantiate (M_boomanimation, this.gameObject.transfor M.position, quaternion.identity) as Gameobject; Destroy (temp, 0.5f); String name = This.gameObject.name; Gameobject Temp_tank = Instantiate (This.gameobject, M_initposition, quaternion.identity) as GameObject; Temp_tank.name = name; } else {//You lost Camera.main.getcomponent<ccamera> (). M_bislose = t Rue } Destroy (This.gameobject); } }
That's the whole mytank process.
--------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------
Below to the implementation of Aitank, Aitank is mainly to add a number of triggers, such as the detection of a collision on the turn, every two seconds to launch bullets and so on, as a very simple AI, there is no need to consider so much. The first is collision detection:
void Oncollisionenter2d (collision2d coll) { Debug.Log (m_sname + "oncollisionenter2d:" + coll.gameObject.name ); Changestatefromwall (); }
When you encounter a collision, you turn, and the Changestatefromwall is implemented as follows:
void Changestatefromwall () { switch (m_curstate) {case state.idle: setcurstate ( State.downwalk); break; Case State.leftwalk: setcurstate (state.upwalk); break; Case State.upwalk: setcurstate (state.rightwalk); break; Case State.downwalk: setcurstate (state.leftwalk); break; Case State.rightwalk: setcurstate (state.downwalk); break; Case State.fire: setcurstate (m_laststate); break; } This. Updaterotate (m_curstate); }}
This is a function of circular steering, if the current direction is left, go up, if the current direction is top, go right .... If it is in the firing state, it returns to the previous state, and finally updates the AI's angle.
And then to fire, the setting of the fire is very simple, call to a function: Invokerepeating, this is a repeating timer, the function prototype is:
The first parameter is the method passed in, the second argument starts after a few seconds, and the third parameter is repeated every few seconds after the start.
What we need is to fire the bullets one second after the AI tank is generated and then the cycle is fired every two seconds, so it should be written in the start function:
Fire invokerepeating every 2 seconds ("Dofire", 1, 2);
Then we need to rewrite the Dofire function:
protected override void Dofire () { base.dofire (); }
This completes the function of firing a bullet every two seconds.
The above is the basic function of AI, you can slowly optimize it later, so that it becomes a powerful AI.
"Learn Unity3d with Me" as a 2D 90 tank battle AI system