首页 > 其他分享 >Unity判断对象是否在视野内

Unity判断对象是否在视野内

时间:2022-11-29 20:37:41浏览次数:53  
标签:positionOffset 对象 float transform Transform Unity 视野 targetObject


判断对象是否在视野内,有两种方式:

第一种:

  • 不设置固定的目标,
  • 使用LayerMask,设置寻找对象的Layer,
  • 使用Physics.OverlapSphere方法,以给定的位置为圆心,按照设定距离投射一个球体,返回与投射的球体相交的碰撞器。

第二种:

  • 设置固定的目标,
  • 计算当前对象与目标对象的距离direction.magnitude小于设定视野距离,
  • 计算当前对象的位置到目标点的方向与当前对象的前进方向的夹角Vector3.Angle(direction, transform.forward)小于设定视野角度,
  • 使用Physics.Linecast,如果有任何碰撞器与起始点与终点之间的射线相交,返回true。如果在视野内,返回目标对象。
using UnityEngine;

public class CanSeeObjectScript : MonoBehaviour
{
public Transform targetObject;
public Vector3 positionOffset;
public LayerMask objectLayerMask;
private Transform objectInSight;
public float fieldOfViewAngle;
public float viewDistance;

private void Update()
{
if (CanSeeObject())
{
Debug.Log("找到目标");
}
else
{
Debug.Log("没有找到目标");
}
}

private bool CanSeeObject()
{
if (targetObject == null)
{
// 如果目标对象为空,按照设定距离投射一个球体,检查在视野内与投射的球体相交的碰撞器
objectInSight = WithinSight(transform, positionOffset, fieldOfViewAngle, viewDistance, objectLayerMask);
}
else
{
// 如果目标对象不为空,则确定目标对象在视野内
objectInSight = WithinSight(transform, positionOffset, fieldOfViewAngle, viewDistance, targetObject);
}
if (objectInSight != null)
{
return true;
}
return false;
}

public static Transform WithinSight(Transform transform, Vector3 positionOffset, float fieldOfViewAngle, float viewDistance, LayerMask objectLayerMask)
{
Transform objectFound = null;
// Physics.OverlapSphere 检测场景中与投射的球体相交的碰撞器
var hitColliders = Physics.OverlapSphere(transform.position, viewDistance, objectLayerMask);
if (hitColliders != null)
{
float minAngle = Mathf.Infinity;
for (int i = 0; i < hitColliders.Length; ++i)
{
float angle;
Transform obj;
if ((obj = WithinSight(transform, positionOffset, fieldOfViewAngle, viewDistance, hitColliders[i].transform, false, out angle)) != null)
{
// 这个对象在视野内,并且角度小于任何其他的对象,设置位于当前对象最前面的对象到objectFound
if (angle < minAngle)
{
minAngle = angle;
objectFound = obj;
}
}
}
}
return objectFound;
}

public static Transform WithinSight(Transform transform, Vector3 positionOffset, float fieldOfViewAngle, float viewDistance, Transform targetObject)
{
float angle;
return WithinSight(transform, positionOffset, fieldOfViewAngle, viewDistance, targetObject, false, out angle);
}

private static Transform WithinSight(Transform transform, Vector3 positionOffset, float fieldOfViewAngle, float viewDistance, Transform targetObject, bool usePhysics2D, out float angle)
{
// 计算当前对象的位置到目标点的方向
var direction = targetObject.position - (transform.position + positionOffset);
// 计算当前对象的位置到目标点的方向与当前对象的前进方向的夹角
angle = Vector3.Angle(direction, transform.forward);
if (direction.magnitude < viewDistance && angle < fieldOfViewAngle * 0.5f)
{
// 目标对象需要在当前对象的视野内
if (LineOfSight(transform, positionOffset, targetObject, usePhysics2D) != null)
{
//如果在视野内,返回目标对象
return targetObject;
}
else if (targetObject.GetComponent<Collider>() == null)
{
// 如果linecast没有碰撞到任何对象,并且目标对象没有collider,没有什么阻碍
if (targetObject.gameObject.activeSelf)
return targetObject;
}
}
// 如果目标对象没有在视野内,返回空
return null;
}

public static Transform LineOfSight(Transform transform, Vector3 positionOffset, Transform targetObject, bool usePhysics2D)
{
RaycastHit hit;
// transform.TransformPoint方法,在原来位置的基础上加上偏移位置
// Physics.Linecast 如果有任何碰撞器与起始点与终点之间的射线相交,返回true
if (Physics.Linecast(transform.TransformPoint(positionOffset), targetObject.position, out hit))
{
if (hit.transform.Equals(targetObject))
{
//如果在视野内,返回目标对象
return targetObject;
}
}
return null;
}
}

 

标签:positionOffset,对象,float,transform,Transform,Unity,视野,targetObject
From: https://blog.51cto.com/u_6871414/5896973

相关文章

  • Unity--Physics.OverlapSphere的参数LayerMask和GameObject的layer
    Layer介绍:Unity中是用int32来表示32个Layer层。int32表示二进制一共有32位(0—31)在Unity中每个GameObject都有Layer属性,默认的Layer都是Default。在Unity中可编辑的Layer共......
  • Unity-Animator Override Controller
    AnimatorOverrideController是一种资产类型,允许您扩展现有的AnimatorController,替换使用的特定动画,但保留原始结构,参数和逻辑。允许您创建相同基本状态机的多个变体,但每......
  • Unity用户手册-AssetBundle
    AssetBundle什么是AssetBundle?AssetBundle实际上是一个资源管理包。AssetBundle包含了两个部分:数据头以及数据段。数据头内包含了AssetBundle的元数据信息,比如它的标识符......
  • 对象原型 原型链 原型继承 constructor属性
    原型:   每个构造函数身上都有一个prototype原型  原型身上有一个对象   被称为原型对象(构造函数的this和原型上的this都指向实例化对象)<body>......
  • 1-Unity学习计划
    1、Unity3D程序开发基础-从基础讲解C#语言,熟悉字段、属性、接口、委托、事件,掌握C#面向对象编程的核心思想。让学员掌握Unity3d各个方面的知识和基本使用方法,为后面深入的......
  • 虹科分享 | 网络仿真器 | 预测云中对象存储系统的实际性能
    对象存储是一种在云中存储非结构化数据的方法,从理论上讲,它使得以其原始格式存储几乎无限量的数据成为可能。在这种存储架构中,数据被作为对象进行管理,而传统的系统则将数据作......
  • python-面向对象- 实例方法,类方法,静态方法, 类属性
    名称定义方法权限调用方法实例方法第一个参数必须是示例,一般命名为self可以访问实例的属性和方法,也可以访问类的实例和方法一般通过示例调用,类也可以调用类方法......
  • StringUtils 使用更新对象的非空值去覆盖待更新对象
    //使用更新对象的非空值去覆盖待更新对象StringUtils.copyPropertiesIgnoreNull(device,dev);//用device对象去覆盖dev对象复制属性:将attr实体中的属性一一拷贝给attrE......
  • 01. 魔法球特效_Unity Visual Effect Graph
    效果图01.粒子线条02.中心球体03.周边粒子 特效来源于:GabrielAguiarProd的VisualEffectGraph教程想学习更多的特效可以去UnityVFXGraph-BeginnerToInte......
  • 百度地图之收索视野内的建筑物
    1.  mysqlspatial介绍  从MySQL4.0开始加入了Spatial扩展功能,实现了OpenGIS规定的几何数据类型,在SQL中的简单空间运算。但是MySQL对空间查询的支持不够完善,要进行复杂......