用途
如需要提示玩家点击目标内容时
做法
- 黑色遮罩所属的Canvas的RenderMode应设置为ScreenSpace—Camera
- UICamera的制作
ClearFlags:Depth only
CullingMask:UI
Depth:大于MainCamera的 - 新增一个层:Top
- SetToTopSys的实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 将目标物设置到最前(通常是设置到黑色遮罩之前)
/// </summary>
public class SetToTopSys
{
private static SetToTopSys _instance;
public static SetToTopSys Instance
{
get
{
if (_instance == null)
{
_instance = new SetToTopSys();
}
return _instance;
}
}
private Camera _cam;
private const string TargetLayerMaskName = "Top";
private readonly int UiCanvasOrderInLayer;
private SetToTopSys()
{
InitCam();
// 初始化UICanvas的Order(要比其他所有的都大)
int value = -1;
var allCanvas = GameObject.FindObjectsOfType<Canvas>();
foreach (var c in allCanvas)
{
if (value < c.sortingOrder)
{
value = c.sortingOrder;
}
}
value++;
UiCanvasOrderInLayer = value;
void InitCam()
{
// 新创建的Cam的Depth应是所有Depth中最大的!
var cams = GameObject.FindObjectsOfType<Camera>();
float depth = -1;
foreach (var cam in cams)
{
if (depth < cam.depth)
{
depth = cam.depth;
}
}
depth++;
_cam = new GameObject("TopCam").AddComponent<Camera>();
_cam.clearFlags = CameraClearFlags.Depth;
_cam.cullingMask = 1 << LayerMask.NameToLayer(TargetLayerMaskName);
_cam.orthographic = Camera.main.orthographic;
_cam.orthographicSize = Camera.main.orthographicSize;
_cam.depth = depth;
_cam.transform.SetParent(Camera.main.transform);
_cam.transform.localPosition = Vector3.zero;
_cam.transform.localRotation = Quaternion.identity;
_cam.transform.localScale = Vector3.one;
}
}
public void MyDestroy()
{
DestroyCam();
void DestroyCam()
{
if (_cam != null)
{
GameObject.Destroy(_cam.gameObject);
_cam = null;
}
}
}
public void SetUiGoToTop(GameObject uiGo)
{
if (uiGo.GetComponent<Canvas>() == null)
{
var canvas = uiGo.AddComponent<Canvas>();
canvas.overrideSorting = true;
canvas.sortingOrder = UiCanvasOrderInLayer;
uiGo.AddComponent<GraphicRaycaster>();
}
}
public void ResetUiGo(GameObject uiGo)
{
Object.Destroy(uiGo.GetComponent<GraphicRaycaster>());
Object.Destroy(uiGo.GetComponent<Canvas>());
}
public void SetSceneGoToTop(GameObject go)
{
SetLayer(go, LayerMask.NameToLayer(TargetLayerMaskName));
}
public void ResetSceneGo(GameObject go, int originalLayer)
{
SetLayer(go, originalLayer);
}
// 设置自己及所有子孙节点的Layer
private void SetLayer(GameObject go, int layer)
{
var transforms = go.GetComponentsInChildren<Transform>(true);
foreach (var trans in transforms)
{
trans.gameObject.layer = layer;
}
}
public void EnableCam()
{
_cam.gameObject.SetActive(true);
}
public void DisableCam()
{
_cam.gameObject.SetActive(false);
}
}
- 调用示意
SetToTopTest
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SetToTopTest : MonoBehaviour
{
[SerializeField]
private GameObject[] _uiGos;
[SerializeField]
private GameObject[] _sceneGos;
[SerializeField]
private string _originalLayerName;
private void Start()
{
Init();
}
private void Update()
{
MyUpdate();
}
private void OnDestroy()
{
MyDestroy();
}
private void Init()
{
}
private void MyUpdate()
{
// 目标UI显示到最前
if (Input.GetKeyDown(KeyCode.A))
{
foreach (var go in _uiGos)
{
SetToTopSys.Instance.SetUiGoToTop(go);
}
}
// 目标UI不显示到最前
else if (Input.GetKeyDown(KeyCode.B))
{
foreach (var go in _uiGos)
{
SetToTopSys.Instance.ResetUiGo(go);
}
}
// 目标物件显示到最前
else if (Input.GetKeyDown(KeyCode.C))
{
foreach (var go in _sceneGos)
{
SetToTopSys.Instance.SetSceneGoToTop(go);
}
}
// 目标物件不显示到最前
else if (Input.GetKeyDown(KeyCode.D))
{
foreach (var go in _sceneGos)
{
SetToTopSys.Instance.ResetSceneGo(go, LayerMask.NameToLayer(_originalLayerName));
}
}
}
private void MyDestroy()
{
}
}
网友评论