Invalid engine. Unable to create a canvas

const advancedTexture = AdvancedDynamicTexture.CreateFullscreenUI( "MainGuiContainer",true,this.Scene);
advancedTexture.addControl(xxxx)

I upgraded from v4 to v5, when i add the gui, an error occurs.I don’t know if the api changed after the upgrade

My package version:
···
@babylonjs/core”: “^5.0.3”,
@babylonjs/inspector”: “^5.0.3”,
@babylonjs/loaders”: “^5.0.3”,
@babylonjs/materials”: “^5.0.3”,
···

Did you update the gui to 5.0.3 as well?

Yes.
image

pinging @sebavan @RaananW

What error do you see exactly? how does the stacktrace look like?

Error: Invalid engine. Unable to create a canvas.
    at Function.__webpack_modules__.../../engine/lib/index.js.Control._GetFontOffset (index.js:241405:23)
    at TextBlock.__webpack_modules__.../../engine/lib/index.js.Control._prepareFont (index.js:241279:40)
    at TextBlock.__webpack_modules__.../../engine/lib/index.js.Control._applyStates (index.js:240728:22)
    at TextBlock.__webpack_modules__.../../engine/lib/index.js.TextBlock._applyStates (index.js:245962:43)
    at TextBlock.__webpack_modules__.../../engine/lib/index.js.Control._layout (index.js:240757:22)
    at Ellipse.__webpack_modules__.../../engine/lib/index.js.Container._layout (index.js:245238:35)
    at Container.__webpack_modules__.../../engine/lib/index.js.Container._layout (index.js:245238:35)
    at AdvancedDynamicTexture.__webpack_modules__.../../engine/lib/index.js.AdvancedDynamicTexture._render (index.js:269467:33)
    at AdvancedDynamicTexture.__webpack_modules__.../../engine/lib/index.js.AdvancedDynamicTexture._checkUpdate (index.js:269453:18)
    at Observer.callback (index.js:268875:111)

And how does the rest of the code look like? What engine are you creating? can you share a little more?

1 Like

I have a Viewer class that will initialize SceneHelper when instantiated, this class will add some GUI to Scene

export class Viewer {

  engine: Engine;
  private _engineOption: EngineOptions = {

    preserveDrawingBuffer: true,

    stencil: true,

  };

  private _sceneHelper: SceneHelper;

  constructor(

    public canvas: HTMLCanvasElement,

    private preview = false,

    private _option = { defaultLight: false }

  ) {

    this.init();

    this._regiser();

    this.render();

  }

  init() {

    this._initEngine();

    this._initScene();

    this._initCamera();

     this._initSceneHelper();
  }

  render() {

    this.engine.runRenderLoop(() => {

      if (this.Reading) return;

      this.sceneControl.render();

      if (this._sceneHelper) this._sceneHelper.render();

    });

  }

  private _regiser() {

    window.addEventListener("resize", () => {

      this.setSize();

    });

  }

  private _initEngine() {

    const engine = new Engine(this.canvas, true, this._engineOption);

    this.engine = engine;

  }

  private _initScene() {

    this.sceneControl = new SceneControl(this.engine);

  }

  private _initCamera() {

    this.cameraControl = new CameraControl(this.Scene, this.canvas);

  }

  private _initLight() {

    const light = new BHLight("global-light", new Vector3(1, 1, 1), this.Scene);

  }

  private _initSceneHelper() {

    this._sceneHelper = new SceneHelper(this.engine, this.Camera);

    this.Scene.onAfterRenderObservable.add(() => {

      const activeCamera = this._sceneHelper.Scene

        .activeCamera as ArcRotateCamera;

      activeCamera.inertialAlphaOffset = this.Camera.inertialAlphaOffset;

      activeCamera.inertialBetaOffset = this.Camera.inertialBetaOffset;

    });
  }
}
export class SceneHelper {
  private _scene: Scene;
  private _cameraHeight = 3.2;
  private ellipses: Ellipse[] = [];
  constructor(private engine: Engine, private camera: ArcRotateCamera) {
    this.init();
    this.initViewHelper();
  }
  public render() {
    if (this._scene.activeCamera) {
      this._scene.render();
    }
  }
  private init() {
    const scene = new Scene(this.engine);
    scene.autoClear = false;
    scene.ambientColor = Color3.White();

    scene.createDefaultCamera(true, true, true);
    scene.useRightHandedSystem = true;
    const activeCamera = scene.activeCamera as ArcRotateCamera;

    activeCamera.viewport = new Viewport(0.85, 0.85, 0.15, 0.15);

    activeCamera.detachControl();
    activeCamera.target = Vector3.Zero();
    activeCamera.setPosition(new Vector3(0, 0, this._cameraHeight));

    this._scene = scene;
  }
  private initViewHelper() {
    const height = 1;
    const option = { diameter: 0.05, height, tessellation: 96 };

    const root = new TransformNode("viewerHelper", this._scene);

    const Red = "#ff3653";
    const Green = "#8adb00";
    const Blue = "#2c8fff";

    //x-line
    const xl = CylinderBuilder.CreateCylinder("x-line", option, this._scene);

    xl.position.x += height / 2;
    xl.rotation.z = Math.PI / 2;

    xl.parent = root;

    const xMlt = new StandardMaterial("", this._scene);
    xMlt.ambientColor = Color3.FromHexString(Red);
    xl.material = xMlt;

    const yl = CylinderBuilder.CreateCylinder("y-line", option, this._scene);

    const yMlt = new StandardMaterial("", this._scene);
    yMlt.ambientColor = Color3.FromHexString(Green);
    yl.material = yMlt;
    yl.position.y += height / 2;

    const zl = CylinderBuilder.CreateCylinder("z-line", option, this._scene);

    const zMlt = new StandardMaterial("", this._scene);
    zMlt.ambientColor = Color3.FromHexString(Blue);
    zl.material = zMlt;

    zl.rotation.x = Math.PI / 2;
    zl.position.z += height / 2;

    const advancedTexture = AdvancedDynamicTexture.CreateFullscreenUI(
      "UI",
      true,
      this._scene
    );

    const opt = {
      height,
      cameraHeight: this._cameraHeight,
      scene: this._scene,
      camera: this.camera,
    };

   advancedTexture.addControl(GUI)
  }
}


I don’t know why the runtime context of gui and core is different after 4 upgrade to 5.

I think this is the reason for the error

Just as a test - could you set this variable to the engine you are creating? i.e.

EngineStore.LastCreatedEngine = this.engine; after creating the engine

Also - would you be able to share your project on github?

Thanks :slight_smile:

I solved the problem by modifying the rollup configuration. But I don’t know why the 4 version is ok, thank you all for your answers.

You got me there, I have no idea why that would work (or wouldn’t).

I’ll find time to play around with rollup and see. will be interesting to find out :slight_smile:

I am getting similar issues when trying to get a simple button working with 5.4.0.

Uncaught Error: Invalid engine. Unable to create a canvas.
at Function…/…/node_modules/@babylonjs/gui/2D/controls/control.js.Control._GetFontOffset (control.ts:2471:19)
at TextBlock…/…/node_modules/@babylonjs/gui/2D/controls/textBlock.js.TextBlock._processMeasures (textBlock.ts:295:40)
at TextBlock…/…/node_modules/@babylonjs/gui/2D/controls/control.js.Control._layout (control.ts:1715:22)
at Button…/…/node_modules/@babylonjs/gui/2D/controls/container.js.Container._layout (container.ts:413:31)
at Container…/…/node_modules/@babylonjs/gui/2D/controls/container.js.Container._layout (container.ts:413:31)
at AdvancedDynamicTexture…/…/node_modules/@babylonjs/gui/2D/advancedDynamicTexture.js.AdvancedDynamicTexture._render (advancedDynamicTexture.ts:713:29)
at AdvancedDynamicTexture…/…/node_modules/@babylonjs/gui/2D/advancedDynamicTexture.js.AdvancedDynamicTexture._checkUpdate (advancedDynamicTexture.ts:694:14)
at Observer.callback (advancedDynamicTexture.ts:382:98)
at Observable…/node_modules/@babylonjs/core/Misc/observable.js.Observable.notifyObservers (observable.ts:364:49)
at Scene…/node_modules/@babylonjs/core/scene.js.Scene._renderForCamera (scene.ts:3483:45)

The above was with: const advancedTexture = GUI.AdvancedDynamicTexture.CreateFullscreenUI(“UI”,true,this.scene);

when just do const advancedTexture = GUI.AdvancedDynamicTexture.CreateFullscreenUI(“UI”);
I get:
layer.ts:169 Uncaught (in promise) TypeError: Cannot read properties of null (reading ‘_getComponent’)
at new Layer (layer.ts:169:42)
at Function…/…/node_modules/@babylonjs/gui/2D/advancedDynamicTexture.js.AdvancedDynamicTexture.CreateFullscreenUI (advancedDynamicTexture.ts:1322:23)
at TileSet…/…/lib/TileSet.js.TileSet.showAttributionOSM (TileSet.ts:90:60)
at Game. (index.ts:116:20)
at step (index.ts:4:3)
at Object.next (index.ts:4:3)
at fulfilled (index.ts:4:3)

Got this working, I had to do:
import { AdvancedDynamicTexture, Button } from “@babylonjs/gui/2D”;

Previously I was doing
import * as GUI from “@babylonjs/gui/”;
it seems to work (ie, doesn’t give me any compile errors, but doesn’t work at runtime)

2 Likes

cc @RaananW

Actually, still having the issue. I moved the code out of the index.ts, and into the NPM module I’m trying to make, and the GUI error(s) are back. Interestingly I checked on the EngineStore, and it seems its not finding anything in the code for the NPM module:

enginestore num engines: 0
last engine: undefined
last scene: undefined

Perhaps this is some sort of Global Context issue I’m not quite understanding?

Solved!: in my NPM module I pass in the scene and engine (from the main file which calls it), and then I set:
EngineStore._LastCreatedScene=scene;
EngineStore.Instances.push(engine);
This solves the problem as EngineStore now has valid data.

2 Likes

I Got it working using babylonjs/core and babylonjs/gui packages using the version 5.6.1 I let the code sandbox example working.

Codesandbox Example

3 Likes

I run into same issue, and you’ve got it right.
Defining engine with BABYLON.Engine causes this, you might import Engine from @babylonjs/core then define your engine with new Engine(…)

1 Like