有时我们会碰到一个物体频繁更换模型的情况,比如:一块花田里的作物经常改变,自己的某个装饰,如车位上的汽车经常动态设置。如果异步创建管理不好,可能出现后创建的物体被先创建的物体覆盖的情况。我分享一个类,可以频繁创建更换预制件 ^_^
1. 定义一个异步物体类 AsyncObject
2. 在类里定义一个 公有属性 public go: Core.GameObject;。这个属性就是现在这个对象所创建出来的 物体。
3. 定义一个公有函数 public async setGuid(guid?: string): Promise<Core.GameObject>。用于外部每次设置需要异步加载的预制体的 guid,并异步返回创建的物体。
/**
* 设置物体的 guid
* @param guid 设置的 guid
* @param initCall 生成完成的回调
* @param initCallTag 生成完成的回调的调用对象
* @returns
*/
public async setGuid(guid?: string): Promise<Core.GameObject> {
// 校验是否需要生成
if (this._goGuid == guid) {
return this.getGo();
}
this._goGuid = guid;
if (this.go) {
this.go.destroy();
this.go = null;
}
if (!guid) {
this.onCreateGo(null);
return null;
}
// 生成物体
let go = await Core.GameObject.asyncSpawnGameObject(guid);
await go.ready();
if (guid != this._goGuid) {
go.destroy();
return this.getGo();
}
// 校验物体是否需要释放
if (guid != this._goGuid) {
go.destroy();
return;
}
if (this.go) {
this.go.destroy();
}
// 将物体赋值给类成员
this.go = go;
this.onCreateGo(go);
return go;
}
4. 我们再考虑这个函数多次调用的情况:
5. 每次调用 setGuid,如果当前 guid没变,且是相同创建。哪我们就需要保存当前的 promise,等待这次创建结束后再调用。
6. 相同 guid的物体不能多次初始化,所以我们将初始化函数传入,就只有在创建的时候执行一次初始化。
/**
* 设置物体的 guid
* @param guid 设置的 guid
* @param initCall 生成完成的回调
* @param initCallTag 生成完成的回调的调用对象
* @returns
*/
public async setGuid(guid?: string, initCall?: (go: Core.GameObject) => Promise<void>, initCallTag?: any): Promise<Core.GameObject> {
// 校验是否需要生成
if (this._goGuid == guid) {
return this.getGo();
}
this._goGuid = guid;
if (this.go) {
this.go.destroy();
this.go = null;
}
if (!guid) {
this.onCreateGo(null);
return null;
}
// 生成物体
let go = await Core.GameObject.asyncSpawnGameObject(guid);
await go.ready();
if (guid != this._goGuid) {
go.destroy();
return this.getGo();
}
// 初始化物体
if (initCall) {
await initCall.call(initCallTag, go);
}
// 校验物体是否需要释放
if (guid != this._goGuid) {
go.destroy();
return;
}
if (this.go) {
this.go.destroy();
}
// 将物体赋值给类成员
this.go = go;
this.onCreateGo(go);
return go;
}
7. 我们再考虑加入设置显示隐藏的功能,这个功能将显示的数据和物体的具体显示分开。
/**
* 设置显隐
*/
private _show: boolean = true;
public get show() {
return this._show;
}
public set show(isShow: boolean) {
this._show = isShow;
if (this.go) {
this.go.setVisibility(isShow ? Type.PropertyStatus.On : Type.PropertyStatus.Off);
}
}
8. 创建出来了再设置一次显隐
9. 剩下的 onCreateGo 等函数 见楼下详细代码 Q.Q
|