先上图,一些RPG游戏中,可以用这种方法检测玩家,我个人感觉这个方法比直接给敌人加触发器,要来得方便一些。
注意:脚本是根据tag标签来检测玩家的,请勿忘记给玩家添加标签~
using UnityEngine;
/// <summary>
///
/// * Writer:June
/// *
/// * Data:2021.5.1
/// * 2022.7.13 修改
/// *
/// * Function:玩家检测
/// *
/// * Remarks:
///
/// </summary>
public class PlayerCheck : MonoBehaviour
{
/// <summary>
/// 检测半径
/// </summary>
public float radius;
/// <summary>
/// 缓存器容量
/// </summary>
private const int MAX_COUNT = 10;
/// <summary>
/// 缓存处在检测范围内的碰撞体
/// </summary>
private Collider[] colliders;
private void Start()
{
colliders = new Collider[MAX_COUNT];
}
private void Update()
{
FoundPlayer();
}
private void FoundPlayer()
{
//球形范围检测器
#region 这个是一种解决方案,但会每隔一段时间会产生GC,不推荐使用
//var colliders = Physics.OverlapSphere(transform.position, radius);
//foreach (var target in colliders)
//{
// if (target.CompareTag("Player"))
// {
// Debug.LogError("发现玩家!");
// }
//}
#endregion
#region 计算与球体接触或位于球体内部的碰撞体,并将它们存储到提供的缓冲区中。
//在范围内的所有碰撞体数量
int colliderCount = Physics.OverlapSphereNonAlloc(transform.position, radius, colliders);
for (int i = 0; i < colliderCount; i++)
{
if (colliders[i].CompareTag("Player"))
{
Debug.LogError("发现玩家!");
}
}
#endregion
}
/// <summary>
/// 在编辑器里绘制Gizmos(一般用于scene窗口中便于观看,实际运行中可注释或删除)
/// </summary>
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
//绘制球形线框范围
Gizmos.DrawWireSphere(transform.position, radius);
}
}
一开始我使用的是OverlapSphere,在此先感谢评论区的大佬的指出问题,OverlapSphere没有缓存机制,每隔一段时间会调用一次GC,显然是不可取的,而OverlapSphereNonAlloc是有缓存的,当进入范围内的碰撞体,检测并会加入到指定的缓存数组中。
两种解决方式都在代码中,可以复制1000份带有脚本的物体,打开profiler查看,就很明显看出来差距。