日志2025.2.18
1.完善了远程敌人的遮蔽系统
public class Cover : MonoBehaviour
{
[SerializeField] private GameObject coverPointPrefab;
public List<CoverPoint> coverPoints = new List<CoverPoint>();
[SerializeField] private Vector3 offset = new Vector3(1f, 0f, 1f);
private Transform playerTransform;
private void Awake()
{
playerTransform = FindFirstObjectByType<Player>().transform;
}
private void Start()
{
GenarateCoverPoints();
}
private void GenarateCoverPoints()
{
Vector3[] localCoverPoints =
{
new Vector3(0, offset.y, offset.z), //前
new Vector3(0, offset.y, -offset.z), //后
new Vector3(offset.x, offset.y, 0), //右
new Vector3(-offset.x, offset.y, 0) //左
};
foreach (Vector3 localPoint in localCoverPoints)
{
Vector3 worldPoint = transform.TransformPoint(localPoint);
CoverPoint coverPoint =
Instantiate(coverPointPrefab, worldPoint, Quaternion.identity, transform).GetComponent<CoverPoint>();
coverPoints.Add(coverPoint);
}
}
public List<CoverPoint> GetValidCoverPoints(Transform EnemyTransform)
{
List<CoverPoint> validCoverPoints = new List<CoverPoint>();
foreach (CoverPoint coverPoint in coverPoints)
{
if(IsValidCoverPoint(coverPoint, EnemyTransform))
validCoverPoints.Add(coverPoint);
}
return validCoverPoints;
}
private bool IsValidCoverPoint(CoverPoint coverPoint, Transform EnemyTransform)
{
if(coverPoint.occupied)
return false;
if(IsFurthestCoverPoint(coverPoint) == false)
return false;
if(IsCoverPointBehindPlayer(coverPoint, EnemyTransform))
return false;
return true;
}
private bool IsFurthestCoverPoint(CoverPoint coverPoint)
{
CoverPoint furthestPoint = null;
float furthestDistance = 0f;
foreach(CoverPoint point in coverPoints)
{
float distance = Vector3.Distance(point.transform.position, playerTransform.position);
if(distance > furthestDistance)
{
furthestDistance = distance;
furthestPoint = point;
}
}
return furthestPoint == coverPoint;
}
//判断遮蔽点是否在玩家身后
private bool IsCoverPointBehindPlayer(CoverPoint coverPoint, Transform enemyTransform)
{
float distanceToPlayer = Vector3.Distance(coverPoint.transform.position, playerTransform.position);
float distanceToEnemy = Vector3.Distance(coverPoint.transform.position, enemyTransform.position);
return distanceToPlayer < distanceToEnemy;
}
}
#region Cover System
public bool CanRunToCover()
{
if (canUseCovers == false)
return false;
AttemptFindCoverPoint();
if(currentCoverPoint == null)
return false;
return true;
}
public Transform AttemptFindCoverPoint()
{
List<CoverPoint> collectedCoverPoints = new List<CoverPoint>();
foreach (Cover cover in allCovers)
{
collectedCoverPoints.AddRange(cover.GetValidCoverPoints(transform));
}
CoverPoint lastestCoverPoint = null; //最近的有效的遮蔽点
float minDistance = float.MaxValue;
foreach (CoverPoint coverPoint in collectedCoverPoints)
{
float distance = Vector3.Distance(transform.position, coverPoint.transform.position);
if(distance < minDistance)
{
minDistance = distance;
lastestCoverPoint = coverPoint;
}
}
if(lastestCoverPoint != null)
{
lastCoverPoint = currentCoverPoint;
lastCoverPoint?.SetOccupied(false);
currentCoverPoint = lastestCoverPoint;
currentCoverPoint.SetOccupied(true);
return currentCoverPoint.transform;
}
return null;
}
private List<Cover> CollectNearCovers()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, checkCoverRadius);
List<Cover> collectedCovers = new List<Cover>();
foreach (Collider collider in colliders)
{
Cover cover = collider.GetComponent<Cover>();
//collectedCovers.Contains(cover) == false 是为了防止一个物体有多个碰撞体而导致的重复计入
if (cover != null && collectedCovers.Contains(cover) == false)
{
collectedCovers.Add(cover);
}
}
return collectedCovers;
}
#endregion
private void ShouldRunToCover()
{
checkCoverTimer -= Time.deltaTime;
if (checkCoverTimer <= 0)
{
checkCoverTimer = 0.5f;
if (IsPlayerInClearSight())
{
if (enemy.CanRunToCover())
{
stateMachine.ChangeState(enemy.runToCoverState);
}
}
}
}
private bool IsPlayerInClearSight()
{
if(Physics.Raycast(enemy.transform.position, enemy.DirectionToPlayer(), out RaycastHit hit))
{
return hit.collider.GetComponentInParent<Player>();
}
return false;
}