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

相关文章

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

使用Python自动化生成PPT并结合LLM生成内容的代码解析

《使用Python自动化生成PPT并结合LLM生成内容的代码解析》PowerPoint是常用的文档工具,但手动设计和排版耗时耗力,本文将展示如何通过Python自动化提取PPT样式并生成新PPT,同时... 目录核心代码解析1. 提取 PPT 样式到 jsON关键步骤:代码片段:2. 应用 JSON 样式到

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换功能

《SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能》:本文主要介绍SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能,本文分步骤给大家介绍的... 目录原理解析1. mysql主从复制(Master-Slave Replication)2. 读写分离3.

Python结合Flask框架构建一个简易的远程控制系统

《Python结合Flask框架构建一个简易的远程控制系统》这篇文章主要为大家详细介绍了如何使用Python与Flask框架构建一个简易的远程控制系统,能够远程执行操作命令(如关机、重启、锁屏等),还... 目录1.概述2.功能使用系统命令执行实时屏幕监控3. BUG修复过程1. Authorization

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

Python结合requests和Cheerio处理网页内容的操作步骤

《Python结合requests和Cheerio处理网页内容的操作步骤》Python因其简洁明了的语法和强大的库支持,成为了编写爬虫程序的首选语言之一,requests库是Python中用于发送HT... 目录一、前言二、环境搭建三、requests库的基本使用四、Cheerio库的基本使用五、结合req

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2