Unity3D:如何找出场景中某个点的覆盖程度?

问候!

我知道,从本质上讲,您知道您缺少哪些纸牌游戏或三合一游戏。 隐形系统!

当然,任何自尊的隐形系统都应该能够考虑到玩家周围环境的光照。 我惊讶地发现了这个话题,发现异常少量的信息。 因此,我赶紧分享成果。

今天,我们将不为玩家开发完整的隐形系统,我们仅考虑与照明的交互。

方法1:撞机


一种简单但不是很耗资源的方法。

我们向每个光源添加一个球形对撞机。 我们使其成为触发器。 我们将尺寸设置为大约等于光的半径。

其余的就像阴影一样清晰。 我们正在编写一个简单的脚本,在该脚本中,我们在OnTriggerEnter()中激活灯光计算功能(这样,当玩家不在附近时,光源就不会“空转”)。

照度计算本身将位于Update()中。 本质上,这是通常的Physics.Raycast()。 如果它击中了播放器,则该播放器处于亮区。 如果它没有掉落,则表示玩家在障碍物后面,因此在阴影中。

您还可以在此处添加播放器和光源之间距离的计算。 因此,为了确定照度,我们将使用一个简单的浮标,该浮标将根据距光源的距离而变化。 而且,您可以随时随地使用它。

例子

在点1,照明接近最大值。 在第2点,光照很小-在该点和该点之间有障碍物。 在点3,照度是平均的。

不仅如此! 您可以将触发对撞机添加到玩家必须隐藏的各个“阴影区域”。 遵循Manhunt的最佳传统。 同样,您可以使用对撞机标记亮区,例如模拟聚光灯。

优点:


  • 易于定制点光源。
  • 如果您不发送垃圾邮件,则在资源方面非常经济。

缺点:


  • 对聚光灯和定向光进行了严格的调整。 如果第一种情况足以将对撞机放置在光场中(以增加玩家在入口处的能见度),那么第二种情况确实令人恐惧。 您需要在每个阴影处放置对撞机(以减少玩家在入口处的可见性),或使用Physics.Raycast()不断检查玩家与“太阳”之间的位置-它位于光线下方或阴影中。
  • 大量的对撞机使场景变得混乱,使物理复杂化。
  • 必须注意相交的光源。
  • 需要通过脚本分别添加动态光(移动或改变强度)。

方法2:RenderTexture


我们在这里做什么? 实际上,我们从摄像机(而不是从主摄像机)获得“屏幕快照”。 然后,我们分析屏幕截图的颜色,以找出明亮的光线如何照射到主体上。

首先,我们需要一个从中“读取”光线的对象。 创建一个常规球体或平面,使其变小(比例尺为0.1),将其放置在靠近地面的位置,使其变白,然后移除对撞机:

隐藏文字


添加一个摄像头(确保删除音频侦听器并检查MainCamera标签是否值得)。 将其绑定到我们的对象。 我们将其放高一点,然后将其放低。 我们在设置中不显示主屏幕。 正字法照您的口味。

最后,我们将其放置在适当的位置,以便仅查看对象。

隐藏文字


最后,配置主摄像机和辅助摄像机的消隐遮罩,以使主摄像机不显示我们的“亮”对象,而辅助摄像机仅看到它们,而不会弄乱其他任何东西。

从这里开始乐趣。 我们将脚本附加到相机:

public Camera cam; //   RenderTexture tex; Texture2D _tex; void Start () { //    "". // ,       -   . // Depth   0   -   . tex = new RenderTexture (1, 1, 8); // RenderTexture "" , //   ,    . _tex = new Texture2D (1, 1, TextureFormat.RGB24, false); } void Update () { //   ""  cam.targetTexture = tex; cam.Render (); //     RenderTexture.active = tex; //   Texture2D _tex.ReadPixels (new Rect (0, 0, 1, 1), 0, 0); _tex.Apply (); Color col = _tex.GetPixel (0, 0); float vis = (col.r + col.g + col.b) / 3; } 

在输出中,我们得到一个浮动的vis,从本质上讲,它是入射在我们物体上的照明水平的数字表示。 如果源关闭-对象为白色-可见为1。如果源为暗-对象为黑色-可见为〜0。

我们不需要每一帧都执行上述操作,因此我们嵌入了一个小的第二个计时器:

 float interval = 0; void Update () { interval += Time.deltaTime; if (interval < 1) return; interval = 0; //   } 

接下来,我们将整个系统绑定到玩家,以便它随他一起移动。 并且我们的vis变量会自动在播放器周围返回光!

该系统不仅可以与播放器一起使用。 您可以将其放置在任何位置,并根据需要创建一种光传感器。 通常,有更有效的方法来实现它们,但是拥有替代方法总是很好吗?

优点是显而易见的,让我们谈谈缺点。

缺点


  • 每个“光检测器”(如果有多个)都需要一个单独的摄像头。
  • Texture2D.ReadPixels()-很好,非常慢。 即使您每秒执行一次,而不是每隔一帧一次,即使您破坏了将纹理写入和读取到不同帧中的功能,仍然存在40-110ms的布局。
  • 该系统未考虑一些罕见情况。 例如,手电筒照在角色上。 角色光线很好,但是光线分别照射到他和他的身后,而不是落下,我们的光检测器显示出低照度。 您可以解决问题,例如,通过将探测器不放在地板上,而是放置在角色胸部的水平上。 然后,您需要将两个摄像头放在相对的两侧以读取任一侧的光。 什么会使系统速度减半。

Source: https://habr.com/ru/post/zh-CN417135/


All Articles