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> [Animation ref](https://www.youtube.com/watch?v=K2SbThbGw6w&list=PLy78FINcVmjA0zDBhLuLNL1Jo6xNMMq-W&index=12) 4:00 ~<br> [Animator ref](https://www.youtube.com/watch?v=K2SbThbGw6w&list=PLy78FINcVmjA0zDBhLuLNL1Jo6xNMMq-W&index=12) 5:00 ~<br><a id="REF"/> [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>