UGUI提供了分屏显示功能,可以通过 Canvas 的 TargetDisplay 属性指定在哪个显示器进行显示,但是经过实践发现,该功能存在一些Bug,主要是两个分屏的UGUI会相互干扰,(点击屏幕A内的UI,其他界面相应位置也会被点击),根据官方的说法,由于当前版本(2017.4.2f2)多屏显示存在问题,所以UGUI的多屏显示无法进行修复。(吐槽下Unity对PC端的支持和更新真是差)
为了解决该问题,需要研究一下UGUI的源码,找到问题的原因和解决办法,这里使用的是 ILSpy 对Dll进行反编译,也可以直接去 BitBucket 下载对应版本的 UGUI源码 进行查看,造成两个屏幕操作相互干扰主要原因是由射线检测引起,所以这里需要对GraphicRaycaster进行分析和修改,所幸,Raycast检测接口是 virtual 可重写的,只需要继承 GraphicRaycaster 对 Raycast接口进行重写即可,直接上代码。
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System;
using UnityEngine;
#if UNITY_EDITOR
using System.Reflection;
using UnityEditor;
#endif
public class MultiDisplayUtil
{
delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData);
[DllImport("user32.dll")]
static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);
[DllImport("user32.dll")]
static extern bool GetMonitorInfo(IntPtr hMonitor, ref MonitorInfo lpmi);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(out POINT lpPoint);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
public bool Contains(int x, int y)
{
return x >= this.left && x < this.right && y >= this.top && y < this.bottom;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal struct MonitorInfo
{
/// <summary>
/// The size, in bytes, of the structure. Set this member to sizeof(MONITORINFOEX) (72) before calling the GetMonitorInfo function.
/// Doing so lets the function determine the type of structure you are passing to it.