You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The behavior of opening or closing a prefab will trigger scene switch, there is a global variable called _sharedAtlas in letter-font.ts whose texture will be cleared and re-constructed.
// font-utils.tsexportclassLetterAtlas{
......
constructor(width: number,height: number){
......
// Subscribe the event of before loading scene.director.on(DirectorEvent.BEFORE_SCENE_LAUNCH,this.beforeSceneLoad,this);}publicbeforeSceneLoad(): void{this.clearAllCache();}publicclearAllCache(): void{this.destroy();// Will destroy the internal texture instanceconsttexture=newLetterRenderTexture();// Re-create the internal texture instancetexture.initWithSize(this._width,this._height);this.fontDefDictionary.texture=texture;}publicdestroy(): void{this.reset();constdict=this.fontDefDictionary;if(dict&&dict.texture){dict.texture.destroy();dict.texture=null;}}
There is a new functionality that could preview a prefab in inspector window in v3.8.5.
It uses an individual scene which will never be destroyed and never be run.
Some code snippet:
// preview/Interactive-preview.tsclassInteractivePreviewextendsPreviewBase{protectedscene!: Scene;protectedcameraComp!: Camera;protectedcamera: renderer.scene.Camera|null=null;protectedworldAxisNode!: Node;protectedaxisCameraOffset=newVec3(0,0,40);protectedisMouseLeft=false;protectedisMouseMiddle=false;protectedenableAxis=true;protectedworldAxis: PreviewWorldAxis|null=null;protectedenableGrid=true;protectedgrid: Grid|null=null;protectedenableSkybox=true;protectedskybox: SkyboxInfo|null=null;publiccreateNodes(scene: Scene){}publicinit(registerName: string,queryName: string){this.scene=newScene(registerName);if(this.enableSkybox){this.skybox=this.scene.globals.skybox;this.scene.globals.skybox.enabled=true;}this.cameraComp=newNode(registerName+'camera').addComponent(Camera);this.cameraComp.node.setParent(this.scene);this.cameraComp.node.setPosition(0,1,2.5);this.cameraComp.node.lookAt(Vec3.ZERO);this.cameraComp.near=0.01;this.cameraComp.enabled=false;this.createNodes(this.scene);// Load the scene manually instead of running it.this.scene._load();this.scene._activate();this.cameraComp.clearColor=newColor(71,71,71,255);this.camera=this.cameraComp.camera;
......
// Create the Preview buffer which will create an offscreen RenderWindow. See the code bellow.this.previewBuffer=newPreviewBuffer(registerName,queryName,this.scene);// Change the render window for camera which created in preview buffer.this.camera.changeTargetWindow(this.previewBuffer.window);
........}
// preview/buffer.tsclassPreviewBufferextendsEventEmitter{
......
constructor(registerName: string,name: string,scene: any=null){super();
......
this.createWindow();// Create render windowthis.queue=[];}createWindow(uuid: string|null=null){if(uuid&&this.windows[uuid]){this.window=this.windows[uuid];return;}constroot=cc.director.root;constrenderPassInfo=newgfx.RenderPassInfo([newgfx.ColorAttachment(root.mainWindow.swapchain.colorTexture.format)],newgfx.DepthStencilAttachment(root.mainWindow.swapchain.depthStencilTexture.format),);renderPassInfo.colorAttachments[0].barrier=root.device.getGeneralBarrier(newgfx.GeneralBarrierInfo(0,gfx.AccessFlagBit.FRAGMENT_SHADER_READ_TEXTURE));constwindow=root.createWindow({title: this._name,width: this.width,height: this.height,
renderPassInfo,isOffscreen: true,// Mark it as an offscreen render window.});this.window=window;uuid&&(this.windows[uuid]=window);}
So we get an independent preview-prefab-scene who contains an offscreen render window and all its children will be walked and rendered to offscreen texture even the preview-prefab-scene is not the current active scene.
When the global variable _sharedAtlas re-creates the altas texture, the label with char mode will not know that the texture is destroyed and changed. It will use the destroyed texture to render the label in preview-prefab-scene. Then, we get the error message in Label._render.
// label.tsprotected_render(render: IBatcher): void{// BOMB, this._texture was destroyed.render.commitComp(this,this.renderData,this._texture,this._assembler!,null);}
Probable Solutions
Solution 1
The global variable _sharedAtlas should be associated with scene, which means each scene should have an individual _sharedAtlas instance. So when editor switchs scenes, the label cached in preview-prefab-scene will hold a valid texture.
And add a public interface to re-create the texture in _sharedAtlas, this is for editor to release the memory manually.
I don't find a good place the store all _sharedAtlas instances ( one per scene).
Solution 2
Fire an event when the texture re-created, Label component subscribes that event and update the texture. This solution will make the label cached in preview-prefab-scene always change the texture and fill new letter textures to altas texture which will cause some redundant operations.
Solution 3
Don't re-create the letter altas texture while scene switch in editor mode, add a reset method for editor to decide when to re-create it.
Solution 4
Use Asset.refCount to decide whether could destroy the altas texture.
The text was updated successfully, but these errors were encountered:
Reported at https://forum.cocos.org/t/topic/164672
This issue is fired in v3.8.5.
How to Reproduce?
CHAR
Get the error log:
Reason
The behavior of opening or closing a prefab will trigger scene switch, there is a global variable called
_sharedAtlas
inletter-font.ts
whose texture will be cleared and re-constructed.There is a new functionality that could preview a prefab in inspector window in v3.8.5.
It uses an individual
scene
which will never be destroyed and never be run.Some code snippet:
So we get an independent
preview-prefab-scene
who contains an offscreen render window and all its children will be walked and rendered to offscreen texture even thepreview-prefab-scene
is not the current active scene.When the global variable
_sharedAtlas
re-creates the altas texture, the label with char mode will not know that the texture is destroyed and changed. It will use the destroyed texture to render the label inpreview-prefab-scene
. Then, we get the error message in Label._render.Probable Solutions
Solution 1
The global variable
_sharedAtlas
should be associated with scene, which means each scene should have an individual_sharedAtlas
instance. So when editor switchs scenes, the label cached inpreview-prefab-scene
will hold a valid texture.And add a public interface to re-create the texture in
_sharedAtlas
, this is for editor to release the memory manually.I don't find a good place the store all
_sharedAtlas
instances ( one per scene).Solution 2
Fire an event when the texture re-created, Label component subscribes that event and update the texture. This solution will make the label cached in
preview-prefab-scene
always change the texture and fill new letter textures to altas texture which will cause some redundant operations.Solution 3
Don't re-create the letter altas texture while scene switch in editor mode, add a
reset
method for editor to decide when to re-create it.Solution 4
Use Asset.refCount to decide whether could destroy the altas texture.
The text was updated successfully, but these errors were encountered: