NGUI AnchorPoint与Camera CullingMask的结合之痛

2024-04-12 21:18

本文主要是介绍NGUI AnchorPoint与Camera CullingMask的结合之痛,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题

NGUI内建的Anchor系统可以方便的定位UI(底层的一个支持结构是AnchorPoint),例如一些需要全屏显示的游戏界面一般都需要借助这项功能;另外的,对于稍复杂的UI设计,我们可能会将UI进行分层处理,一些游戏状态下我们可能也会主动显示或者隐藏其中的某些层级.而要实现这种UI的分层显示,一种自然的方式便是采用Camera的CullingMask.
两个系统单独来看好像都没有什么问题,但是结合起来使用却容易出现岔子~

原因

原因在于NGUI的Anchor系统并不能很好的支持Camera CullingMask的切换,我们简单来看一段NGUI实现Anchor的代码片段:

public void ResetAnchors ()
{mAnchorsCached = true;leftAnchor.rect     = (leftAnchor.target)   ? leftAnchor.target.GetComponent<UIRect>()   : null;bottomAnchor.rect   = (bottomAnchor.target) ? bottomAnchor.target.GetComponent<UIRect>() : null;rightAnchor.rect    = (rightAnchor.target)  ? rightAnchor.target.GetComponent<UIRect>()  : null;topAnchor.rect      = (topAnchor.target)    ? topAnchor.target.GetComponent<UIRect>()    : null;mCam = NGUITools.FindCameraForLayer(cachedGameObject.layer);FindCameraFor(leftAnchor);FindCameraFor(bottomAnchor);FindCameraFor(rightAnchor);FindCameraFor(topAnchor);mUpdateAnchors = true;
}

代码的大意便是重置一些Anchor相关的数据,其中重要的有两处:
第一个是 mAnchorsCached,他是缓存标记,用以标记Anchor数据是否已经重置;
第二个则是 NGUITools.FindCameraForLayer ,该接口会返回CullingMask包含指定layer的Camera对象.
一般而言,对于Camera CullingMask不会变动的情况,ResetAnchors的实现是没有问题的,但是正如上面所说,如果我们通过改变CullingMask来实现UI分层显示的话,某些被隐藏层级的UI可能会因为查找不到Camera而导致Anchor出错,而此时缓存标记又已设置,后面的逻辑便再不会主动重置Anchor数据,导致定位出错~

方法

解决方法可能有以下一些:
一是避免使用NGUI的Anchor系统,转而自己实现UI的定位,一般来讲并不推荐.
二是改造NGUI Anchor系统,以使其支持Camera的CullingMask变动,譬如实现某种CullingMask的变动通知机制,然后主动重置更新相应的Anchor~
而对于一些全屏性质的UI(需要通过整个屏幕来定位的UI),则有一个比较简单的改动方法,原理则是实现一种特定的UIRect,使其一直保持全屏大小,即便找不到对应layer的Camera也是如此,而UI则根据这个定制的UIRect来进行定位.
一个简单的参考实现大概是这个样子:

// desc UIScreenRect is for handling problem NGUI anchor system does not fit Camera culling mask changes
// maintainer hugoyuusing UnityEngine;public class UIScreenRect : UIRect
{Vector3[] m_invalidWorldCorners = new Vector3[] { Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero };public override float alpha { get{return 0;}set{Debug.LogWarning("[UIScreenRect]Do not support set UIScreenRect's alpha");}}public override float CalculateFinalAlpha(int frameID){return 0;}public override Vector3[] localCorners { get{Vector3[] corners = worldCorners;Transform wt = cachedTransform;for (int i = 0; i < 4; ++i){corners[i] = wt.InverseTransformPoint(corners[i]);}return corners;}}public override Vector3[] worldCorners { get{var anchorCam = GetAnchorCamera();if (anchorCam != null){return anchorCam.GetWorldCorners(cameraRayDistance);}else{return m_invalidWorldCorners;}}}protected override void OnAnchor(){}protected override void OnStart(){}public override void SetRect(float x, float y, float width, float height){Debug.LogWarning("[UIScreenRect]Do not support set UIScreenRect's rect");}public override bool canBeAnchored{get{return false;}}public override Vector3[] GetSides(Transform relativeTo){GetAnchorCamera();return base.GetSides(relativeTo);}public Camera GetAnchorCamera(){if (!anchorCamera){// when anchor camera is missing, we set to first UICameraif (UICamera.list.size > 0){mCam = UICamera.list.buffer[0].cachedCamera;}}if (!mCam){Debug.LogWarning("[UIScreenRect]Error to get anchor camera");}return mCam;}}

OK,下次再见吧~

这篇关于NGUI AnchorPoint与Camera CullingMask的结合之痛的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/898262

相关文章

Go 语言中Select与for结合使用break

func test(){i := 0for {select {case <-time.After(time.Second * time.Duration(2)):i++if i == 5{fmt.Println("break now")break }fmt.Println("inside the select: ")}fmt.Println("inside the for: ")}} 执行后

4-4.Andorid Camera 之简化编码模板(获取摄像头 ID、选择最优预览尺寸)

一、Camera 简化思路 在 Camera 的开发中,其实我们通常只关注打开相机、图像预览和关闭相机,其他的步骤我们不应该花费太多的精力 为此,应该提供一个工具类,它有处理相机的一些基本工具方法,包括获取摄像头 ID、选择最优预览尺寸以及打印相机参数信息 二、Camera 工具类 CameraIdResult.java public class CameraIdResult {

Jenkins--pipeline认识及与RF文件的结合应用

什么是pipeline? Pipeline,就是可运行在Jenkins上的工作流框架,将原本独立运行的单个或多个节点任务连接起来,实现单个任务难以完成的复杂流程编排与可视化。 为什么要使用pipeline? 1.流程可视化显示 2.可自定义流程任务 3.所有步骤代码化实现 如何使用pipeline 首先需要安装pipeline插件: 流水线有声明式和脚本式的流水线语法 流水线结构介绍 Node:

结合Python与GUI实现比赛预测与游戏数据分析

在现代软件开发中,用户界面设计和数据处理紧密结合,以提升用户体验和功能性。本篇博客将基于Python代码和相关数据分析进行讨论,尤其是如何通过PyQt5等图形界面库实现交互式功能。同时,我们将探讨如何通过嵌入式预测模型为用户提供赛果预测服务。 本文的主要内容包括: 基于PyQt5的图形用户界面设计。结合数据进行比赛预测。文件处理和数据分析流程。 1. PyQt5 图形用户界面设计

第二十一章 rust与动静态库的结合使用

注意 本系列文章已升级、转移至我的自建站点中,本章原文为:rust与动静态库的结合使用 目录 注意一、前言二、库生成三、库使用四、总结 一、前言 rust中多了很多类型的库,比如前面章节中我们提到基本的bin与lib这两种crate类型库。 如果你在命令行执行下列语句: rustc --help 那么你将能找到这样的内容: --crate-type [bin|li

王立平-NGUI

NGUI: UI插件 UI : 人机交互界面 UI大部分是2D 目前就总结了这些,后续会补充

“设计模式双剑合璧:工厂模式与策略模式在支付系统中的完美结合”

工厂模式(Factory Pattern)和策略模式(Strategy Pattern)都是常见的设计模式,但它们解决的问题和应用场景不同。下面是它们的区别: 1. 目的不同: 工厂模式(Factory Pattern): 工厂模式的主要目的是创建对象。它通过定义一个创建对象的接口,让子类决定实例化哪一个具体类,从而将对象创建的逻辑与使用的代码分离。 工厂模式可以分为简单工厂、工厂方法和抽象

Windows电脑本地安装HFS文件共享服务结合内网穿透搭建低成本NAS

文章目录 前言1.软件下载安装1.1 设置HFS访客1.2 虚拟文件系统 2. 使用cpolar建立一条内网穿透数据隧道2.1 保留隧道2.2 隧道名称2.3 创建二级子域名访问本地hfs 总结 前言 本文主要介绍如何在Windows系统电脑使用HFS并结合cpolar内网穿透工具搭建低成本NAS,并实现使用公网地址远程访问管理本地局域网电脑存储的文件。 云存储作为一个新概念

Spring回顾之五 —— 测试,JUnit与SpringTest的完美结合

没有测试的程序,是不完整的,每一个从事写程序的人员,都应该坚持做单元测试,通过单元测试可以验证程序基本功能的有效性,从而保证整个系统的质量,功在一时,利在千秋。这里我们将尝试使用Junit和SpringTest,在之前的系统里添加测试功能。 第一步:JUnit与SpringTest的引入     JUnit故名知意,是一个专门为Java语言提供单元测试的框架。平时的开发过程中,单元

Windows系统使用小皮面板搭建Kodcloud结合内网穿透体验私有云盘

文章目录 1.前言2. Kodcloud网站搭建2.1. Kodcloud下载和安装2.2 Kodcloud网页测试 3. cpolar内网穿透的安装和注册4. 本地网页发布4.1 Cpolar云端设置4.2 Cpolar本地设置 5. 公网访问测试6.结语 1.前言 本文主要为大家介绍一款国人自研的在线Web文件管理器可道云,能够支持在线管理图片、播放音乐视频、编辑和查看文件