TypeError: Cannot read property 'physicsImpostor' of undefined

I am trying to use babylonjs in the react+typescript project, and I downloaded the example in the documentation. There were some errors in the running of this example, but some errors in RCA itself, which I solved later.

Then, I followed the steps of the readme file in the above example to create a new typescript application:
1.npx create-react-app demo --template typescript
2.Add babylonjs dependencies:
yarn add react-babylonjs
yarn add @babylonjs/core
yarn add @babylonjs/gui
yarn add @babylonjs/loaders
yarn add cannon
3. Use the src in the example to replace the src in the new project
4.yarn start

Here is my package.json file:

{
“name”: “my-app”,
“version”: “0.1.0”,
“private”: true,
“dependencies”: {
@babylonjs/core”: “^4.2.0”,
@babylonjs/gui”: “^4.2.0”,
@babylonjs/loaders”: “^4.2.0”,
@testing-library/jest-dom”: “^5.11.4”,
@testing-library/react”: “^11.1.0”,
@testing-library/user-event”: “^12.1.10”,
@types/cannon”: “^0.1.5”,
@types/jest”: “^26.0.15”,
@types/node”: “^12.0.0”,
@types/react”: “^17.0.0”,
@types/react-dom”: “^17.0.0”,
“cannon”: “^0.6.2”,
“react”: “^17.0.2”,
“react-babylonjs”: “^3.0.15”,
“react-dom”: “^17.0.2”,
“react-scripts”: “4.0.3”,
“typescript”: “^4.1.2”,
“web-vitals”: “^1.0.1”
},
“scripts”: {
“start”: “react-scripts start”,
“build”: “react-scripts build”,
“test”: “react-scripts test”,
“eject”: “react-scripts eject”
},
“eslintConfig”: {
“extends”: [
“react-app”,
“react-app/jest”
]
},
“browserslist”: {
“production”: [
“>0.2%”,
“not dead”,
“not op_mini all”
],
“development”: [
“last 1 chrome version”,
“last 1 firefox version”,
“last 1 safari version”
]
}
}

After running, it seems to be able to display normally at first, except the “×” before “click me” cannot be displayed(App.tsx file has no compilation error).

But when clicked, there’s an error:

If I turn the parameter “physicsImpostor” into an optional parameter

sphere.physicsImpostor!.applyImpulse(Vector3.Up().scale(10), sphere.getAbsolutePosition())

sphere?.physicsImpostor!.applyImpulse(Vector3.Up().scale(10), sphere.getAbsolutePosition())

There is no response after clicking, but the following error will be reported:

Any suggestions would be helpful,thanks for your help and time!

Hi!

Are you initializing the physics impostor in any way?

1 Like

No, how can I do it? But I didn’t initialize the physics impostor when I used the example in the document directly. :disappointed_relieved:

I am not sure how the react component is initializing the physics impostor, but it seems like the importor was not (yet?) created when you are trying to run the code. It also might be that the physics importor is not directly referenced in the mesh (you can have it declared separately, it will still work).

Enable physics on the scene, and enable the impostor on the mesh itself

1 Like

I didn’t make any changes to the original App.tsx file, maybe these codes are used for initialization?

If it has been initialized, I can’t understand why it still reports undefined :sweat:

Physics was initialized, but not the physics impostor of the specific mesh. When creating the mesh, you should probably add a physics impostor parameter, including the type of impostor and its options.

@brianzinn can help on this one for sure, as he is the brains behind the react integration.

1 Like

Thank you very much for your answers! I refer to the github of react-babylonjs but still puzzled,in the example of readme file,I didn’t find any code specifically for enable physics on the scene,maybe there are some details that I didn’t notice?

hi @Youmyin - Good questions - It’s definitely confusing to have that example not work with the latest version. I will update that repository to the react-babylonjs v3 as there are a few breaking changes. Most notably for you is that the hostInstance property for references does not exist and the returned value is the babylonjs object itself now. I will update that tonight.

For the font - I think that is really interesting and would actually be a cool extension to @babylonjs/gui. Specifically what is happening here is that the font is loaded that the GUI needs after the render, but the GUI isn’t invalidating (you are seeing a fallback font). Here is a workaround (the 1 second delay is just so you can see the icon change - you may need a hard page refresh to see):

const [fontsReady, setFontsReady] = useState(false);
const adtRef = useRef<AdvancedDynamicTexture | null>(null);
const faLoaded = useRef(false);
document.fonts.load("16px FontAwesome").then(() => {
  if (faLoaded.current !== true && adtRef.current !== null) {
    faLoaded.current = true;

    setTimeout(() => {
      setFontsReady(true);
      adtRef.current!.markAsDirty();
    }, 1000);
  }
});

return (
   <advancedDynamicTexture ref={adtRef} ...>
     ...
     <textBlock text={`${fontsReady ? '\uf00d' : 'X'} click me`} fontFamily='FontAwesome' ... />
     ...
   </advancedDynamicTexture>
)

Probably a cool extension for the GUI would be to listen to those events for those fonts (either automatically or via a usedFonts: string[] maybe and do a _markAsDirty() on the root containing rectangle. That would allow all fonts to appear - whereas right now you need to interact with the GUI to trigger the change. I wouldn’t say it’s a “bug” in babylonjs, but it would be useful for people loading fonts and not too much effort to add. I’ll message you again when that example project is updated - thanks for keeping me on my toes there :slight_smile:

2 Likes

Much obliged and expect for your reply! :smiley:

1 Like

ok - repo has been updated to v3.

I didn’t get time to check it 100% - i’m fixing production issues at work still… I think there is still a race condition that the .then can fire multiple times.

2 Likes

Thank you very much,I’ll try it ~