NOTE: A more general-purpose (and beginner-friendly) version of this guide is now available on the Babylon Docs!
Hi! Are you allergic to Webpack like I am? Do you hate dealing with its clunky config files? Thankfully the 2020s have given us Vite, which is simpler to use. But if you’re following the Create a Game Tutorial Series like I am, you’re probably wondering how to use it with Babylon.
This guide is intended to replace the Getting Set Up chapter in the tutorial series, but you should read Getting Started first if you haven’t used Babylon.js before.
-
Create a folder for your code project(s) and open it with a code editor like Visual Studio Code (or VSCodium.)
-
Install npm (either through here or your package manager if you’re running Linux).
-
Close and reopen your code editor to the same folder and then run each of these commands in the Terminal at the bottom after you do that:
npm i vite
(i
is short forinstall
)
npm i -D @babylonjs/core
(-D
is short for--save-dev
)
npm i -D @babylonjs/inspector
npm i -D @babylonjs/gui
-
Now run
npm init vite
and give your project any name you want, select “Vanilla,” and then select “TypeScript.” A project folder with the name you chose should now appear on the left-hand side. Feel free to rename this folder if you’d like.
(NOTE: The reason why we didn’t install the babylonjs packages inside the actual project folder that Vite just created is because it saves on space. Why install another copy of babylonjs in every project folder, when you can install it in the root folder above all your future game projects? You can use npm packages installed in folders ABOVE your working directory, not just in the same folder as your code.)
- Right-click this folder and click “Open in Integrated Terminal.” You should now have a second terminal window open that lists the name of your new generated project folder. Run
npm i
and thennpm run dev
. If you ctrl+click the localhost: link in the terminal, you should be taken to a functioning test page within your browser:
- Go back to your code editor and press Ctrl+C in the Terminal to stop Vite from running. Using the left-hand side bar, do the following:
- Delete everything inside the
src
andpublic
folders - Inside the
src
folder, create a file calledapp.ts
- Double-click
index.html
andtsconfig.json
to open them
*ignore the dist
folder
- Open
index.html
, paste in the following, and save:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title of Your Project</title>
</head>
<body>
<script type="module" src="./src/app.ts"></script>
</body>
</html>
(This is the same code as the lesson but with the addition of a script
tag to indicate our primary TS file.)
- Open
app.ts
, paste in the following, and save:
import "@babylonjs/core/Debug/debugLayer";
import "@babylonjs/inspector";
import "@babylonjs/loaders/glTF";
import { Engine, Scene, ArcRotateCamera, Vector3, HemisphericLight, Mesh, MeshBuilder } from "@babylonjs/core";
class App {
constructor() {
// create the canvas html element and attach it to the webpage
var canvas = document.createElement("canvas");
canvas.style.width = "100%";
canvas.style.height = "100%";
canvas.id = "gameCanvas";
document.body.appendChild(canvas);
// initialize babylon scene and engine
var engine = new Engine(canvas, true);
var scene = new Scene(engine);
var camera: ArcRotateCamera = new ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2, 2, Vector3.Zero(), scene);
camera.attachControl(canvas, true);
var light1: HemisphericLight = new HemisphericLight("light1", new Vector3(1, 1, 0), scene);
var sphere: Mesh = MeshBuilder.CreateSphere("sphere", { diameter: 1 }, scene);
// hide/show the Inspector
window.addEventListener("keydown", (ev) => {
// Shift+Ctrl+Alt+I
if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) {
if (scene.debugLayer.isVisible()) {
scene.debugLayer.hide();
} else {
scene.debugLayer.show();
}
}
});
// run the main render loop
engine.runRenderLoop(() => {
scene.render();
});
}
}
new App();
(This code is unaltered from the original lesson. Take note of how the import
statements allow the rest of the code to work, as well as how this structure should be divided into functions and class variables as you progress.)
- Open
tsconfig.json
, paste in the following, and save:
{
"compilerOptions": {
"target": "es6",
"lib": [
"dom",
"es6"
],
"useDefineForClassFields": true,
"module": "ESNext",
"rootDir": "src",
"moduleResolution": "node",
"resolveJsonModule": true,
"noResolve": false,
"sourceMap": true,
"noEmit": true,
"preserveConstEnums": true,
"isolatedModules": true,
"esModuleInterop": true,
"noImplicitAny": false,
"noUnusedLocals": false,
"noUnusedParameters": true,
"noImplicitReturns": true,
"skipLibCheck": true
},
"include": [
"src"
]
}
(This tsconfig.json file is a mix between the one provided in the tutorial and the one generated by Vite. I wrote a more efficient version of this file for the Babylon Docs version of this tutorial, but this works fine too. You can read more about how this file works in the TypeScript docs.)
- Run
npm run dev
in that second terminal and ctrl+click the localhost: link again to display it in your browser… and be amazed!
And just like before, you can press Ctrl+C in the terminal window to stop Vite from running.
Isn’t that so much cleaner to handle? Now you can turn your project into a Git repository if you want, and then move on to the next chapter. UPDATE: As you complete the rest of this tutorial, please keep the following in mind…
-
The lessons are a little unfinished- this series is more of an explanation of this game’s code rather than a step-by-step tutorial to make it. There’s also missing links to assets that you’ll need to grab yourself from the GitHub repo, such as textures or sound files. I was not able to run any code until I got to the Game GUI chapter that introduces
ui.ts
, and it was still crashing while looking for un-introduced sound files… -
Static assets and their respective folders (such as images/models/sounds/etc.) still go in the
public
folder so that they are included in any compiled bundles you make. If you get assets that don’t load in for some reason, try adding?url
to the end of your code’s filepaths. Some uncommon file types (such as.glsl
shader code) may need?raw
at the end to tell Vite to import the file as a string. This means/shaders/example.glsl
would become/shaders/example.glsl?raw
. -
OPTIONAL NOTE: This technically goes against the Vite docs’ recommendation of making every static asset’s path into an import statement, but you’ll have to create a
.d.ts
file in yoursrc
folder and figure out this code snippet if you want to do it this way. There really isn’t a need to do this unless you want to obscure the filenames of your assets (which doesn’t prevent players from ripping assets from your game) and also have the browser cache these large files locally. Caching your assets may irritate some players of your game since it’ll take up extra space on their computers, but doing this could theoretically allow them to play an offline copy of your game. I haven’t tested this though. -
ALSO OPTIONAL: If you really want to optimize your code and shrink your compiled bundle sizes, you can turn your import statements into dynamic ones. I haven’t tested if this works with Babylon.js yet either, but this video can help you get started if you want to explore that.
BUILDING AND SHARING ONLINE:
-
Once you reach the end of the tutorial series and address the extra notes above, you can build the final deployment of the game with
npm run build
and then test it withnpm run preview
. If everything works as intended, you can find the exported production code in thedist
folder. BEFORE you share it online, be sure to open theindex.html
file and edit the"/assets/index.(...).js"
string to add a period before the first slash. (Explanation for why this happens is in the next bullet point.) Now you can host online wherever you’d like! -
Once you build and host this code online, you may have a weird glitch where lit lanterns have weird red glowing patterns instead of their usual yellow appearance. This is caused by a typo left by the original developer. To fix this, go to
environment.ts
, locate the"/textures/litLantern.png"
string, and add a period in front of the first slash. (As you may have noticed, browsers can’t find folders in your root structure unless you have no preceding slash"like/this"
, or one with a period"./like/this"
, because"/doing/this"
confuses the browser.) -
If you’re unable to compile your code at all because of a leftover error, it’s probably because of
res
inapp.ts
, which can be resolved by adding a leading underscore to it like this:_res
. I don’t know why TypeScript wants us to annotate the variable like this, but it works.
And that’s how you use Vite with Babylon. Enjoy!