开发平台:Unity 2020 编程平台:Visual Studio 2022
前言在游戏中,玩家观测世界的方式是通过主摄像机(Main Camera)进行。将摄像机视线中的画面呈现于屏幕上,即游戏视线。在开发中,这类游戏视线的应用范围广泛,例如 Unity Technology 提供的 Occlusion Culling(遮挡剔除)的整体优化手段。或是 《Secret Library》 游戏中,对 Area Room 模型的优化加载方式,亦或是用于显示游戏角色 Monster 阵营的特性。本文以探讨基于游戏视线的娱乐性构思与设计。
思考:如何判断对象是否在摄像机范围内 判断对象,最可能想到的使用方式是 Physics.RayCast()
物理射线检测。即通过 Camera.Main
发射射线进行识别与获取对象 Transform 组件信息,以判断对象是否在摄像机范围内。在Unity 2018版本中,有一款名为 InstanceOS 的优化插件,也是后来 Unity 版本中 Occlusion Culling(遮挡剔除) ,相比较下两者大同小异。 Unity Technology 提供的 OC 原理是针对设置 Occluder Static 的 GameObject 对象进行 视窗判断。在场景视窗内的游戏对象,保持激活状态;不可见的游戏对象将保持禁用状态,以最终达到运行时最佳优化效果。
通过使用多个屏幕坐标,批量性创建物理射线,对射线碰撞对象进行检测信息。有则返回游戏对象信息,无则返回Null
。
public void LateUpdate()
{
List points = GetScreenPoints(100, 100);
foreach (var item in points)
{
Ray _Ray = ScreenPointToRay(item);
string result = Physics.Raycast(_Ray, out RaycastHit hit) ? "I m Looking!" : "I m not Looking";
Debug.Log(result);
}
}
GetScreenPoints(int x, int y)
:获取屏幕坐标点数据集,返回类型List
。该方法基于Screen.width
与Screen.height
进行均等份屏幕坐标。为后续射线做准备。Screen.width
=Camera.main.pixelWidth
Screen.height
=Camera.main.pixelHeght
◼ 问题点:批量性使用物理射线对计算机性能损耗程度高。(官方文档与民间开发者实践反馈与分享)
2)基于屏幕坐标的检测方式public string CheckIsInScreen_ScreenPoint()
{
// targetTF 即目标 Transform组件
Vector3 current = Camera.main.WorldToScreenPoint(targetTF.position);
if (current.x >= 0f && current.x = 0f && current.y = 0f && current.x = 0f && current.y Debug.Log("In Screen");
public void OnBecameInvisible() => Debug.Log("Out Screen");
OnBecameVisible()
:当物体出现在 摄像机视角下时,执行一次命令内容。OnBecameInvisible()
:当物体消失在 摄像机视角下的那一刻,执行一次命令内容。
值得注意的是,对 Mesh Renderer 或准确意义上说是继承于 Renderer 基类的对象均可使用此类方法。且此方法仅适用于被检测的对象自身。要求该对象拥有且激活该类型的 Renderer 子类组件。 在表现上,并非是肉眼见透过屏幕空间观察到对象出现或消失后即可发送消息。而是在小时后相机视野移动一小部分忽略不计的距离后进行消息传送。总体上并不影响问题。 ◼ 问题点:
- 目标 与 摄像机 中存在遮挡物的情况下,该两方法依旧正常执行。 解决方法(暂):使用
ScreenPointToRay()
建立射线检测机制(单条),用于判断对象是否为障碍物 或 目标对象。是则发送消息,否则不然。 其他说明:在检测上建议设立白名单忽略层,例如 玻璃、铁网(贴图)等层可能会阻碍正常的射线检测。应避免此情况发生。
行为逻辑描述:
- 在摄像机观察范围内:视野范围内,不可移动,直到观察者主动偏移至视野内无该对象情况下。
- 在摄像机观察范围外:自由高速移动。
- 建立触发机制 - 观测机制。当物体渲染出现至 摄像机 视野范围内时,启用视口坐标的观测方法。 1)在多人游戏下,建议使用 MyCamera、CustomCamera 两种标签(Tag)区别 自己客户端与其他客户端用户的摄像机。 2)仅针对己摄像机情况下进行 视口坐标/屏幕坐标(二选一)进行位置判断。同理,在触发退出机制时,通知服务器终止位置判断。 注:考量到联网数据传递与实际出现最高权限干涉出现多数目的编号对象下,独立各自的检测机制。交由服务器计算结果处理。
- 建立计算规则 - 影响逻辑。在 屏幕坐标/视口坐标 的计算判断中。重点的距离判断(Z轴轴值) 须注意:其计算的距离属于 目标 - 摄像机。实际上距离最低限制不局限于0f。有关具体合适的数据可调整。而为保证游戏性,也会设置距离最大值进行限制。使其仅在距离范围内生效规则。
小结
或许 在遮挡物 判断上 Unity 有提供此类的API方法。或者整体的实现上更具备最优方案待发现与学习了解。期待这篇思路分享有助于开发者的开发进程。