You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
6.8 KiB
228 lines
6.8 KiB
3 years ago
|
using System.Collections;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.AI;
|
||
|
|
||
|
//战士敌军类
|
||
|
//带有武器的战士可以使用
|
||
|
//用于一般敌人,小boss身上
|
||
|
//会攻击,血量低于一定值时会奔跑
|
||
|
//拥有攻击间隔及攻击力属性,攻击玩家后不会消失,玩家躲开后会继续追击玩家
|
||
|
public class GhostWarrior : Hurtable
|
||
|
{
|
||
|
//数值相关
|
||
|
//是否碰到玩家
|
||
|
public bool isTouched;
|
||
|
//是否死亡
|
||
|
public bool isDeath;
|
||
|
//是否暂停
|
||
|
public bool isPause;
|
||
|
//怪物的状态(0为行走,1为站立,2为跑步,3为攻击,4为死亡)
|
||
|
private int status;
|
||
|
//怪物的各项属性值(攻击力,护甲值,行走速度,奔跑速度)
|
||
|
public int atk;
|
||
|
public int def;
|
||
|
public float runningSpeed;
|
||
|
public float walkingSpeed;
|
||
|
//显示或与玩家相关
|
||
|
private GameObject Player;
|
||
|
private Player playerScript;
|
||
|
private float distancePE_;
|
||
|
//敌人发动攻击时离玩家的距离
|
||
|
private float standTimer;
|
||
|
public float attackDistace;
|
||
|
//玩家所持盾
|
||
|
private LightShield playerShield_;
|
||
|
//判断攻击对象是不是玩家(不是玩家就是盾牌)
|
||
|
private bool isAttackedPlayer;
|
||
|
//敌人最大生命值
|
||
|
private float maxHp;
|
||
|
//死亡特效
|
||
|
public GameObject deathEffect_;
|
||
|
//动作
|
||
|
public Animator warriorAnime_;
|
||
|
//判断敌人是否愤怒
|
||
|
private bool isAngry;
|
||
|
|
||
|
//攻击间隔(以秒计)(攻击过程中进行判定)
|
||
|
public float nextAttackTimer;
|
||
|
//攻击过程中的计时器
|
||
|
public float attackTimer;
|
||
|
public float attackEndTimer;
|
||
|
//是否处于攻击状态
|
||
|
private bool isAttacking_;
|
||
|
//是否命中玩家
|
||
|
private bool isHitPlayer;
|
||
|
//是否被防御(攻击判定圈里有检测到盾牌)
|
||
|
private bool isDefended;
|
||
|
|
||
|
// Use this for initialization
|
||
|
void Start()
|
||
|
{
|
||
|
Player = GameObject.FindGameObjectWithTag("Player");
|
||
|
playerScript = Player.GetComponent<Player>();
|
||
|
hitEvent.AddListener(GhostAttacked_);
|
||
|
deathEvent.AddListener(GhostDeath_);
|
||
|
status = 0;
|
||
|
standTimer = 0.3f;
|
||
|
isAttackedPlayer = false;
|
||
|
myself_1.GetComponent<NavMeshAgent>().speed = walkingSpeed;
|
||
|
maxHp = hp;
|
||
|
warriorAnime_.SetBool("walk", true);
|
||
|
myself_1.GetComponent<BoxCollider>().enabled = false;
|
||
|
isDefended = false;
|
||
|
}
|
||
|
|
||
|
// Update is called once per frame
|
||
|
void Update()
|
||
|
{
|
||
|
distancePE_ = CaculatePlayerDistance();
|
||
|
if (!isDeath)
|
||
|
{
|
||
|
GhostAlive_();
|
||
|
}
|
||
|
//生气了之后2倍速奔跑
|
||
|
if (hp <= maxHp / 2 && !isAngry)
|
||
|
{
|
||
|
isAngry = true;
|
||
|
warriorAnime_.SetBool("walk", false);
|
||
|
warriorAnime_.SetBool("run", true);
|
||
|
myself_1.GetComponent<NavMeshAgent>().speed = walkingSpeed * 2;
|
||
|
}
|
||
|
|
||
|
//敌人攻击相关判定
|
||
|
if (isAttacking_ && isTouched) {
|
||
|
isHitPlayer = true;
|
||
|
isTouched = false;
|
||
|
}
|
||
|
if (isHitPlayer) {
|
||
|
if (isAttackedPlayer)
|
||
|
{
|
||
|
//warriorAnime_.SetBool("attack", true);
|
||
|
if (isDefended)
|
||
|
{
|
||
|
playerShield_.shieldHit();
|
||
|
}
|
||
|
else {
|
||
|
playerScript.Hurted(atk);
|
||
|
}
|
||
|
isHitPlayer = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//敌人行为相关
|
||
|
private void GhostBirth_()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
//原地不动
|
||
|
private void GhostStand_()
|
||
|
{
|
||
|
myself_1.GetComponent<NavMeshAgent>().destination = myself_1.transform.position;
|
||
|
warriorAnime_.SetBool("walk", false);
|
||
|
warriorAnime_.SetBool("run", false);
|
||
|
}
|
||
|
//行走
|
||
|
private void GhostWalk_()
|
||
|
{
|
||
|
//myself_1.transform.position += new Vector3(0, 0, Mathf.Sin(distancePE_) * 0.01f);
|
||
|
myself_1.GetComponent<NavMeshAgent>().destination = Player.transform.position + Player.GetComponent<CapsuleCollider>().center;
|
||
|
}
|
||
|
//跑(这里的跑指最后的冲刺)
|
||
|
private void GhostRun_()
|
||
|
{
|
||
|
myself_1.GetComponent<NavMeshAgent>().speed = runningSpeed;
|
||
|
warriorAnime_.SetBool("run", true);
|
||
|
GhostWalk_();
|
||
|
}
|
||
|
//攻击玩家
|
||
|
private void GhostAttack_()
|
||
|
{
|
||
|
isHitPlayer = false;
|
||
|
StartCoroutine(AttackAction());
|
||
|
/*if (isAttackedPlayer)
|
||
|
{
|
||
|
//warriorAnime_.SetBool("attack", true);
|
||
|
playerScript.Hurted(atk);
|
||
|
}*/
|
||
|
}
|
||
|
//受到攻击
|
||
|
private void GhostAttacked_()
|
||
|
{
|
||
|
myself_1.GetComponentInChildren<Renderer>().material.color = new Vector4(1.0f, hp / maxHp, hp / maxHp, 1.0f);
|
||
|
}
|
||
|
//死亡
|
||
|
private void GhostDeath_()
|
||
|
{
|
||
|
status = 4;
|
||
|
isDeath = true;
|
||
|
Instantiate(deathEffect_);
|
||
|
deathEffect_.transform.position = myself_1.transform.position;
|
||
|
int criticalRandom = Random.Range(0, 3);
|
||
|
if (criticalRandom > 1)
|
||
|
{
|
||
|
playerScript.speedUp();
|
||
|
}
|
||
|
Destroy(myself_1);
|
||
|
}
|
||
|
|
||
|
//判断距离相关(计算敌人与玩家的距离)
|
||
|
private float CaculatePlayerDistance()
|
||
|
{
|
||
|
float posX = myself_1.transform.position.x;
|
||
|
float posZ = myself_1.transform.position.z;
|
||
|
Vector3 playerPos = Player.transform.position + Player.GetComponent<CapsuleCollider>().center;
|
||
|
float playerX = playerPos.x;
|
||
|
float playerZ = playerPos.z;
|
||
|
float distancePE = Mathf.Sqrt((playerX - posX) * (playerX - posX) + (playerZ - posZ) * (playerZ - posZ));
|
||
|
return distancePE;
|
||
|
}
|
||
|
|
||
|
//怪物活着的时候该做的事情
|
||
|
private void GhostAlive_()
|
||
|
{
|
||
|
if (status == 0 && distancePE_ > attackDistace)
|
||
|
{
|
||
|
GhostWalk_();
|
||
|
}
|
||
|
else if (status == 0 && distancePE_ <= attackDistace)
|
||
|
{
|
||
|
GhostStand_();
|
||
|
status = 1;
|
||
|
GhostAttack_();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
private void OnCollisionEnter(Collision collision)
|
||
|
{
|
||
|
if (collision.collider.gameObject.tag == "shield")
|
||
|
{
|
||
|
isDefended = true;
|
||
|
isTouched = true;
|
||
|
playerShield_ = GameObject.FindGameObjectWithTag("shield").GetComponent<LightShield>();
|
||
|
}
|
||
|
else if(collision.collider.gameObject.tag == "Player")
|
||
|
{
|
||
|
isAttackedPlayer = true;
|
||
|
isTouched = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IEnumerator AttackAction() {
|
||
|
warriorAnime_.SetBool("attack",true);
|
||
|
yield return new WaitForSeconds(attackTimer) ;
|
||
|
isDefended = false;
|
||
|
myself_1.GetComponent<BoxCollider>().enabled = true;
|
||
|
isAttacking_ = true;
|
||
|
yield return new WaitForSeconds(attackEndTimer);
|
||
|
isAttacking_ = false;
|
||
|
isDefended = false;
|
||
|
myself_1.GetComponent<BoxCollider>().enabled = false;
|
||
|
warriorAnime_.SetBool("attack",false);
|
||
|
yield return new WaitForSeconds(nextAttackTimer);
|
||
|
status = 0;
|
||
|
}
|
||
|
}
|