僵尸基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public enum ZombieState
{
Idel,
Walk,
Attack,
Dead
}
public abstract class ZombieBase : MonoBehaviour
{
protected ZombieState state;
protected Animator animator;
protected SpriteRenderer spriteRenderer;
protected Grid currGrid;
protected int hp;
protected abstract int MaxHP { get; }
protected abstract float speed { get; }
private bool isAttackState;
protected bool isLostHead;
protected abstract float attackValue { get; }
protected abstract GameObject Prefab { get; }
protected virtual Vector2 offset { get; } = Vector2.zero;
protected ZombieHpState zombieHpState;
public ZombieState State
{
get => state;
set
{
state = value;
CheckState();
}
}
public Grid CurrGrid { get => currGrid; }
public int Hp
{
get => hp;
set
{
hp = value;
zombieHpState.UpdateZombieHpState(hp);
if (hp <= 0)
{
State = ZombieState.Dead;
}
}
}
public void Init(int lineNum, int orderNum, Vector2 pos)
{
hp = MaxHP;
InitZombieHpState();
isLostHead = false;
transform.position = pos+offset;
Find();
GetGridByVerticalNum(lineNum);
CheckOrder(orderNum);
State = ZombieState.Idel;
}
public abstract void InitZombieHpState();
public abstract void OnDead();
private void CheckOrder(int orderNum)
{
int startNum = 0;
switch ((int)CurrGrid.Point.y)
{
case 0:
startNum = 400;
break;
case 1:
startNum = 300;
break;
case 2:
startNum = 200;
break;
case 3:
startNum = 100;
break;
case 4:
startNum = 0;
break;
}
spriteRenderer.sortingOrder = startNum + orderNum;
}
void Find()
{
animator = GetComponentInChildren<Animator>();
spriteRenderer = GetComponentInChildren<SpriteRenderer>();
}
void Update()
{
FSM();
}
protected void CheckState()
{
switch (State)
{
case ZombieState.Idel:
animator.Play(zombieHpState.GetCurrWalkAnimationStr(), 0, 0);
animator.speed = 0;
break;
case ZombieState.Walk:
animator.Play(zombieHpState.GetCurrWalkAnimationStr(), 0, animator.GetCurrentAnimatorStateInfo(0).normalizedTime);
animator.speed = 1;
break;
case ZombieState.Attack:
animator.Play(zombieHpState.GetCurrAttackAnimationStr(), 0, animator.GetCurrentAnimatorStateInfo(0).normalizedTime);
animator.speed = 1;
break;
case ZombieState.Dead:
Dead();
break;
}
}
private void FSM()
{
switch (State)
{
case ZombieState.Idel:
State = ZombieState.Walk;
break;
case ZombieState.Walk:
Move();
break;
case ZombieState.Attack:
if (isAttackState) break;
Attack(currGrid.CurrPlantBase);
break;
}
}
private void GetGridByVerticalNum(int verticalNum)
{
currGrid = GridManager.Instance.GetGridByVerticalNum(verticalNum);
transform.position = new Vector2(transform.position.x, currGrid.Position.y)+offset;
}
protected void Move()
{
if (currGrid == null) return;
currGrid = GridManager.Instance.GetGridByWorldPos(transform.position+(Vector3)offset);
if (currGrid.HavePlant
&& CurrGrid.CurrPlantBase.ZombieCanEat
&& currGrid.CurrPlantBase.transform.position.x < transform.position.x + ((Vector3)offset).x
&& transform.position.x+ ((Vector3)offset).x - currGrid.CurrPlantBase.transform.position.x < 0.3f)
{
State = ZombieState.Attack;
return;
}
else if (currGrid.Point.x == 0 && currGrid.Position.x - transform.position.x-((Vector3)offset).x > 1f)
{
Vector2 pos = transform.position+ (Vector3)offset;
Vector2 target = new Vector2(-9.17f, -1.37f);
Vector2 dir = (target - pos).normalized * 3f;
transform.Translate((dir * (Time.deltaTime / 1)) / speed);
if (Vector2.Distance(target, pos) < 0.05f)
{
LVManager.Instance.GameOver();
}
return;
}
transform.Translate((new Vector2(-1.33f, 0) * (Time.deltaTime / 1)) / speed);
}
private void Attack(PlantBase plant)
{
isAttackState = true;
StartCoroutine(DoHurtPlant(plant));
}
IEnumerator DoHurtPlant(PlantBase plant)
{
int num = 0;
while (plant != null && plant.Hp > 0)
{
if (num == 5) num = 0;
if (num == 0)
{
AudioManager.Instance.PlayEFAudio(GameManager.Instance.GameConf.ZombieEat);
}
num += 1;
plant.Hurt(attackValue / 5);
yield return new WaitForSeconds(0.2f);
}
isAttackState = false;
State = ZombieState.Walk;
}
public void Hurt(int attackValue)
{
Hp -= attackValue;
if (State!=ZombieState.Dead)
{
StartCoroutine(ColorEF(0.2f, new Color(0.4f, 0.4f, 0.4f), 0.05f, null));
}
}
public void BoomHurt(int attackValue)
{
if (attackValue >= Hp)
{
State = ZombieState.Dead;
Zombie_DieBody body = PoolManager.Instance.GetObj(GameManager.Instance.GameConf.Zombie_DieBody).GetComponent<Zombie_DieBody>();
body.InitForBoomDie(animator.transform.position+(Vector3)offset);
}
else
{
Hurt(attackValue);
}
}
public void Dead(bool playOndead=true)
{
if (playOndead)
{
OnDead();
}
ZombieManager.Instance.RemoveZombie(this);
StopAllCoroutines();
currGrid = null;
PoolManager.Instance.PushObj(Prefab, gameObject);
}
protected IEnumerator ColorEF(float wantTime, Color targetColor, float delayTime, UnityAction fun)
{
float currTime = 0;
float lerp;
while (currTime < wantTime)
{
yield return new WaitForSeconds(delayTime);
lerp = currTime / wantTime;
currTime += delayTime;
spriteRenderer.color = Color.Lerp(Color.white, targetColor, lerp);
}
spriteRenderer.color = Color.white;
if (fun != null) fun();
}
public void StartMove()
{
State = ZombieState.Walk;
}
}