Unity Platform 10 Enermy Basic === 2020.08.16 ###### tags: `platform` ## List 1. [Structure of Enermy](#SE) 2. [Enermy State](#ES) 3. [State : Moving](#SM) 4. [State : Knockback](#SK) 5. [State : Dead](#SD) 6. [Dash FIX](#DF) ## Content ### Structure of Enermy<a id="SE"/> Enemry state are dead or alive.<br>Alive also devides walking, knockback, chase, etc...<br>We consider this state, so component like this<br>`RigidBody2D`, `Animator`, `SpriteRenderer`, `BoxCollider2D` and Enemry Obj's child alive obj + dead particle(or alive obj+ dead obj)<br>Animation & animator & particle refer to below.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;[Animation ref](https://www.youtube.com/watch?v=K2SbThbGw6w&list=PLy78FINcVmjA0zDBhLuLNL1Jo6xNMMq-W&index=12) 4:00 ~<br>&nbsp;&nbsp;&nbsp;&nbsp;[Animator ref](https://www.youtube.com/watch?v=K2SbThbGw6w&list=PLy78FINcVmjA0zDBhLuLNL1Jo6xNMMq-W&index=12) 5:00 ~<br><a id="REF"/>&nbsp;&nbsp;&nbsp;&nbsp;[Particle ref](https://www.youtube.com/watch?v=K2SbThbGw6w&list=PLy78FINcVmjA0zDBhLuLNL1Jo6xNMMq-W&index=12) 37:00 ~<br><br>In Script, variable like this. ```csharp= // GameObj private GameObject alive; private Rigidbody2D aliveRb2D; private Animator aliveAnim; private void Start() { alive = transform.Find("Alive").gameObject; aliveRb2D = alive.GetComponent<Rigidbody2D>(); aliveAnim = alive.GetComponent<Animator>(); } ``` ### Enermy State<a id="ES"/> Enermy States are various. But this example show 3 State, `Moving` `Knockback`, `Dead`.<br>`enum` makes Macro with sucessvie numbers. ```csharp= private enum State { Moving, Knockback, Dead } private State currentState; ``` <br> And every state has 3 function Enter, Update Exit.<br>And Switch function for func from one state to other state.<br>state update functions work in `Update()` ```csharp= // Update Check EveryState private void Update() { switch(currentState) { case State.Moving : UpdateMovingState(); break; case State.Knockback : UpdateKnockbackState(); break; case State.Dead : UpdateDeadState(); break; } } //----Moving State---- and other states also like this private void EnterMovingState() { } private void UpdateMovingState() { } private void ExitMovingState() { } // Switch function. private void SwitchState(State state) { switch (currentState) { case State.Moving : ExitMovingState(); break; case State.Knockback : ExitKnockbackState(); break; case State.Dead : ExitDeadState(); break; } switch (state) { case State.Moving : EnterMovingState(); break; case State.Knockback : EnterKnockbackState(); break; case State.Dead : EnterDeadState(); break; } currentState = state; } ``` <br> ### State : Moving<a id="SM"/> For moving, grounding must be set.<br>Their technic is same players. But apply it differently.<br>if not grounded or meet wall, enemry flip, else just walk. ```csharp= // Object Detection [SerializeField] private Transform groundCheck, wallCheck; [SerializeField] private LayerMask whatIsGround; [SerializeField] private float groundCheckDistance, wallCheckDistance; private bool groundDetected, wallDetected; // Movement [SerializeField] private int facingDirection; private float movementSpeed; private Vector2 movement; private void UpdateMovingState() { groundDetected = Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround); wallDetected = Physics2D.Raycast(wallCheck.position, Vector2.right, wallCheckDistance, whatIsGround); if (groundDetected || wallDetected) Flip(); else { movement.Set(movementSpeed * facingDirection, aliveRb2D.velocity.y); aliveRb2D.velocity = movement; } } private void Flip() { facingDirection *= -1; alive.transform.Rotate(0.0f, 180.0f, 0.0f); } ``` ### State : Knockback<a id="SK"/> Before knockback, must make damage function.<br>Like dummyEnermy, but little changed about direction.<br>Show below. ```csharp= /* * attackDetails[0] = attack Damage * attackDetails[1] = attack Position(Player position) */ private void Damage(float[] attackDetails) { currentHealth -= attackDetails[0]; //Make particle Instantiate(hitParticle, alive.transform.position, Quaternion.Euler(0.0f, 0.0f, Random.Range(0.0f, 180.0f))); //Set knockback direction if (attackDetails[1] > alive.transform.position.x) damageDirection = -1; else damageDirection = 1; if (currentHealth > 0.0f) SwitchState(State.Knockback); else SwitchState(State.Dead); } ``` <br> Knockback technic is same players.<br>Time duration and movespeed, set animation. ```csharp= private void EnterKnockbackState() { knockbackStartTime = Time.time; movement.Set(knockbackSpeed.x * damageDirection, knockbackSpeed.y); aliveRb2D.velocity = movement; aliveAnim.SetBool("Knockback", true); } private void UpdateKnockbackState() { if (Time.time >= knockbackStartTime + knockbackDuration) SwitchState(State.Moving); } private void ExitKnockbackState() { aliveAnim.SetBool("Knockback", false); } ``` ### State : Dead<a id="SD"/> If dead, particles are made, and destroy enermy.<br>Particle ref above [link](#REF) ```csharp= private void EnterDeadState() { Destroy(gameObject); Instantiate(deathChunkParticle, alive.transform.position, deathChunkParticle.transform.rotation); Instantiate(deathBloodParticle, alive.transform.position, deathBloodParticle.transform.rotation); } ``` ### Dash FIX<a id="DF"/> Dash Image's litte problem with time rate.<br> ```csharp= // before : alphaMultiplier = 0.05f; [SerializeField] private float alphaDecay; //Maybe 10? private void Update() { // before : alpha *= alphaMutiplier alpha -= alphaDecay * Time.deltaTime; // } ``` [Dash rate fix](https://www.youtube.com/watch?v=K2SbThbGw6w&list=PLy78FINcVmjA0zDBhLuLNL1Jo6xNMMq-W&index=12) 43:00 ~<br>