管理您的 Cookie 设置。您可以在下方启用或禁用不同种类的 Cookie。详情请查看我们的隐私政策

为 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 中,打包过程足够快,因此可以将浏览器中的最终应用程序用作预览。

每当您重新打包时,浏览器页面会重新加载。查看 Views > Preferences 以便禁用“强制整页重载”,以实现更快速的实时重载循环。

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

多场景 

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

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

预制件 

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

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

导入资产 

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

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

优化资产 

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

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

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

目录 

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

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

动画 

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

关键帧编辑和“自定义事件”关键帧受到支持,但轨道混合尚未实现。

物理 

刚体通过 physx 组件类型创建。可以通过 Debug > Simulate Physics (Shift + 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', this.myName, this.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', this.myName, this.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.setDiffuseColor([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 代替,这些会创建有作用域的变量。