第 24 课
菜单页面制作
上一课已经让介绍、导航、设置三个按钮能够切换页面。本课继续制作三个页面的实际内容。介绍页和导航页的信息固定,适合直接使用设计好的图片;设置页需要响应你的操作,因此使用真正的 Toggle(开关)、Dropdown(下拉列表)、Slider(滑动条)和 Button(按钮)。学习过程中不仅要把界面摆出来,还要检查对象层级、图片透明度、页面引用、控件状态和可交互范围。
完成介绍、导航与设置三张菜单页面
把菜单的内容区域补充完整:用两张图片呈现项目介绍与展馆导航,再用开关、下拉列表、滑动条和按钮组成设置页面。你会学会判断什么时候适合使用整张图片,什么时候必须保留真正可操作的界面控件。

完成效果:SettingsPage 中的控件按功能分组,左侧负责声音与风格,右侧负责画面调节,底部提供重置按钮。
点击图片可以查看完整截图学完你将能够
学习目标
- 说清 IntroductionPage、NavigationPage 和 SettingsPage 各自承担的内容职责。
- 把 IntroImage 与 BlueprintImage 导入为 Sprite(2D and UI),并理解 Max Size 的作用。
- 正确处理页面激活状态、层级顺序、Image 颜色透明度、原始尺寸和锚点。
- 检查 NavbarController 中三组目标页面引用,并完成页面切换测试。
- 理解整张图片页面与真实界面控件的适用范围。
- 使用可复用的控件组制作背景音乐和语音解说开关。
- 配置风格下拉列表及其选项和状态颜色。
- 使用 MinMaxSlider 预制体完成色温、曝光和饱和度三组调节界面。
- 制作带圆角拉伸和状态反馈的重置按钮。
- 完成三页连续切换、控件反馈和常见问题排查。
开始操作前
准备工作
- 打开主场景,确认 MenuUI 下已经存在 ContentPanel、NavigationBar 和 DragHandle。
- 确认 ContentPanel 下已经有 IntroductionPage、NavigationPage 和 SettingsPage。
- 确认 NavbarController 能够在三个导航按钮之间切换页面。
- 准备 IntroImage.png、BlueprintImage.png 和 CustomToggle.unitypackage。
- 确认项目已经导入 XR Interaction Toolkit 的入门资源,可以找到 Dropdown 与 MinMaxSlider 预制体。预制体是预先配置好并能重复使用的对象模板。
- 退出运行状态并保存场景,再开始修改界面对象。
本课学习路线
按照学习模块逐步完成
每个模块都包含理解、跟随操作和独立实践。页面形式由内容是否需要交互决定
先分清三张页面的职责
三个页面都显示在 ContentPanel 的同一块区域,但它们的内容性质不同。先判断你只是阅读信息,还是需要操作控件,才能选择合适的制作方式。三张页面的内容选择
判断标准不是制作速度,而是页面中的信息是否需要随操作改变。
左右滑动表格,可查看完整内容
| 页面对象 | 主要内容 | 制作方式 | 选择原因 |
|---|---|---|---|
| IntroductionPage | 项目名称、简介与展示信息 | 整张 IntroImage 图片 | 版式固定,主要用于阅读 |
| NavigationPage | 展馆平面图与区域说明 | 整张 BlueprintImage 图片 | 地图标记固定,需要保持完整布局 |
| SettingsPage | 声音、风格和画面设置 | 真实界面控件 | 开关、选择、拖动和重置都要接收输入 |
观察重点:三个页面都是 ContentPanel 的直接子对象;介绍页和导航页使用图片,设置页保留可以接收输入的真实控件。
手机上可左右滑动;点击图片可以查看完整图整张图片和真实控件有什么区别
整张图片能完整保留设计软件中的字体、间距和装饰效果,适合内容固定的介绍页和地图页。它的局限是文字不能单独修改,也不能让其中某个区域直接响应按钮或滑动操作。
真实控件由多个界面对象组成。制作步骤更多,但每个控件都有明确的交互状态,可以在后面的功能课中把输入结果连接到声音和画面参数。
为三张页面选择正确形式
对照 ContentPanel 下的三个页面对象,说明每张页面为什么使用图片或真实控件。
- 指出两个只承担信息展示的页面。
- 指出必须接收你输入的页面。
- 确认三个页面都位于 ContentPanel 下,而不是放进 NavigationBar。
先让图片能被界面组件识别
导入两张页面图片并整理页面层级
普通纹理不能直接作为 Image 的 Source Image。导入后要把 Texture Type 改为 Sprite(2D and UI),再检查压缩上限和三个页面的层级。下载介绍页与导航页图片
压缩包包含 IntroImage.png 和 BlueprintImage.png,可导入项目中的 _Textures 文件夹。
- IntroImage.png:1280 × 860,用于 IntroductionPage。
- BlueprintImage.png:880 × 495,用于 NavigationPage。
让两张图片成为界面精灵
- 01
把 IntroImage.png 与 BlueprintImage.png 拖入项目面板的 _Textures 文件夹。
- 02
选择 IntroImage,把 Texture Type 设为 Sprite(2D and UI),Max Size 设为 2048,关闭 Mipmap,然后点击 Apply。
- 03
选择 BlueprintImage,把 Texture Type 设为 Sprite(2D and UI),Max Size 设为 1024,关闭 Mipmap,然后点击 Apply。
- 04
回到层级面板,确认 ContentPanel 的三个直接子对象依次为 IntroductionPage、NavigationPage、SettingsPage。
- 05
暂时只激活正在制作的页面,避免多个页面叠在同一区域影响观察。
Max Size 不是把图片放大的命令
Max Size 表示导入后允许保留的最大边长。图片某一边超过这个上限时,Unity 会缩小导入纹理;图片本来就小于上限时,不会被强行放大。
IntroImage 的最长边是 1280,小于 2048;BlueprintImage 的最长边是 880,小于 1024。因此两张图都能保留原始尺寸。
Mipmap 会为纹理生成多级缩小版本,常用于远处三维表面的纹理。本课两张图片直接显示在菜单界面上,为保持文字和细线清楚,可以关闭 Mipmap。

IntroImage 用于呈现固定的项目介绍版式,导入时应保持文字和装饰图形清晰。
点击图片可以查看完整截图
BlueprintImage 用于呈现展馆平面图,设置尺寸时要避免把地图拉伸变形。
点击图片可以查看完整截图检查图片导入与页面层级
逐一选择两张图片和三个页面对象,完成一次可复现的导入检查。
- 确认两张图片的 Texture Type 都是 Sprite(2D and UI)。
- 确认两张图片的 Max Size 不会压低当前原始尺寸。
- 确认三个页面都是 ContentPanel 的直接子对象。
- 确认当前只激活一张页面用于编辑。
正确显示图片要同时检查精灵、颜色和矩形范围
完成 IntroductionPage
把 IntroImage 赋给 IntroductionPage 只是第一步。Image 的颜色会与原图相乘,透明度决定底层的 ContentPanel 背景能透出多少;Rect Transform 的锚点和尺寸则决定图片占据多大区域。设置介绍页图片
- 01
激活 IntroductionPage,暂时关闭 NavigationPage 和 SettingsPage。
- 02
在 Image 组件的 Source Image 中选择 IntroImage。
- 03
把 Color 的红、绿、蓝通道设为纯白,透明度设为约 100/255。纯白避免给原图染色,适度透明让黑色内容背景参与最终效果。
- 04
点击 Set Native Size,让 Rect Transform 先恢复到图片的原始像素比例。
- 05
把锚点设为四向拉伸,并让页面最终填满 ContentPanel。当前项目关闭 Preserve Aspect,以铺满内容区域为优先。
- 06
观察人物、标志和文字的形状,确认当前拉伸结果仍然清楚可读;如果以后改用不同宽高比的图片,应重新权衡铺满、留白和裁切。

观察重点:图中的叠层是制作过程中的对比现象。最终使用纯白颜色和约 100/255 的透明度,并确保同一时刻只激活当前页面。
点击图片可以查看完整截图图片显示异常与对应检查
按表现寻找原因,可以比反复拖动尺寸更快定位问题。
左右滑动表格,可查看完整内容
| 观察到的现象 | 优先检查 | 正确处理 |
|---|---|---|
| 整张图偏红或偏灰 | Image 的 Color | 改为纯白 |
| 整张图比预期更淡 | Color 的透明度 | 恢复到约 100/255,再结合黑色背景观察 |
| 人物或文字明显变宽 | Rect Transform 比例 | 重新权衡铺满、Preserve Aspect 与边缘留白 |
| 能看到两张页面内容 | 页面激活状态 | 只保留当前页面激活 |
Rect Transform 与锚点分别负责什么
Rect Transform 是界面对象使用的矩形变换组件,它记录位置、宽度、高度和锚点。普通三维对象使用 Transform,而界面元素依靠 Rect Transform 在画布中排列。
锚点表示这个矩形参考父对象的哪些位置。四向拉伸锚点会同时参考父对象的左、右、上、下边界;父对象尺寸变化时,页面会跟随边界变化。锚点只负责矩形如何变化,不会自动保护图片宽高比。
完成并观察介绍页
在场景视图中只显示 IntroductionPage,检查图片颜色、透明度、比例和边界。
- 确认 Source Image 为 IntroImage。
- 确认红、绿、蓝通道为纯白,图片没有额外染色。
- 确认透明度约为 100/255,黑色内容背景能够适度透出。
- 确认标题和正文在填满区域后仍然清楚可读。
- 确认图片位于 ContentPanel 内,不遮挡 NavigationBar。
本课先完成输入界面和可观察反馈
规划 SettingsPage 的结构和功能边界
设置页不是一张静态图片,而是一组可以接收输入的控件。本课让它们具备清楚的布局和自身状态反馈;声音、风格和画面参数的实际变化将在对应功能课中连接。让 SettingsPage 成为透明的控件容器
- 01
选择 SettingsPage,保持对象本身激活。
- 02
让 Rect Transform 四向拉伸并覆盖 ContentPanel 的内容区域。
- 03
关闭 SettingsPage 上 Image 组件的勾选,让页面根对象不再绘制整块背景。
- 04
不要关闭 SettingsPage 整个对象,否则它下面的所有控件都会一起停止显示和交互。
- 05
在 SettingsPage 下规划六个功能组和一个 ResetButton。六个功能组使用纯深灰色 #1E1E1E 的矩形背景,不添加额外圆角精灵。
设置页对象与本课可观察结果
先确认界面负责收集哪一种输入,再连接实际功能。
左右滑动表格,可查看完整内容
| 对象 | 控件类型 | 本课可观察结果 | 对应功能 |
|---|---|---|---|
| BackgroundMusicControl | Toggle | 开关状态变化 | 背景音乐 |
| VoiceNarrationControl | Toggle | 开关状态变化 | 语音解说 |
| VisualStyleControl | Dropdown | 选中项变化 | 展馆风格 |
| ColorTemperatureControl | Slider | 滑块位置变化 | 色温 |
| ExposureControl | Slider | 滑块位置变化 | 曝光 |
| SaturationControl | Slider | 滑块位置变化 | 饱和度 |
| ResetButton | Button | 按压状态变化 | 恢复默认设置 |
观察重点:本课可以看到开关、选项、拖动和按压反馈;要真正改变声音或画面,还需要让脚本接收控件输出并修改目标系统。
手机上可左右滑动;点击图片可以查看完整图规划设置页一级结构
先写出六个功能组和一个重置按钮的名称。本模块不提前创建空对象,后续将直接制作完整控件组,避免出现同名对象。
- 确认 SettingsPage 对象激活,但它自身的 Image 组件关闭。
- 在笔记中依次写出六个功能组和 ResetButton。
- 为每个名称标注将使用开关、下拉列表、滑动条还是按钮。
- 口头说明本课能看到的反馈与实际功能变化之间的区别。
先完成一个模板,再复制出同类控件
制作标签与两组声音开关
背景音乐和语音解说都是开或关两种状态,适合使用 Toggle。先把第一组的容器、文字和开关调好,再复制整个功能组,可以保持尺寸、间距和界面风格一致。下载自定义开关控件
导入 CustomToggle.unitypackage 后,可以在 CustomToggle 的 Prefabs 文件夹中找到 Boolean Toggle。
- 导入时保留预制体、精灵和依赖资源。
- 把 Boolean Toggle 作为实例拖入对应功能组。
完成 BackgroundMusicControl
- 01
在 SettingsPage 下创建一个 UI Image 容器并命名为 BackgroundMusicControl,当前场景参考尺寸为 263.5 × 41.1。
- 02
清空容器 Image 的 Source Image,把 Color 设为纯深灰色 #1E1E1E,得到与当前页面一致的矩形背景。
- 03
在组内创建 Legacy Text 并命名为 BackgroundMusicLabel,文字设为“背景音乐”。
- 04
把字号设为 25、颜色设为白色,并使用水平居中和垂直居中。
- 05
导入 CustomToggle.unitypackage,把 Boolean Toggle 预制体拖入组内并命名为 BackgroundMusicToggle。
- 06
当前场景中的开关参考尺寸为 70 × 36,初始状态为开启;把它放在文字右侧并确认没有超出组边界。

观察重点:这里只观察 25 号白色文字与双向居中。完成后请使用 BackgroundMusicLabel、VoiceNarrationLabel 等能够表达用途的名称。
点击图片可以查看完整截图
观察重点:使用 Boolean Toggle 预制体实例可以保留开关内部结构和状态效果;完成后将实例命名为 BackgroundMusicToggle 或 VoiceNarrationToggle。
点击图片可以查看完整截图复制并改成 VoiceNarrationControl
- 01
复制整个 BackgroundMusicControl,而不是只复制标签或开关。
- 02
把副本改名为 VoiceNarrationControl,并移动到背景音乐组下方。
- 03
把标签改名为 VoiceNarrationLabel,文字改为“语音解说”。
- 04
把开关实例改名为 VoiceNarrationToggle。
- 05
确认两组尺寸、文字对齐和开关位置一致,同时保留各自独立的 Toggle 组件。
Boolean Toggle 怎样把状态变成可见反馈
Toggle 组件保存一个布尔值,也就是只有开启和关闭两种可能的状态。你点击开关后,Toggle 会改变这个值,并通过 onValueChanged 事件通知与它连接的组件。事件可以理解为“状态变化时发出的一次通知”。
BooleanToggleVisualsController 接收通知后,会把圆形滑块移动到不同位置:开启时横向位置约为 17,关闭时约为 -17。指针悬停时,滑块还会沿前后方向轻微移动,让空间界面中的反馈更明显。
- Toggle 负责保存开或关。
- onValueChanged 负责发出状态变化通知。
- 视觉控制器负责移动滑块和呈现悬停反馈。
- 真正控制音乐或解说,需要再让功能脚本接收同一个状态。
完成两组可独立操作的开关
进入运行状态分别点击两个开关,观察它们是否各自改变状态。
- 确认点击背景音乐开关不会同时改变语音解说开关。
- 确认标签文字完整且没有被开关遮挡。
- 确认两个开关的可点击范围与视觉位置一致。
- 确认退出运行状态后对象命名仍然准确。
Dropdown 用一个控件承载多个互斥选项
制作风格下拉列表
风格只能在多个方案中选择一个,适合使用 Dropdown。下拉列表折叠时只占一行,展开后才显示全部选项,能够节省设置页面空间。完成 VisualStyleControl
- 01
复制一组已有功能组,改名为 VisualStyleControl,并把标签改为 VisualStyleLabel,文字改为“风格”。
- 02
删除组内原有 Toggle,把 XR Interaction Toolkit 入门资源中的 Dropdown 预制体拖入组内。
- 03
把实例改名为 VisualStyleDropdown,当前场景中的参考尺寸为 260 × 60。
- 04
在 Dropdown 组件的 Options 中保留两个选项:“现代简约”和“复古怀旧”。
- 05
检查折叠状态中的标题文字,当前场景使用 35 号字,选项展开后应保持清楚可读。
- 06
把 Normal Color(普通状态颜色)设为蓝色 #0048FF,并检查 Highlighted(悬停)、Pressed(按下)、Selected(选中)和 Disabled(不可用)状态仍然有清楚差异。
- 07
检查背景 Image 的 Type 为 Sliced,Pixels Per Unit Multiplier 为 4,使圆角在拉伸后仍保持自然。

观察重点:Dropdown 是完整预制体,背景使用 Sliced,Pixels Per Unit Multiplier 为 4,并通过状态颜色提示悬停、按下和选中。
点击图片可以查看完整截图Sliced 为什么能保护圆角
Sliced 常被称为九宫格拉伸。它把图片分成四个角、四条边和中心区域。控件尺寸变化时,中心和边可以延展,四个角尽量保持原状,因此不会把圆角拉成长椭圆。
Pixels Per Unit Multiplier 会影响切片边界在界面中的换算比例。数值变化会让边框和圆角看起来更厚或更薄,需要结合当前精灵观察。
展开并检查两个风格选项
进入运行状态打开下拉列表,分别选择两个选项并观察折叠后的显示。
- 确认列表中只有“现代简约”和“复古怀旧”两个有效选项。
- 确认选择后,折叠状态显示当前选项文字。
- 确认指针悬停和按下时都有可辨认的颜色反馈。
- 确认圆角没有因宽度变化而被明显拉扁。
同一套模板承载三种连续数值
制作色温、曝光和饱和度滑动组
色温、曝光和饱和度都不是简单的开或关,而是在一定范围内连续变化,适合使用 Slider。本项目使用 MinMaxSlider 预制体的单值交互外观,并为每组保留独立的数值文字。完成 ColorTemperatureControl
- 01
在 SettingsPage 下创建一个 UI Image 容器并命名为 ColorTemperatureControl,当前场景参考尺寸为 338.4 × 43.64。
- 02
清空容器 Image 的 Source Image,把 Color 设为纯深灰色 #1E1E1E,保持与左侧功能组一致的矩形背景。
- 03
创建 ColorTemperatureLabel,文字设为“色温”,沿用 25 号白色居中标签样式。
- 04
把入门资源中的 MinMaxSlider 预制体拖入组内并命名为 ColorTemperatureSlider。
- 05
当前场景中的滑动控件参考尺寸为 260 × 60,数值范围保持 0 到 1,初始值约为 0.495。
- 06
把滑动控件的 Normal Color(普通状态颜色)设为蓝色 #0048FF,同时保留悬停、按下、选中和不可用状态的差异。
- 07
创建 ColorTemperatureValueText,放在滑动条右侧并使用 15 号字;当前显示文字为 10,用于确认数值区域的版式和可读性。
- 08
确认 On Value Changed(数值变化时触发的事件)目前没有连接实际画面功能,本课只检查拖动和视觉反馈。

观察重点:MinMaxSlider 预制体尺寸为 260 × 60,范围为 0 到 1,初始值约为 0.495;完成后使用 ColorTemperatureSlider、ExposureSlider、SaturationSlider 三个语义名称。
点击图片可以查看完整截图完成 ExposureControl 与 SaturationControl
- 01
复制整个 ColorTemperatureControl,改名为 ExposureControl。
- 02
把标签改名为 ExposureLabel,文字改为“曝光”;把滑动控件和数值文字也改成 Exposure 开头。
- 03
再次复制整个组并改名为 SaturationControl。
- 04
把标签改名为 SaturationLabel,文字准确写成“饱和度”;把子对象统一改成 Saturation 开头。
- 05
确认 ColorTemperatureValueText、ExposureValueText、SaturationValueText 都使用 15 号字并显示 10。这个文字只呈现当前版式;由于 On Value Changed 没有连接更新方法,拖动滑块时文字不会自动变化。
- 06
让三组控件在右侧竖向对齐,并保持相同的标签、滑动条和数值文字间距。
三组滑动控件的语义名称
语义名称能让后面连接脚本时清楚找到每个输入对象。
左右滑动表格,可查看完整内容
| 功能组 | 标签 | 滑动控件 | 数值文字 |
|---|---|---|---|
| ColorTemperatureControl | ColorTemperatureLabel | ColorTemperatureSlider | ColorTemperatureValueText |
| ExposureControl | ExposureLabel | ExposureSlider | ExposureValueText |
| SaturationControl | SaturationLabel | SaturationSlider | SaturationValueText |
逐组拖动并检查独立性
进入运行状态依次拖动色温、曝光和饱和度滑动控件,确认每组都能独立响应。
- 确认拖动一个滑块时,另外两组手柄不会一起移动。
- 确认三个标签文字分别为色温、曝光、饱和度。
- 确认三个数值文字没有与滑动条重叠。
- 确认滑动手柄从最小端到最大端都能保持在轨道范围内。
按钮外观、状态反馈和实际行为是三个层次
制作重置按钮
重置按钮位于页面底部,用来表达“恢复默认设置”这一明确动作。本课先完成它的外观与按压反馈,后面的重置功能再把点击事件连接到各项默认值。配置 ResetButton
- 01
在 SettingsPage 下创建 ResetButton,当前场景参考尺寸为 160 × 55.2,并放在页面底部中央。
- 02
为背景 Image 选择 Circle_60x60_Horizontal 精灵,把 Image Type 设为 Sliced。
- 03
把 Pixels Per Unit Multiplier 设为 4,检查左右圆角没有被横向拉扁。
- 04
在 Button 的 Color Tint 中把 Normal(普通)与 Selected(选中)设为蓝色 #0048FF,并让 Highlighted(悬停)、Pressed(按下)、Disabled(不可用)保持可辨认差异。
- 05
在按钮下创建 ResetButtonText,文字设为“重置”、字号设为 22,居中显示并确保不会拦截按钮操作。
- 06
进入运行状态悬停并按下按钮,确认颜色状态变化;本课不要求点击后立即改动其他控件数值。
重置按钮的三个层次
看到按钮变色,只能证明输入和视觉状态正常。
左右滑动表格,可查看完整内容
| 层次 | 负责内容 | 本课完成标准 |
|---|---|---|
| 外观 | 圆角背景、尺寸、文字 | 重置文字清楚,圆角不变形 |
| 状态反馈 | 普通、悬停、按下、不可用颜色 | 输入时能看到对应变化 |
| 实际行为 | 恢复声音、风格和画面默认值 | 在重置功能课中连接 |
完成按钮状态观察
让指针依次离开、悬停、按下 ResetButton,比较三个状态。
- 确认普通状态使用蓝色背景。
- 确认悬停与按下时有不同的颜色反馈。
- 确认横向拉伸后左右圆角仍然对称。
- 确认“重置”文字始终位于按钮中央。
把知识变成作品
本课练习
请按顺序完成以下任务,并保存自己的学习成果。- 01
不查看表格,画出 MenuUI、ContentPanel、三张页面和 NavigationBar 的层级关系。
- 02
分别说明 IntroImage、BlueprintImage 和 SettingsPage 为什么采用不同的制作方式。
- 03
把任意一张页面图片的透明度调低,观察现象后恢复为约 100/255。
- 04
故意交换 NavigationPage 与 SettingsPage 的目标引用,观察错误后按索引表修复。
- 05
复制一个功能组并重新命名所有子对象,练习保持语义名称和布局一致。
- 06
完整演示三页切换与七个设置控件的视觉反馈。
把本课进度保存下来
登录后可以保存浏览内容、有效学习时间、完成状态和答题参与记录。