说实话,很多刚接触Unity的新手在UI这一块都会踩坑。现在的Unity版本(尤其是2018+)原生有了UGUI,功能非常强大,社区教程也多。但如果你是在维护老项目,或者在教程里偶然看到了“NGUI”这三个字,千万别慌,也别急着关掉页面——因为NGUI曾经统治了移动端UI开发好几年,它的很多设计思想(比如Atlas图集打包、字体渲染优化)依然值得参考,而且它的逻辑其实比现在的UGUI更“物理”、更直观。
今天这篇教程,我不打算给你堆砌枯燥的定义,咱们直接动手,像搭积木一样,把NGUI从导入到第一个可运行的UI界面完整走一遍。我会尽量把原理讲得透彻,哪怕你是个完全的小白,也能跟着把界面做出来。
一、 为什么要聊NGUI?先搞清它在哪儿
首先,我得跟你交个底:NGUI目前不再活跃更新(作者Tasharen停止了对它的长期支持),Unity官方的推荐方案早已是UGUI。但是,NGUI的逻辑非常纯粹。它把UI当成3D物体来对待,每一个按钮都是一个GameObject,这反而让新手更容易理解“坐标”、“层级”、“父子关系”这些核心概念。
如果你是在做一个非常老的移动端项目(比如早期的Cocos转Unity,或者2015年之前的项目),你大概率会遇到NGUI。所以,学会它,能帮你迅速读懂那些老旧的代码和工程结构。
注意:本教程基于NGUI 3.x版本(最常见的稳定版),在Unity 5.x到Unity 2020 LTS版本中均可使用,但需要注意部分API的差异。
二、 导入NGUI插件:别只拖进去就完事
很多新手导插件的步骤是:打开Asset Store,搜索NGUI,点“导入”。停!这一步通常是不够的。如果你直接点导入,你可能会发现NGUI的图标出现在菜单里,但界面是空的,或者报错。
1. 正确的导入姿势
首先,你需要从Unity Asset Store下载NGUI(现在Asset Store里通常叫“NGUI: Next-Gen UI kit”)。下载后,双击.unitypackage文件,Unity会弹出导入窗口。
关键点来了:在导入窗口中,不要只点“Import”。请务必检查以下两个文件夹是否被选中:
Scripts:这是NGUI的核心代码,必须有。Plugins:包含一些跨平台的原生代码。
如果Scripts文件夹里有遗漏(比如UIWidget.cs等核心脚本不见了),UI系统将无法工作。
2. 编译确认
导入完成后,看Unity底部的Console窗口。如果是绿色的,说明编译成功。如果看到红色报错,比如“UnityNGUI namespace not found”,通常是因为你的项目路径包含中文字符,或者NGUI的脚本文件权限有问题。建议把项目移到纯英文路径下重新导入。
3. 打开NGUI界面
在Unity菜单栏,你会看到一个新的菜单项:NGUI(如果没看到,可能是插件没导入成功,或者你的Unity版本太新不兼容)。
点击NGUI -> Open,此时会弹出一个NGUI的专用面板。这个面板就像NGUI的“工作台”,所有的工具都在这里。
三、 理解NGUI的核心:Atlas(图集)
在开始做按钮之前,我必须让你理解NGUI最核心的一个概念:Atlas(图集)。
在3D游戏中,每张贴图(Texture)都是一次Draw Call(绘制调用)。如果你做一个UI,有100个图标,每个图标一张图,那你的游戏每帧就要画100次,手机会卡成PPT。
NGUI的做法是:把所有UI用到的图片,拼成一张大的大图,这就是Atlas。这样做,一次Draw Call就能画出整个界面,性能极高。
1. 创建你的第一个Atlas
想象一下,你手头有一组UI资源:一个背景图、一个按钮正常状态、一个按钮按下状态、一个血条进度条。
步骤如下:
- 在Project面板中,新建一个文件夹,叫
Assets/UI/Resources(NGUI默认从Resources加载图集)。 - 把你的所有UI图片(PNG格式,不带Alpha通道的边缘最好)拖进这个文件夹。
- 选中这些图片,在Inspector面板底部,你会看到一个按钮:Create Atlas。
- 点击它,Unity会弹出一个窗口,让你选择Atlas的名称。输入
MyFirstAtlas,确认。
此时,你会发现Project面板里多了一个名为MyFirstAtlas的文件夹,里面有一个MyFirstAtlas.png和MyFirstAtlas.atlas文件。
这里有个坑:Create Atlas按钮只有在选中多个图片时才会亮起。如果你只选中一张图,它也会工作,但Atlas的主要优势在多图时体现。
2. 字体也要做Atlas
NGUI的文本渲染和UGUI不一样。UGUI用的是字体文件(.ttf),而NGUI通常推荐你用BMFont(位图字体)。
为什么?因为BMFont性能更好,而且支持中文、特殊符号。NGUI自带了一个工具叫BMFont。
操作:
- 点击菜单
NGUI->Open Font Creator。 - 在Font Creator窗口里,选择你喜欢的字体(比如Arial,或者中文字体)。
- 设置字体大小(比如24px)。
- 在“Character Set”里,你可以选择“All”或者手动输入一些字符(比如“1234567890”)。
- 点击Create按钮,NGUI会自动生成一个字体图集。
这个生成的字体图集,也需要像图片一样,放进一个文件夹,然后右键选择Create Atlas,生成一个字体Atlas。这样,你的NGUI文本就能正确显示了。
四、 构建第一个UI:从零开始制作一个“设置面板”
好,理论够了,咱们动手做一个小功能:点击按钮,弹出一个设置面板。这个面板里有一个关闭按钮。
第一步:创建UI Root
在NGUI里,所有的UI元素都必须在一个UI Root之下。UI Root是一个特殊的GameObject,它负责管理整个UI的缩放、对齐方式。
- 在Hierarchy面板右键 ->
NGUI->Create New UI。 - 这会创建一个名为
UI Root的物体。你会看到Inspector里有一个UI Root (2D)组件。 - 重点设置:
Custom Region:建议勾选,这样你可以手动控制UI在屏幕上的显示区域,避免被裁剪。Scaling Style:选择FixedSize on Mobile。这个选项的意思是,无论屏幕多大,UI元素的大小保持不变(以像素为单位)。对于新手来说,这是最直观的模式,不用去算缩放比例。
第二步:添加背景(Panel)
- 右键点击
UI Root->NGUI->Create Empty。这创建了一个名为Panel的物体。 - 在Inspector里,你会看到
Panel组件。 - 给这个Panel添加一个Atlas Material。如果没有,点击
Choose,选择你之前创建的MyFirstAtlas。 - 调整Panel的位置和大小,让它覆盖整个屏幕。你可以直接在Scene视图里拖拽它的四个角,或者在Inspector里设置:
X: 0,Y: 0Width: 960 (假设你的设计分辨率是960x640),Height: 640
- 关键:确保Panel的
Depth(深度)值是0。深度值越小,越靠底层。
第三步:添加一个按钮
- 右键点击
UI Root->NGUI->Create->Button。 - 这会创建一个名为
Button的物体,它是Panel的子物体。 - 调整按钮样式:
- 在Inspector里,找到
Button组件。 Atlas:选择你的MyFirstAtlas。Sprite:选择按钮的背景图片(比如一个圆角矩形的图)。Normal:正常状态的颜色,设为白色(255,255,255,255)。Hover:鼠标悬停状态的颜色。Pressed:点击状态的颜色。Disabled:禁用状态的颜色。
- 在Inspector里,找到
- 设置按钮文字:
- 在Hierarchy里,选中按钮下的
Label子物体。 - 在Inspector里,设置
Text为“设置”。 - 调整
Font为你的字体Atlas。 - 调整大小和位置,让文字居中。
- 在Hierarchy里,选中按钮下的
第四步:让按钮有交互(脚本)
NGUI的按钮自带了点击事件,但我们通常需要更灵活的控制。NGUI推荐使用UIButton组件,它已经内置了简单的点击响应。
选中刚才创建的
Button物体。在Inspector里,确保
UIButton组件存在(通常创建Button时自动添加)。添加点击响应:
- 方案A(简单):在
UIButton组件的OnClick列表里,点击+号。 - 拖拽一个Game Object(比如你自己新建的一个空物体
Manager)进去。 - 在下拉菜单里选择
Manager->OnClickButton。 - 这意味着,当按钮被点击时,会调用
Manager脚本里的OnClickButton方法。
方案B(更灵活,推荐):
- 创建一个新脚本
UISettings.cs:
using UnityEngine; public class UISettings : MonoBehaviour { // 这个方法来响应按钮点击 public void OnSettingsButtonClick() { Debug.Log("设置按钮被点击了!"); // 这里可以打开设置面板,或者播放音效 } }- 把这个脚本挂到一个空物体上,比如叫
UIManager。 - 回到Unity编辑器,选中
Button物体。 - 在
UIButton组件的OnClick列表里,拖拽UIManager物体。 - 选择方法:
UIManager->UISettings->OnClickSettingsButton。
注意:NGUI的按钮点击需要射线检测,确保
Button物体上有Collider组件(通常是Box Collider)。NGUI的UIButton组件会自动添加正确的Collider。- 方案A(简单):在
第五步:创建一个“设置面板”并隐藏/显示
现在,咱们让点击按钮后,弹出一个设置面板。
创建面板:
- 右键点击
UI Root->NGUI->Create->Panel。 - 命名为
SettingsPanel。 - 给它添加一个背景Sprite(比如一个半透明的黑色方块,或者一个精致的UI框)。
- 调整它的位置,比如让它从屏幕右侧滑入,或者居中显示。
- 关键:在
SettingsPanel的Panel组件里,把Visible选项取消勾选(或者在Inspector里把alpha设为0,或者直接用NGUI提供的UIPanel的isVisible属性)。
- 右键点击
添加关闭按钮:
- 在
SettingsPanel内部,创建一个按钮,命名为CloseButton。 - 同样给它添加
UIButton组件,并绑定一个方法OnClickClose。
- 在
编写面板控制脚本:
using UnityEngine; public class SettingsPanelController : MonoBehaviour { public GameObject settingsPanel; // 拖拽SettingsPanel物体 public GameObject closeButton; // 拖拽CloseButton物体 // 初始化时隐藏面板 void Start() { if (settingsPanel != null) { settingsPanel.SetActive(false); // 如果Unity版本较老,用NGUITools.SetActive } } // 打开面板 public void OpenPanel() { if (settingsPanel != null) { settingsPanel.SetActive(true); } } // 关闭面板 public void ClosePanel() { if (settingsPanel != null) { settingsPanel.SetActive(false); } } }注意:NGUI对SetActive的支持可能不如UGUI那么直接,因为NGUI有自己的显隐管理。更稳妥的方式是使用NGUI提供的
NGUITools.SetActive:NGUITools.SetActive(settingsPanel, true); // 显示 NGUITools.SetActive(settingsPanel, false); // 隐藏同时,要确保
Panel组件的isActive属性也被正确管理。关联脚本:
- 把
SettingsPanelController脚本挂到UIManager物体上。 - 把
SettingsPanel和CloseButton拖拽到Inspector里的对应槽位。 - 回到之前的
UISettings脚本,修改OnClickSettingsButtonClick方法:
public void OnClickSettingsButton() { // 假设UIManager上有SettingsPanelController组件 SettingsPanelController panelCtrl = GameObject.Find("UIManager").GetComponent<SettingsPanelController>(); if (panelCtrl != null) { panelCtrl.OpenPanel(); } }- 在
CloseButton的UIButton组件里,添加点击事件,调用panelCtrl.ClosePanel()。
- 把
五、 常见坑与解决方案
1. 按钮点击无效
现象:鼠标移上去有Hover效果,但点击没反应。 原因:
- 没有
Collider组件。NGUI的UIButton会自动添加,但如果你手动删除了,就会失效。 Physics2D或Physics的射线层设置问题。确保UI Root所在的层(Layer)被射线检测包含。- 在3D模式下,可能点击到了后面的3D物体。确保
UI Root的Depth足够高,并且没有3D物体遮挡。
2. 文字显示为空白或乱码
原因:
- 字体Atlas没有正确创建。确认字体图片已经打进Atlas。
- 文字颜色是白色,背景也是白色,看不见。
- 字体大小不对。调整Label的
Point Size。
3. UI被裁剪
原因:
UI Root的Custom Region没有正确设置。如果启用了Custom Region,确保Panel的边界没有超出这个区域。- 相机裁剪问题。检查Main Camera的
Near Clip Plane和Far Clip Plane,确保UI在裁剪范围内。
4. 性能问题
原因:
- 没有使用Atlas。每个独立的Sprite都会增加Draw Call。
- 使用了过多的半透明叠加。半透明渲染需要额外的排序和混合开销。
六、 总结与进阶建议
通过上面的步骤,你已经成功创建了一个带有按钮和可弹出面板的NGUI界面。虽然这看起来简单,但它涵盖了NGUI开发的完整流程:导入 -> 创建Atlas -> 搭建UI Root -> 创建元素 -> 绑定脚本 -> 处理交互。
给新手的建议:
- 多看Demo:NGUI插件包里通常有
Demo场景,里面展示了各种UI效果(滑动列表、动画、输入框等)。这是最好的学习资料。 - 理解坐标系统:NGUI使用局部坐标,父物体的移动会影响所有子物体。善用
Anchor(锚点)系统,比如把按钮固定在屏幕右下角。 - 不要混用UGUI和NGUI:虽然技术上可以共存,但这会导致坐标系统混乱,调试极其痛苦。选择一个,深入学。
最后,记住NGUI虽然老,但它的设计哲学——性能优先、图集管理、显式控制——在任何UI系统中都是通用的。学会了NGUI,再去看UGUI,你会发现很多概念是相通的,只是UGUI用更高效的方式封装了这些功能。
希望这篇教程能帮你跨过NGUI的第一道门槛。如果在操作中遇到具体的报错,欢迎随时记录错误信息,我们再深入探讨。祝你UI开发顺利!
