热重载
复杂项目每次改脚本都完整刷新很低效,尤其进入测试状态需要较长时间时。代码热替换可以避免这一过程。
使用热替换
按脚本启用,只需实现 swap()。
- ESM
- 经典脚本
swap(old) {
// Recover state here
}
MyScript.prototype.swap = function(old) {
// Recover state here
};
修改带 swap 的脚本后,已启动应用重新加载并注册脚本,创建新实例替换旧实例,为每个新实例调用 swap,但不再调用 initialize。旧实例作为参数传入,由开发者复制运行状态;已声明脚本属性自动复制。同时应移除旧实例监听器,在新实例重新注册。
例如:
- ESM
- 经典脚本
import { Script, math } from 'playcanvas';
export class Rotator extends Script {
static scriptName = 'rotator';
/**
* @attribute
*/
xSpeed = 10;
initialize() {
// Listen for enable event and call method
this.on('enable', this._onEnable);
this.ySpeed = 0;
}
swap(old) {
// xSpeed is an attribute and so is automatically copied
// Copy the ySpeed property from the old script instance to the new one
this.ySpeed = old.ySpeed;
// Remove the old event listener
old.off('enable', old._onEnable);
// Add a new event listener
this.on('enable', this._onEnable);
}
_onEnable() {
// When enabled, randomize the speed
this.ySpeed = math.random(0, 10);
}
update(dt) {
this.entity.rotate(this.xSpeed * dt, this.ySpeed * dt, 0);
}
}
var Rotator = pc.createScript('rotator');
Rotator.attributes.add('xSpeed', { type: 'number', default: 10 });
Rotator.prototype.initialize = function () {
// Listen for enable event and call method
this.on('enable', this._onEnable);
this.ySpeed = 0;
};
Rotator.prototype.swap = function (old) {
// xSpeed is an attribute and so is automatically copied
// Copy the ySpeed property from the old script instance to the new one
this.ySpeed = old.ySpeed;
// Remove the old event listener
old.off('enable', old._onEnable);
// Add a new event listener
this.on('enable', this._onEnable);
};
Rotator.prototype._onEnable = function () {
// When enabled randomize the speed
this.ySpeed = pc.math.random(0, 10);
}
Rotator.prototype.update = function (dt) {
this.entity.rotate(this.xSpeed * dt, this.ySpeed * dt, 0);
};
尝试修改 update 并保存,应用会自动将 rotator 替换为新实例,继续使用新逻辑运行。
无论实例当前是否运行,swap 都会调用,因此错误导致禁用的实例也可在其中重新启用。