我们重视您的隐私。我们使用cookies来提升您在我们网站的体验。使用本网站即表示您同意我们的隐私政策.

为 Unity 开发者准备的 Wonderland Engine

本页面提供从 Unity 到 Wonderland Engine 的脚本映射,并列出构建解决方案的差异。

如果您更喜欢视频格式,可以在我们的 YouTube 频道上查看切换指南:

YouTube Video

脚本编写 

Wonderland Engine 运行在浏览器中,其内置了 JavaScript 运行时。这使其成为 Web 引擎的最佳脚本语言选择,因为无需下载额外的组件。

要创建脚本,请在 Wonderland Editor 的资产浏览器中右键单击,并创建一个新的 JavaScript / TypeScript 组件。该组件配有一个基本模板,帮助您入门。

一个适用于 JS/TS 的 IDE 是 Visual Studio Code

关于 Wonderland Engine 的 API 与 Unity 的不同之处,请参阅代码部分

TypeScript vs JavaScript 

TypeScript 为 JavaScript 增加了静态类型检查,使其更接近 C#,并极大改善了 IDE 的代码补全。我们通常推荐熟悉 Unity 的开发者使用 TypeScript。

Wonderland Engine 会自动为您处理所有 tsconfig.json 的设置,只需从资产浏览器中创建一个 TypeScript 组件即可。

打包 

虽然 Unity 工作流通常使用编辑器内预览,但在 Wonderland Engine 中,最终打包过程非常快(不到 1 秒),这使得浏览器中的最终应用程序可以用作预览。

每当您重新打包时,浏览器页面将重新加载,并且您可以检查 视图 > 偏好设置,使其在每次保存后自动运行。

要部署应用程序,您只需将项目中 deploy 文件夹的内容上传到 Web 服务器。或者,您可以通过可以在 视图 > 插件 中激活的 “Wonderland Cloud Publish” 插件上传。

多个场景 

Wonderland Engine 允许在 多个项目文件(.wlp) 创建的多个场景之间切换。查看切换场景教程获取说明。

您还可以在运行时流式加载场景的一部分。请参考运行时流式加载 .bin 文件教程

预制件 

Wonderland Engine 尚未具备与预制件等效的功能。您可以在场景中设置一个原型,并使用 object.clone() 复制其层次结构及所有组件。

或者,将预制件对象移动到一个单独的场景,以便在运行时使用 engine.loadPrefab(…) 加载并实例化它。

导入资产 

在 Wonderland Engine 中,如果导入了场景文件(通过将其从资产浏览器拖放到场景视图或场景大纲中,或将图像文件拖动到材质的纹理槽中),它就会被链接并监视更改。场景文件中发现的资源将被应用于项目,并可在 “资源” 视图中查看。

在从资产浏览器中导入文件之前,它在项目中是不可用的。“资产浏览器” 可以被视为一个文件浏览器,与您在 Unity 中习惯的不同。

优化资产 

一旦资产被导入,可以进一步优化:

  • 网格可以自动简化以减少顶点数
  • 网格可以均匀缩放
  • 图像会自动压缩
  • 图像可以降级

这些设置可以在 “资源” 视图中找到。

目录 

  • deploy 包含打包的最终结果。
  • static 包含被原样复制到 deploy 的文件。
  • cache 包含缓存的资产编译结果,例如压缩的图像。通常可以安全地删除,但需要时间重新生成。

这些设置可以在 “资源” 视图中找到。

动画 

动画通过 animation 组件类型播放。如果组件附加到目标皮肤的某个骨骼/关节上,可以通过 retarget 复选框重新定位蒙皮动画。

混合、编辑关键帧或关键帧事件尚不支持。

物理 

刚体通过 physx 组件类型创建。可以通过 调试 > 模拟物理 (Alt + S) 在编辑器中模拟场景。

网络 

点对点网络可以通过社区支持的 Wonderland Engine PeerJS Networking 实现。

它使用 WebRTC,在一定规模上可以利用默认的 PeerJS 服务器基础设施。

另外,社区也已集成 Colyseus 用于多用户。

用户界面 

用户界面可以手动设置,通过 cursorcursor-targetcollider 组件。

以下基于 HTML5 Canvas 的 2D 用户界面由社区维护:Lazy Widgets project

术语 

术语UnityWonderland Engine
项目一个项目文件可能多个项目文件共享一个项目根目录
检查器视图属性视图

代码 

以下是一些常见代码模式及其 Wonderland Engine 等效项:

自定义行为 

在 Wonderland Engine 中,我们使用 “Component” 代替 “MonoBehaviour”。要编写一个,只需扩展 Component 类

UnityWonderland Engine (JavaScript)Wonderland Engine (TypeScript)
 1using UnityEngine;
 2using System.Collections;
 3
 4public class MainPlayer : MonoBehaviour
 5{
 6  [field: SerializeField]
 7  public string myName;
 8
 9  string privateName;
10
11  void Start()
12  {
13    Debug.Log("My name is", this.myName, this.privateName);
14  }
15
16  void Update()
17  {
18    Debug.Log("Delta time:", Time.deltaTime);
19  }
20}
 1import {Component, Property} from '@wonderlandengine/api';
 2
 3export class MainPlayer extends Component {
 4  static TypeName = 'main-player';
 5
 6  /* Properties are exposed in the editor */
 7  static Properties = {
 8      myName: Property.string("Alice")
 9  };
10
11  privateName = "Bob";
12
13  start() {
14    console.log("My name is", myName, privateName);
15  }
16
17  update(dt) {
18    console.log("Delta time:", dt);
19  }
20}
 1import {Component} from '@wonderlandengine/api';
 2import {property} from '@wonderlandengine/api/decorators.js';
 3
 4export class MainPlayer extends Component {
 5  static TypeName = 'main-player';
 6
 7  /* Properties are exposed in the editor */
 8  @property.string("Alice")
 9  myName!: string;
10
11  privateName = "Bob";
12
13  start() {
14    console.log("My name is", myName, privateName);
15  }
16
17  update(dt: number) {
18    console.log("Delta time:", dt);
19  }
20}

与 Unity 中一样,某些 UI 元素将为参数生成。

获取游戏对象上的组件 

UnityWonderland Engine
1gameObject.GetComponent<MyComponent>();
1// 首选方式,因为类型可以被推断
2this.object.getComponent(MyComponent);
3
4// 或者:通过类型名
5this.object.getComponent('my-component');

将组件附加到对象 

UnityWonderland Engine
1MyComponent sc = gameObject.AddComponent<MyComponent>();
2sc.property = "set";
1this.object.addComponent(MyComponent, {property: "set"});
2
3// 或者:通过类型名
4this.object.addComponent('my-component', {property: 'set'});
5
6// 或者:推迟激活
7const sc = this.object.addComponent('my-component', {active: false});
8sc.property = 'set';
9sc.active = true;

获取子对象 

UnityWonderland Engine
1
2gameObject.transform.GetChild(0);
1this.object.children[0];

获取父对象 

UnityWonderland Engine
1gameObject.transform.parent
1this.object.parent;

设置材质属性 

设置颜色或纹理等各种材质属性。

UnityWonderland Engine
1var mesh = gameObject.GetComponent<MeshRenderer>();
2mesh.material.SetColor("_Color", Color.green);
1const mesh = this.object.getComponent(MeshComponent);
2mesh.material.diffuseColor = [0.0, 1.0, 0.0, 1.0];

数学运算 

JavaScript 不支持 运算符重载,这意味着我们对数学代码采取不同的方法。

在许多情况下,可以完全避免编写数学代码,因为 Wonderland Engine 的 Object3D API 包含许多用于操作变换的函数,这些函数在 WebAssembly 中高效实现:

1/* 在多个轴上平移对象。为了避免产生多余的向量垃圾,使用临时向量成员或在模块范围内使用常量。 */
2this.object.translateWorld([1, 2, 3]);
3
4/* 绕 Y 轴旋转对象。 */
5const AxisY = [0, 1, 0];
6this.object.rotateAxisAngleDegLocal(AxisY, 25);

垃圾回收 

JavaScript 是一种垃圾回收语言,这可能导致由于自动垃圾回收而产生无法预测的中断。最佳实践是避免在堆上增加内存,例如列表/向量或对象,因为这些内存不是可以轻松回收的。

最佳实践是创建临时向量/四元数,无论是在构造函数中还是在自定义组件的主体中,并反复使用;或者如果使用得当,放在类的模块范围内。常量向量如 [0, 1, 0] 最好在模块范围内声明为 const AxisY = [0, 1, 0]

数学库 

我们推荐使用 glMatrix,它是一个针对 JavaScript/TypeScript 性能和垃圾回收优化的数学库。它已经随我们的默认模板和默认组件安装,因此您很可能不需要自己安装。

与返回新分配的向量不同,glMatrix 的计算向量或四元数的函数会期望第一个参数作为结果写入的地方。而返回基元的函数会正常返回结果。

可以在这里找到 glMatrix 数学库的完整文档

UnityWonderland Engine
1var v = new Vector3(1, 2, 3);
2v.Set(3, 2, 1);
1const v = vec3.fromValues(1, 2, 3);
2vec3.set(v, 3, 2, 1);
1var a = new Vector3(1, 2, 3);
2var b = new Vector3(1, 2, 3);
3
4var v = a + b;
5var a = a * b;
6var a = 2.0*a;
1import {vec3} from 'gl-matrix';
2
3const a = vec3.fromValues(1, 2, 3);
4const b = vec3.fromValues(1, 2, 3);
5
6const v = vec3.add(vec3.create(), a, b);
7vec3.mul(a, a, b);
8vec3.scale(a, a, 2.0);

JavaScript vs C# 

从 C# 转到 JavaScript 的一些明显差异包括:

  • 始终在访问成员变量时加上 this.
  • var 创建一个“全局变量”,不限制在当前作用域内。最佳实践是避免使用它,而用 letconst 代替,这些会创建有作用域的变量。