using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
namespace WildAttack
{
///
/// 敌人类
///
public class Enemy : MonoBehaviour
{
#region Members
Transform finalPos;
private Animator enemyAnim;
private float speed;
private int score;
private int hp;
private int monsterId;
private int weaponId;
///
/// 是否到达目的地
///
private bool arriveTarget;
private int atk;
private float attackIntervalTime;
Transform armorTrans;
Transform animTrans;
///
/// 装备
///
private Stack ArmorStack;
///
/// 装备破碎动画
///
private Stack AnimStack;
///
/// 存放路径点信息list
///
private List wayList;
private int nextWayIndex;
private AudioSource audioSource;
private int spawnGroupId;
private Transform HpBarRoot;
#endregion
#region Lifecycle
private void OnEnable()
{
finalPos = GameObject.Find("finalPos").transform;
HpBarRoot = GameObject.Find("HpBarRoot").transform;
enemyAnim = GetComponent();
arriveTarget = false;
nextWayIndex = 0;
wayList = new List();
audioSource = GetComponent();
}
bool isBorn = true;
bool isDead = false;
Vector3 deadPos;
// Update is called once per frame
void Update()
{
CheckAnimState();
if (Vector3.Distance(transform.position, finalPos.position) < 15f)
{
GetComponent().isKinematic = true;
}
// Attack
// check state
if (arriveTarget && !isDead && ProcessManager.GetInstance().CurrLevel > 0)
{
enemyAnim.SetBool("run1", false);
enemyAnim.SetBool("run2", false);
// check distance
if (attackIntervalTime > 0)
{
attackIntervalTime -= Time.deltaTime;
}
else
{
PlayAttackAnim();
attackIntervalTime = WeaponModule.GetInstance().GetData(weaponId).cd;
}
}
}
private void FixedUpdate()
{
if (isBorn) return;
if (isDead) return;
if (ProcessManager.GetInstance().CurrLevel <= 0) return;
// change run anim
if (this.weaponId == 3 && this.hp < 3)
{
enemyAnim.SetBool("run2", true);
}
else
{
enemyAnim.SetBool("run1", true);
}
// check arrived
if (nextWayIndex >= wayList.Count)
{
arriveTarget = true;
return;
}
// check distance
if (Vector2.Distance(new Vector2(transform.position.x, transform.position.z), wayList[nextWayIndex]) < 1.5f)
{
nextWayIndex++;
}
else
{
// 射线检测下个目标点y轴
Vector3 target = new Vector3(wayList[nextWayIndex].x, transform.position.y, wayList[nextWayIndex].y);
Ray ray = new Ray(new Vector3(wayList[nextWayIndex].x, transform.position.y + 10, wayList[nextWayIndex].y), -transform.up);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo, 100, 1 << LayerMask.NameToLayer("Plane")))
{
if (hitInfo.collider.gameObject.layer == LayerMask.NameToLayer("Plane"))
{
target = new Vector3(wayList[nextWayIndex].x, hitInfo.point.y, wayList[nextWayIndex].y);
}
}
// 移动
MoveTowards(target);
}
}
bool isJumping = false;
GameObject jumpTarget;
///
/// trigger 触发切换行进路线
///
///
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.layer != LayerMask.NameToLayer("WayPoint")) return;
// 触发检测是路径点或跳跃点
if (other.gameObject.name.Contains("jumpPoint"))
{
// get跳跃目的地
string index = other.gameObject.name.Split('_')[1];
if (other.gameObject.name.Split('_')[2] == "1")
{
if (isJumping)
{
return;
}
isJumping = true;
jumpTarget = GameObject.Find($"jumpPoint_{index}_2");
enemyAnim.SetTrigger("jump" + Random.Range(1, 3));
}
else if (other.gameObject.name.Split('_')[2] == "2")
{
isJumping = false;
}
return;
}
// 切换路径点
int nextGroupID = 0;
for (int i = 0; i < EnemyManager.GetInstance().GetWayPoints().Length; i++)
{
if (Vector3.Distance(other.transform.position, EnemyManager.GetInstance().GetWayPoints()[i].transform.position) < 1f)
{
nextGroupID = i + 1;
break;
}
}
SetNewWayPoint(nextGroupID);
}
#endregion
#region Functions
public void Init(int monsterId, int weaponId, int spawnGroupId)
{
isBorn = true;
transform.GetComponentInChildren().enabled = false;
transform.GetComponentInChildren().enabled = false;
transform.GetComponent().isKinematic = true;
isDead = false;
this.monsterId = monsterId;
hp = this.monsterId;
this.weaponId = weaponId;
this.spawnGroupId = spawnGroupId;
MonsterData monsterData = MonsterModule.GetInstance().GetData(this.monsterId);
speed = monsterData.speed;
score = monsterData.num;
WeaponData weaponData = WeaponModule.GetInstance().GetData(weaponId);
atk = weaponData.atk;
attackIntervalTime = 0;
// spawnGroupId == -1 默认关卡怪
if (spawnGroupId <= 0)
{
Vector2 pos = GameModule.GetInstance().GetDoubleParams("startMonsterXZ");
transform.localPosition = new Vector3(pos.x, 10, pos.y);
// raycast get Y
Ray ray = new Ray(new Vector3(transform.position.x, 30, transform.position.z), -transform.up);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo, 100, 1 << LayerMask.NameToLayer("Plane")))
{
if (hitInfo.collider.gameObject.layer == LayerMask.NameToLayer("Plane"))
{
transform.position = new Vector3(transform.position.x, hitInfo.point.y, transform.position.z);
}
}
transform.LookAt(Camera.main.transform);
// 动画
enemyAnim.SetBool("flag", true);
}
else
{
transform.localPosition = EnemyManager.GetInstance().GetWayPoints()[spawnGroupId - 1].transform.position;
}
enemyAnim.SetTrigger("born");
// 判断血量 上装备
if (this.hp > 1)
{
ArmorStack = new Stack();
armorTrans = transform.Find("ArmorTrans");
for (int i = 0; i < this.hp - 1; i++)
{
GameObject armor = armorTrans.GetChild(i).gameObject;
armor.SetActive(true);
ArmorStack.Push(armor);
}
AnimStack = new Stack();
animTrans = transform.Find("AnimTrans");
for (int i = 0; i < this.hp - 1; i++)
{
GameObject anim = animTrans.GetChild(i).gameObject;
anim.transform.GetComponentInChildren().SetBool("dead", false);
anim.SetActive(false);
//armorTrans.GetChild(i).GetComponent().enabled = true;
AnimStack.Push(anim);
}
}
}
private float voiceTime = 0;
///
/// 判断动画状态 出生死亡
///
private void CheckAnimState()
{
AnimatorStateInfo animInfo = enemyAnim.GetCurrentAnimatorStateInfo(0);
if (animInfo.normalizedTime > 0.9f && animInfo.IsName("Born"))
{
isBorn = false;
transform.GetComponentInChildren().enabled = true;
transform.GetComponentInChildren().enabled = true;
transform.GetComponent().isKinematic = false;
}
if (animInfo.IsName("Dead1") || animInfo.IsName("Dead2"))
{
transform.position = deadPos;
if (animInfo.normalizedTime > 0.9f)
{
ResetEnemy();
gameObject.SetActive(false);
return;
}
return;
}
else
{
// 初始怪随机时间播放随机嘲讽音效
if (voiceTime <= 0 && spawnGroupId <= 0)
{
audioSource.clip = Resources.Load($"Voice/Enemy/joke_{Random.Range(1, 5)}");
audioSource.Play();
Vector2 voiceSpawn = GameModule.GetInstance().GetDoubleParams("monsterATKVoiceTime");
voiceTime = Random.Range(voiceSpawn.x, voiceSpawn.y);
}
else
{
voiceTime -= Time.deltaTime;
}
}
}
///
/// 被击
///
public void Hitted(int damage, bool isHead)
{
if (hp <= 0)
{
return;
}
// 掉血
hp -= damage;
// 血量判断
if (hp <= 0)
{
// 是否被箭攻击
if (damage == 1)
{
audioSource.clip = Resources.Load("Voice/Enemy/Hitted");
audioSource.Play();
}
Dead();
// 气球 运动
CreateBalloon(transform.position, isHead);
}
else
{
// 拿矛的敌人血量小于3切换奔跑动画
if (hp < 3 && this.weaponId == 3)
{
enemyAnim.SetBool("run1", false);
enemyAnim.SetBool("run2", true);
}
// 被击表现
for (int i = 0; i < damage; i++)
{
if (ArmorStack.Peek())
{
GameObject armor = ArmorStack.Pop();
armor.SetActive(false);
}
}
GameObject anim = null;
for (int i = 0; i < damage; i++)
{
if (AnimStack.Peek())
{
anim = AnimStack.Pop();
StartCoroutine(DestroyArmor(anim));
}
}
// 装备受击音效
if (damage == 1)
{
if (anim != null) anim.GetComponent().Play();
}
}
}
///
/// 敌人死亡
///
private void Dead()
{
if (!isDead)
{
// 敌人死亡表现
deadPos = transform.position;
enemyAnim.SetTrigger("dead" + Random.Range(1, 3));
transform.GetComponentInChildren().enabled = false;
transform.GetComponentInChildren().enabled = false;
isDead = true;
// 初始怪不加分
if (spawnGroupId > 0)
{
GameMananger.GetInstance().AddScore(score);
}
}
}
///
/// 掉装备
///
///
///
IEnumerator DestroyArmor(GameObject armor)
{
armor.SetActive(true);
armor.GetComponentInChildren().SetBool("dead", true);
yield return new WaitForSeconds(1);
armor.GetComponentInChildren().SetBool("dead", false);
armor.SetActive(false);
}
///
/// replace OnDestroy
///
public void ResetEnemy()
{
if (ArmorStack != null && ArmorStack.Count > 0)
{
for (int i = 0; i < armorTrans.childCount; i++)
{
//armorTrans.GetChild(i).GetComponentInChildren().SetBool("dead", false);
//armorTrans.GetChild(i).GetComponent().enabled = true;
armorTrans.GetChild(i).gameObject.SetActive(false);
}
ArmorStack.Clear();
}
if (AnimStack != null && AnimStack.Count > 0)
{
for (int i = 0; i < AnimStack.Count; i++)
{
if (animTrans.GetChild(i).GetComponentInChildren())
{
animTrans.GetChild(i).GetComponentInChildren().SetBool("dead", false);
}
//armorTrans.GetChild(i).GetComponent().enabled = true;
animTrans.GetChild(i).gameObject.SetActive(false);
}
AnimStack.Clear();
}
speed = 0;
//GetComponent().constraints = RigidbodyConstraints.FreezeRotation;
GetComponent().isKinematic = false;
EnemyManager.GetInstance().enemyList.Remove(this);
ProcessManager.GetInstance().EnemyDead();
}
///
/// 敌人死亡生成气球
///
///
///
private void CreateBalloon(Vector3 pos, bool isHead)
{
// 爆头非爆头 数量不同
int num = isHead ? 3 : 2;
for (int i = 0; i < num; i++)
{
GameObject balloon = BalloonPool.GetInstance().GetRedBalloon();
balloon.transform.position = new Vector3(pos.x - i, pos.y + 2, pos.z - i);
balloon.SetActive(true);
}
}
private void PlayAttackAnim()
{
enemyAnim.SetTrigger($"attack{weaponId}");
}
///
/// 攻击逻辑 绑定在animation的Event上
///
public void Attack()
{
if (!GameMananger.GetInstance().isOver)
{
audioSource.clip = Resources.Load("Voice/Enemy/Attack");
audioSource.Play();
GameMananger.GetInstance().SubHp(atk);
GameObject flotage = FlotagePool.GetInstance().GetGameObject();
flotage.SetActive(true);
flotage.GetComponent().Init(Camera.main.WorldToScreenPoint(HpBarRoot.position + Vector3.up * 5), -atk, GameModule.GetInstance().GetRGB("BloodLossRGB"), StringModule.GetInstance().GetData("hpUnit"), FlotageTypeEnum.Fixed);
}
}
private void MoveTowards(Vector3 target)
{
if (isJumping && (enemyAnim.GetCurrentAnimatorStateInfo(0).IsName("Jump1") || enemyAnim.GetCurrentAnimatorStateInfo(0).IsName("Jump2")) && enemyAnim.GetCurrentAnimatorStateInfo(0).normalizedTime > 0.2f)
{
// 冰冻魔法触发后跳跃不到目标点
// fixme: 使用配置中的speed
transform.position = Vector3.Lerp(transform.position, jumpTarget.transform.position + Vector3.up * 2, MonsterModule.GetInstance().GetData(monsterId).speed / 2 * Time.deltaTime);
return;
}
transform.LookAt(target);
transform.position = Vector3.MoveTowards(transform.position, target, Time.deltaTime * speed);
// 防止倾斜
transform.rotation = new Quaternion(0, transform.rotation.y, 0, transform.rotation.w);
}
///
/// 速度相关
///
///
public void SetSpeed(float multiple)
{
speed = MonsterModule.GetInstance().GetData(this.monsterId).speed * multiple;
transform.Find("Bip001/Bip001 Pelvis/Bip001 Spine/Bip001 Spine1/body/slow").GetComponentInChildren().Play();
}
public void ResetSpeed()
{
speed = MonsterModule.GetInstance().GetData(this.monsterId).speed;
transform.Find("Bip001/Bip001 Pelvis/Bip001 Spine/Bip001 Spine1/body/slow").GetComponentInChildren().Stop();
}
///
/// 切换路径点list 重新随机
///
///
public void SetNewWayPoint(int nextGroupID)
{
arriveTarget = false;
nextWayIndex = 0;
List wayDataList = WayPointModule.GetInstance().GetDataByGroup(nextGroupID);
List weight = new List();
foreach (var item in wayDataList)
{
weight.Add(item.weight);
}
wayList = wayDataList[WeightRandomUtils.GetInstance().GetRandomId(weight) - 1].wayPoint;
}
#endregion
}
}