Unity使用多屏幕Display以及不同屏幕的射线检测

0.背景

最近在做一个双屏游戏,一个场景中有两个摄像机,分别渲染到两个屏幕显示,然后在点击不同的屏幕时,要从不同的摄像机发射射线检测与场景中的物体交互。

1.设置多屏

unity中设置多屏的方式很简单,选中摄像机组件中的Target Display属性即可。

86c90460d1c044c7a937e53bfdf2eb6a.png

2.显式地激活连接的屏幕

在确保连接了多个显示器后,需要在代码中显式地激活每个屏幕,且激活后不可关闭。

for (int i = 0; i < Display.displays.Length; i++)
{   
    //激活每个显示器
    Display.displays[i].Activate();
    // 将游戏窗口的分辨率设置为当前显示器的分辨率
    Screen.SetResolution(Display.displays[i].renderingWidth, Display.displays[i].renderingHeight, true);
}

注意!在编辑器模式下,无论你连接了多少个显示器,Display.displays.Length的值都是1。只有打包运行的时候,返回值才是真的连接的显示器个数。

3.获取鼠标点击位置

unity中可以直接根据Input.mousePosition来获取到当前鼠标的点击位置。

值得注意的是,在博主的测试下,打包后运行时,相当于将两个屏幕连成了一个大屏幕。那么两个屏幕的连接方式不同,就会导致最终的大屏幕也不一样。以下举例说明。

0f1c89dc81d34ea08e121c8a47d9e11d.png

17c12861b39b42b1828aa37bf7b74679.png

在window显示设置中,我的两块屏幕是按照扩展模式且左右连接的,那么在这种情况下,最终游戏运行时合成的一个大屏幕的分辨率是3840 x 1080(两块小屏幕都是1920 x 1080)。

4.判断当前点击的屏幕且发射射线检测

private void CheckCamera()
{
    Vector2 pos = Input.mousePosition;
    if (pos.x < Display.displays[0].systemWidth && pos.y < Display.displays[0].systemHeight)
    {
        SendRaycast(cameras[0], pos);
    }
    else
    {
        //注意在点击第二块屏幕时,要注意把鼠标坐标减去第一块屏幕的宽度,不然射线不准确
        SendRaycast(cameras[1], pos - new Vector2(Display.displays[0].systemWidth,0));
    }
}

private void SendRaycast(Camera camera, Vector2 pos)
{
    Ray ray = camera.ScreenPointToRay(pos);
    RaycastHit hit;
    Physics.Raycast(ray, out hit);
    if (hit.collider != null)
    {
        print("射线击中了 " + hit.collider.name);
    }
}

根据鼠标点击的位置,判断当前点击的是哪一块屏幕,从而用哪一个摄像机来发射射线检测。比如我的鼠标位置是(2880,540),那么由于x坐标大于了第一块屏幕的宽度(1920),那么表示当前鼠标点击的是第二块屏幕,因此要从摄像机2来发射射线。

值得注意的是,当点击第二块屏幕是,不能直接把当前的鼠标坐标(2880,540)传给camera.ScreenPointToRay(pos)。因为对于每一小块屏幕来说,分辨率是1920x1080,因此需要减去第一块屏幕的宽度,即pos - new Vector2(Display.displays[0].systemWidth,0),也就是说(960,540)才是我要传给camera.ScreenPointToRay(pos)的值。

### 如何在 Unity 中创建找不同游戏 #### 创建基本场景结构 为了构建一个简单的“找不同”游戏,在Unity中需要准备两个相似但存在细微差异的图片。这些图片可以放置于Sprite Renderer组件上,通过Canvas管理UI元素。 ```csharp using UnityEngine; using UnityEngine.UI; public class SpotTheDifference : MonoBehaviour { public Sprite[] images; // 存储两张对比图像 public Image imageDisplay; // 显示当前图像的Image控件 private int currentIndex = 0; void Start() { DisplayNextImage(); } /// <summary> /// 切换并显示下一张待比较的图像 /// </summary> void DisplayNextImage() { if (++currentIndex >= images.Length) currentIndex = 0; imageDisplay.sprite = images[currentIndex]; } } ``` 此脚本允许玩家切换查看两幅不同的图画[^1]。 #### 实现交互逻辑 为了让玩家能够点击指出差异之处,需编写额外的功能来检测鼠标点击位置,并判断该位置是否位于预设的不同点附近。这涉及到将屏幕坐标转换成世界坐标的操作[^2]: ```csharp void Update() { if (Input.GetMouseButtonDown(0)) { CheckForDifferences(Input.mousePosition); } } /// <summary> /// 检查所选位置是否有差异 /// </summary> /// <param name="screenPosition">屏幕空间中的触摸/点击位置</param> private void CheckForDifferences(Vector3 screenPosition) { Ray ray = Camera.main.ScreenPointToRay(screenPosition); RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction); if (hit.collider != null && hit.collider.CompareTag("Different")) { Debug.Log("找到了一处不同!"); // 处理找到不同的情况... } } ``` 上述代码利用射线投射技术确定用户点击的具体对象,并验证其是否标记为`"Different"`以确认是否真的发现了区别所在[^3]。 #### 设置视觉反馈机制 当玩家成功发现一处不同时,应该给予适当提示或奖励。可以通过改变颜色、播放音效等方式增强用户体验。例如,可以在碰撞体周围短暂闪烁一圈光晕效果表示恭喜。 ```csharp // 假设有预制好的粒子系统用于庆祝 [SerializeField] ParticleSystem celebrationEffect; if (hit.collider.CompareTag("Different")) { Instantiate(celebrationEffect, hit.point, Quaternion.identity); } ``` 以上就是基于Unity引擎开发简单版‘找不同’小游戏的核心思路和技术要点介绍[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值