196 lines
6.1 KiB
C#
196 lines
6.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using DragonLi.Core;
|
|
using UnityEngine;
|
|
|
|
public class SharkFish : Fish
|
|
{
|
|
[Header("鲨鱼设置")]
|
|
[NonSerialized]
|
|
public float patrolRadius = 8f; // 巡逻半径
|
|
[NonSerialized]
|
|
public float patrolSpeed = 0.5f; // 巡逻速度
|
|
[NonSerialized]
|
|
public float attackSpeed = 4f; // 攻击速度
|
|
[NonSerialized]
|
|
public float attackInterval = 10f; // 攻击间隔
|
|
|
|
[Header("攻击设置")]
|
|
public float attackDistance = 1.5f; // 攻击距离
|
|
public float retreatDistance = 5f; // 撤退距离
|
|
|
|
public Animator animator;
|
|
|
|
private Transform player;
|
|
private SharkState currentState;
|
|
private float attackTimer;
|
|
private int showTime;
|
|
private float curShowTime;
|
|
private Vector3 circleCenter;
|
|
|
|
// 鲨鱼状态枚举
|
|
private enum SharkState
|
|
{
|
|
Patrolling, // 圆形巡逻
|
|
Attacking, // 攻击玩家
|
|
Retreating // 撤退
|
|
}
|
|
void Start()
|
|
{
|
|
player = GameManager.Ins.player.transform;
|
|
currentState = SharkState.Patrolling;
|
|
// 攻击间隔改为20-30秒随机
|
|
attackInterval = UnityEngine.Random.Range(20f, 30f);
|
|
attackTimer = attackInterval;
|
|
circleCenter = player.position;
|
|
showTime = 60;
|
|
StartCoroutine(SharkAI());
|
|
}
|
|
|
|
IEnumerator SharkAI()
|
|
{
|
|
// 鲨鱼存活且显示时间未到1分钟时继续循环
|
|
while (curShowTime <= showTime && state == FishState.Alive)
|
|
{
|
|
switch (currentState)
|
|
{
|
|
case SharkState.Patrolling:
|
|
animator.SetInteger("state",0);
|
|
yield return StartCoroutine(PatrolBehavior());
|
|
break;
|
|
case SharkState.Attacking:
|
|
animator.SetInteger("state",1);
|
|
yield return StartCoroutine(AttackBehavior());
|
|
break;
|
|
case SharkState.Retreating:
|
|
animator.SetInteger("state",0);
|
|
yield return StartCoroutine(RetreatBehavior());
|
|
break;
|
|
}
|
|
|
|
curShowTime += Time.deltaTime;
|
|
yield return new WaitForEndOfFrame(); // 关键:等待一帧
|
|
}
|
|
|
|
OnSplineEnd();
|
|
}
|
|
|
|
// 圆形巡逻行为
|
|
IEnumerator PatrolBehavior()
|
|
{
|
|
float angle = 0f;
|
|
|
|
while (attackTimer > 0 && currentState == SharkState.Patrolling)
|
|
{
|
|
attackTimer -= Time.deltaTime;
|
|
|
|
// 更新圆形中心点为玩家当前位置
|
|
circleCenter = player.position;
|
|
|
|
// 圆形运动
|
|
angle += patrolSpeed * Time.deltaTime;
|
|
Vector3 targetPosition = circleCenter + new Vector3(
|
|
Mathf.Cos(angle) * patrolRadius,
|
|
0,
|
|
Mathf.Sin(angle) * patrolRadius
|
|
);
|
|
|
|
// 计算移动方向(前进方向)
|
|
Vector3 moveDirection = (targetPosition - transform.position).normalized;
|
|
|
|
// 如果移动方向不为零,让鲨鱼面向前进方向
|
|
if (moveDirection != Vector3.zero)
|
|
{
|
|
Quaternion targetRotation = Quaternion.LookRotation(moveDirection);
|
|
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 5f * Time.deltaTime);
|
|
}
|
|
|
|
// 平滑移动到目标位置
|
|
transform.position = Vector3.Lerp(transform.position, targetPosition, 2f * Time.deltaTime);
|
|
|
|
yield return null;
|
|
}
|
|
|
|
if (attackTimer <= 0)
|
|
{
|
|
currentState = SharkState.Attacking;
|
|
// 重置计时器为20-30秒随机
|
|
attackInterval = UnityEngine.Random.Range(20f, 30f);
|
|
attackTimer = attackInterval;
|
|
}
|
|
}
|
|
|
|
// 攻击行为
|
|
IEnumerator AttackBehavior()
|
|
{
|
|
Vector3 attackDirection = (player.position - transform.position).normalized;
|
|
float attackStartTime = Time.time;
|
|
float maxAttackDuration = 3f;
|
|
|
|
while (currentState == SharkState.Attacking)
|
|
{
|
|
// 朝向玩家
|
|
transform.rotation = Quaternion.LookRotation(attackDirection);
|
|
|
|
// 冲向玩家
|
|
transform.position += attackDirection * attackSpeed * Time.deltaTime;
|
|
GameManager.Ins.PlaySound3D("鲨鱼袭击",transform,true);
|
|
// 检查是否到达攻击距离
|
|
float distanceToPlayer = Vector3.Distance(transform.position, player.position);
|
|
if (distanceToPlayer <= attackDistance)
|
|
{
|
|
// 攻击玩家
|
|
AttackPlayer();
|
|
currentState = SharkState.Retreating;
|
|
break;
|
|
}
|
|
|
|
// 防止攻击时间过长
|
|
if (Time.time - attackStartTime > maxAttackDuration)
|
|
{
|
|
currentState = SharkState.Retreating;
|
|
break;
|
|
}
|
|
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
// 撤退行为
|
|
IEnumerator RetreatBehavior()
|
|
{
|
|
Vector3 retreatDirection = (transform.position - player.position).normalized;
|
|
float retreatStartTime = Time.time;
|
|
float retreatDuration = 2f;
|
|
|
|
while (Time.time - retreatStartTime < retreatDuration && currentState == SharkState.Retreating)
|
|
{
|
|
// 远离玩家撤退
|
|
transform.position += retreatDirection * patrolSpeed * Time.deltaTime;
|
|
yield return null;
|
|
}
|
|
|
|
// 回到巡逻状态
|
|
currentState = SharkState.Patrolling;
|
|
}
|
|
|
|
// 攻击玩家
|
|
void AttackPlayer()
|
|
{
|
|
// 触发屏幕特效
|
|
EventDispatcher.TriggerEvent("PlayerHit",0);
|
|
}
|
|
|
|
void OnDrawGizmosSelected()
|
|
{
|
|
// 绘制巡逻范围
|
|
Gizmos.color = Color.blue;
|
|
Gizmos.DrawWireSphere(circleCenter, patrolRadius);
|
|
|
|
// 绘制攻击距离
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawWireSphere(transform.position, attackDistance);
|
|
}
|
|
}
|