背景
平常都是用ts写代码,目前ts转wasm还不成熟。就只能中间转一次
【go方案】:
go转wasm,包比较大,放弃
【rust方案】:(今天的尝试的)
包体积小(已兼容微信小程序!!)。
本文主要是探索,ts转rust的一些实践总结
环境
rustc 1.76.0 (07dca489a 2024-02-04)
包版本:
wasm-bindgen = “=0.2.76” // 这个注意要用=,之前就是这个版本引起不兼容微信小程序
js-sys = “0.3”
打包:
wasm-pack 0.13.1
bun 1.2.8 (这个是为了ts测试用的)
倒水游戏为实验对象
选了一个最简单的倒水游戏逻辑作为实验
因为是核心玩法,所以是不需要cocos环境的
让ai帮忙无缝将ts转rust的几点总结
开始的时候,我还是用平常的ts写法写逻辑,但是很快发现转出来的rust代码和ts差异很大
为了ts能无缝的转rust,记录了以下几点
先给出瓶子为例子的代码
这个是最开始的ts代码
// 瓶子状态
export enum BottleState {
Empty,
Some,
Full,
Close,
}
// 瓶子
export interface IBottle {
bodys: number[]
index: number
state: BottleState
}
这个是为了无缝转rust后的代码
export class Bottle {
private bodys: number[]
private index: number
private state: BottleState
constructor(index: number) {
this.index = index
this.state = BottleState.Empty
this.bodys = []
}
get_index(): number {
return this.index
}
set_index(index: number): void {
this.index = index
}
get_state(): BottleState {
return this.state
}
set_state(state: BottleState): void {
this.state = state
}
get_bodys(): number[] {
return this.bodys
}
set_bodys(bodys: number[]): void {
this.bodys = bodys
}
}
你会发现以下几点差异
- 1、rust函数方法命名都变为了小写加下划线
比如:getBodys() 需要改为 get_bodys()
(好家伙,我好不容易养成了写驼峰习惯了,又要倒退吗,算了还好只是转核心代码,忍了)
-
2、数据结构偏向类
比如:
bottles: IBottle[] = [] // 原先只需抽象的数据
变成了
bottles: Bottle[] = [] // 现在必须是个类 -
3、类属性的访问不行了,因为转wasm后没法直接获取属性,只能全传方法
比如:
原先获取瓶子bottle的bodys,只需要 bottle.bodys
现在
bottle.getBodys() -
4、获取对象需要转换输出,直接输出会导出ts代码和rust转出来的有差异,不能直接用
需要通过JSON.parse(JSON.stringify(bottle))来转换
如:public get_cur_bottle(): Bottle | null { if (this.cur_index == -1) { return null } // return this.bottles[this.cur_index] // 这个wasm在js中没法直接用 return JSON.parse(JSON.stringify(this.bottles[this.cur_index])) } -
5、因为对象经过rust类后转成json对象,所以属性的顺序排序都的按字母顺序来,不然单元测试时用JSON.stringify出来的顺序不一致。如下面的bodys,index,state顺序
export class Bottle { private bodys: number[] private index: number private state: BottleState .... } -
6、微信小程序的兼容,因为微信小程序里的WebAssembly是老版本的。需要低版本,如wasm-bindgen = “=0.2.76” 并且 在demo.ts中代码
找到下面代码的位置进行按图修改**
转rust
这个当然是请ai帮忙了^ ^,有了上面无缝对接的经验,相信你写出的ts可以顺利生成,无缝衔接的rust版本
rust代码和ts代码的对比
获取瓶子列表,这个rust版本
// 获取所有瓶子
pub fn get_bottles(&self) -> JsValue {
// 将 Vec<Bottle> 转换为 JavaScript 数组
let js_array = js_sys::Array::new();
for bottle in &self.bottles {
js_array.push(&JsValue::from(bottle.clone()));
}
js_array.into()
}
这个是ts版本
public get_bottles() {
return JSON.parse(JSON.stringify(this.bottles))
}
rust打包wasm
wasm-pack build --target web --release --no-typescript
这个时候会生成一个pkg的文件,里面有demo_bg.wasm demo.js
如果是ts项目,需要将demo.js 改为demo.ts
测试
目前准备了4个环境
1、nodejs/bunjs 测试
2、浏览器端测试
3、cocos环境测试
4、微信小程序端测试
1、nodejs/bunjs 测试
通过 bun xxxx.ts 进行原始ts的测试
2、浏览器端测试 测试
3、cocos环境测试
4、微信小程序端测试
这里如果直接用cocos的会错误需要修改,demo.ts中代码
找到下面代码的位置进行按图修改
通过降低wasm-bindgen版本以及修改部分demo.ts的代码,终于解决了微信兼容问题
源码
最后附上实验源码
cocos_ts_to_wasm_daoshui.zip (2.5 MB)







