网格可视化脚本程序员指南
转到 视觉脚本概述文章
限制
- 只有一部分 Unity 功能公开给视觉脚本。
- 具有非简单类型的变量和属性(包括对象引用)不会自动共享。 请参阅 下面的共享和网络 ,详细了解这一点。
Hello World
可以创建的最简单的视觉脚本就是只打开一个消息框:
这就是网格中的外观:
测试脚本
在将场景上传到网格之前,可以开发和测试视觉脚本,即使是在拆分屏幕模式下 使用播放模式和网格仿真的多个客户端。
编辑器中的可视化脚本诊断
在转换层次结构中选择具有脚本计算机的 GameObject 时,网格会在检查器面板底部显示 网格可视化脚本诊断 面板:
诊断面板会立即反馈任何可能阻止脚本在网格中正常运行的警告或错误。
当前限制: 诊断面板的未来版本也可能提供对视觉脚本使用共享变量和属性的见解,并显示其他诊断和警告。
上传到网格
使用网格上传程序上传包含视觉脚本的场景。 若要打开上传程序,请在 “网格工具包 ”菜单上,选择“ 环境”。
注意:网格上传程序在上传之前验证视觉脚本,并在任何视觉脚本中存在任何验证错误时拒绝上传。 详细诊断输出到 控制台。
共享和网络
共享和本地脚本状态
网格使用 Unity 视觉脚本,该脚本设计为无需网络即可工作。 视觉脚本单独在每个客户端上运行。 但是,共享用户的网格体验;所有用户都体验单个共享场景,该场景在所有客户端上看起来相同。
视觉脚本的执行效果是它如何更改场景的状态。
默认情况下,网格会自动将一个客户端上的视觉脚本执行的场景更改复制到所有其他客户端。 除了在场景中共享的所有内容之外,某些状态在每个客户端上保持独立(换句话说,本地)。
本地更改暂时优先于来自客户端的更改。 示例:如果在本地对对象进行动画处理,则来自其他客户端的更改不会损害本地动画。
存在一些自动更新速率限制。 客户端在仍在进行中时不会发送其他更新;每次往返通过服务器发送一次更新。 在实际情况下,这相当于每秒大约五到六次更新。 这意味着由一个客户端驱动的平滑动画在其他客户端上看起来不会平滑。 最佳做法是在本地执行平滑动画,理想情况下不是通过视觉脚本,而是通过正常的 Unity 动画系统。
保证共享状态的最终一致性(即使客户端的状态可能暂时不同)。
本地状态:
- 自然局部状态 – 声音、UI、呈现。
- 用户控制的本地状态 – 使用 本地脚本范围 组件标记的子场景。
- 技术本地状态 – 不属于场景层次结构的对象(例如呈现器材料、资产)。
共享状态:
- 仅限于视觉脚本变量以及属于场景层次结构的 GameObjects 和场景组件的属性。
- 只能复制简单类型的变量和属性:整数、浮点数、布尔值、字符串、
Color
、/4
3
/Vector2
、、Quaternion
、和。Matrix4x4
Rect
通过网络发送对共享状态的任何更改。 这会增加网络流量,如果谨慎使用,可能会消耗大量带宽。
共享和本地脚本触发器
所有可视脚本流都从响应事件开始。
- 如果事件源自单个客户端(例如,用户单击按钮),则视觉脚本仅在该客户端上执行。
- 如果事件在所有客户端上发生,则视觉脚本在所有客户端上执行(例如计时器事件、共享属性更改、共享变量更新、虚拟形象进入触发器、物理体触摸碰撞器)。
添加节点以检测是否选择了对象时,请务必选择正确的节点。 有两个选项: 网格可交互正文:在本地选择,网格 可交互正文:已选中。 例如,假设你想要有一个按钮,可以单击该按钮来触发传送。 若要让与会者单击该按钮并仅传输自己,请使用 网格交互正文:已选择“本地 ”节点。
若要让与会者单击该按钮并传送体验中的每个人,请使用 网格可交互正文:已选择 节点。 在每个情况下,节点上方的文本会告诉你预期的行为:
如果本地脚本设置共享变量,第二个脚本侦听此变量的更改(使用 On State Changed 触发器;请参阅下文),则第二个脚本将在所有客户端上执行。
网格提供一些特殊的脚本节点:
- 在间隔触发器上,在所有客户端上以同步方式同步触发。
- 当状态更改 触发器的输入更改时(例如共享属性、共享变量、局部变量)。
- 显示对话框 将显示一个消息对话框,其中包含自定义文本,可以选择提供按钮作为响应选项。
网格使某些权衡有利于简单:
- 如果多个客户端尝试更改相同的数据,则最后一个客户端将获胜(而不是使用基于事务的数据更新模型)。
- 为了确保数据一致性,在所有客户端上运行的视觉脚本不得读取和写入共享属性或变量。 如果发生这种情况,它将触发运行时错误并中止脚本流的执行。
最佳做法
视觉脚本明显慢于本机 C# 代码。 此外,网格使用网络和其他集成功能增强视觉脚本,并且看似低开销的视觉脚本操作可能会导致网络流量。 若要了解如何从视觉脚本获得最佳性能,建议查看以下文章:
可视化脚本最佳做法概述
性能的可视化脚本最佳做法
网络可视化脚本最佳做法
调试的可视化脚本最佳做法
安全性
网格保护用户免受威胁方案,例如:
- 泄露的场景内容,例如恶意尝试访问敏感的本地数据。
- 遭到入侵的客户端或传输通道(例如,恶意尝试在其他客户端上读取或写入无法访问的远程数据)。
为此,网格在沙盒中运行视觉脚本(如 Web 浏览器中的 JavaScript)。
在场景启动时,Mesh 使用特选的允许列表来验证视觉脚本,以限制对特定类型的 Unity 组件的访问及其属性的安全子集。
在场景运行时,网格限制对场景的某些部分的访问:
- 本地:通过阻止访问网格内部和其他敏感数据。
- 远程:通过检查场景的作者是否打算修改场景的这一部分。 为此,可以静态分析接收器端的视觉脚本,以便进行潜在的场景写入。
示例:
- 恶意的本地视觉脚本想要为所有头像提供头像。 为此,它会尝试扫描代表头像头像的 GameObjects 的整个场景。 网格会自动筛选扫描结果,以排除头像系统。
- 恶意远程客户端希望通过翻转所有 GameObject 倒置来破坏场景。 为此,它会发送一个属性更新,用于设置场景中每个 GameObject 的垂直比例。 但是,由于接收客户端上没有视觉脚本旨在执行此类操作,因此本地客户端将忽略远程输入。
网格集成
当前限制: 本部分介绍仍在进行中的功能的预览。
通常,与其他组件集成通常是通过更改和侦听组件属性更改来完成的。 例如:
交互项:观察“悬停”和“已选定”属性。
物理交互:观察触发器音量中的体或与碰撞体接触。
虚拟形象:读取头像位置、视图旋转和名称板。 (尚不可用)。
会话状态:列出参与者并读取参与者信息。 (尚不可用)。
云脚本:与可以读取和写入变量和组件属性的云脚本一起运行。 (尚不可用)。
某些组件提供本地操作:
- 音频管理器
- 时间线
- 动画 师
- 呈现:读取和写入材料和着色器属性
物理是专门处理的,因为任何给定物理对象的模拟始终由一个客户端授权完成:其所有者。 若要执行此操作,设置物理属性会触发对应用更改的客户端的自动所有权转移。