一、背景
如何检测一个对象范围内的玩家,这个可以直接使用距离判定,物体射线检测等相关方式;这里采用Physics.OverlapSphere的方式来实践其过程,并对Physics.OverlapSphere的使用做一下记录;
二、Physics.OverlapSphere
1、该API表示采用球体的方式进行物体的范围检测;那什么是球体,看下面的动画:
上图就是Unity中创建的一个Sphere;想篮球、乒乓球也是这种形状;那么我们需要检测范围区域就是这种球形;
2、该球形检测的API有两个:
2.1 Physics.OverlapSphere(Vector3 position, float radius, int layerMask)
2.2 Physics.OverlapSphere(Vector3 position, float radius)
这两个API的区别就在于layerMask;如果你指定了layerMask,那么检测的对象就只针对指定的LayerMask,否则就是所有的碰撞体都会检测;
对该API进行详细说明:
position:表示需要指定的检测的位置,如下动画:
上面移动的的位置就是该对象需要检测的起始位置,也就是这个球体的球心;整个检测的起始点位置;
radius: 表示该球心的半径,看动画:
可以看到上面的颜色部分,只是绘制除了一个平面的部分半径可视化的直线;当在进行检测的时候和半径的大小相关联;半径内的可以检测到,半径以外的不可以检测;
layerMask: 可以设置,也可以不设置,如果设置那么就用方式:LayerMask.GetMask(“BoxCollider”); 进行设置;如果不进行设置就检测所有的Layer;这里的BoxCollider是自定义的Layer名字;
三、实践效果
1、检测LayerMask为BoxCollider的物体是否在球体范围内;半径可以调节:动画演示:
默认白色的Cube表示没有被检测到,颜色变为红色的Cube表示在Sphere的范围内;
在上面的动画中:左右两个Cube的Layer为BoxCollider;上下两个Cube的layer为Default;
1.1 、可以看到在半径以外是不会被检测到的,也就是Cube不会变红的;
1.2、即使在半径范围内,如果和需要检测的LayerMask不一样,那么Cube也是不会变红的;
2、检测所有,不区分LayerMask 动画演示:
该动画就是不区分LayerMask,所有可以碰撞的物体都会被检测,如果在半径范围内,那么就会被检测到;
注意
既然是物体碰撞检测,那么被检测的对象一定要有Collider,要不然是不会被检测到的;以上就是通过可视化事件范围内NpC的检测;
四、源码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[ExecuteAlways]
public class PhysicsSphereTest : MonoBehaviour
{
private SphereCollider _sphereCollider;
[SerializeField] private Material _material;
[SerializeField] private Material defaultMaterial;
[SerializeField] private List<MeshRenderer> _meshRenderers;
private void Awake()
{
_sphereCollider = GetComponent<SphereCollider>();
}
// Start is called before the first frame update
void Start()
{
}
private void OnDrawGizmos()
{
if (_sphereCollider == null)
_sphereCollider = GetComponent<SphereCollider>();
float radius = _sphereCollider.radius;
for (int angel = 0; angel < 360; angel += 2)
{
double x = Math.Cos(angel * 1.0f);
double z = Math.Sin(angel * 1.0f);
Vector3 v3 = Vector3.one;
v3.y = 0;
v3.x = (float) x * radius;
v3.z = (float) z * radius;
Vector3 target = transform.position + v3;
Debug.DrawLine(transform.position, target, Color.magenta);
}
ResetMaterial();
int layer = LayerMask.GetMask("BoxCollider");
// Collider[] colliders = Physics.OverlapSphere(transform.position, radius, layer);
Collider[] colliders = Physics.OverlapSphere(transform.position, radius);
foreach (var boid in colliders)
{
boid.GetComponent<MeshRenderer>().material = _material;
}
}
void ResetMaterial()
{
foreach (var mr in _meshRenderers)
{
mr.material = defaultMaterial;
}
}
}
五、结语
外面下雨,但屋里有点热[valaki]