🎮 Making 3D Babylon Scenes more Dynamic with Actions
eankeen (615)

🎮 Making 3D Babylon Scenes more Dynamic with Actions

In the last tutorial, I showed you guys how to make a basic Babylon scene, with lights, cameras, player controls, gravity, collision and other stuff. This time, I'm going to show you how to make scenes more dynamic! If you want to continue where I left off, make sure you fork my repl from the last tutorial!

Image depics the logo of BabylonJS

Prerequisites

  • Intermediate JavaScript knowledge

Actions

To create things that are more dynamic in BabylonJS, you can use things called "Actions". To put it simply, Actions let you execute some function when an event occurs. For example, you can log some output to the console if you look at a Sphere.

Before creating an Action, you must create an ActionManager. This lets you attach multiple actions to the same object. In this case, we are adding an ActionManager to the scene

scene.actionManager = new BABYLON.ActionManager(scene);

Now since we have our ActionManager all set up, we can create some Actions. To start off simply, we're going to create an "action" that tells the user when they have pressed space.

let myAction = new BABYLON.ExecuteCodeAction(
    BABYLON.ActionManager.OnKeyUpTrigger,
    function(event) {
        if(event.sourceEvent.key === " ") {
            console.log("You have pressed space");
        }
    }
)
gameScene.actionManager.registerAction(myAction);
  • We're using the BABYLON.ExecuteCodeAction() constructor to create the "Action".
  • The first argument of the constructor is a "trigger". A trigger will cause the action to execute. In this case, the trigger is "pressing a button on the keyboard"
  • The second argument to the constructor is the function we want to execute. In this case, we create a function that logs some output to the console, but only if the user pressed space.

Cool! So when you press space, it logs to the console. If you want to see it in action, check out this repl.

But logging some text to the console is pretty boring. Wouldn't it be cooler if it spawned in some spheres?

Here I simply call the createSphere function instead of logging output to the console.

  let action = new BABYLON.ExecuteCodeAction(
    BABYLON.ActionManager.OnKeyUpTrigger,
    function(event) {
      if(event.sourceEvent.key === " ") {
        createSphere(scene);
      }
    }
  )
  scene.actionManager.registerAction(action);
};

Inside of the createSphere function, I create a Sphere Mesh. Like in the prevoius tutorial, I create a physics imposter and set collisions to true, so it collides with the ground and other spheres.

function createSphere(scene) {
  // Create Sphere Mesh
  let mySphere = BABYLON.MeshBuilder.CreateSphere("sphere", {
    diameter: 1
  }, scene);

  // Give the sphere mesh a height so it spawns above the ground
  mySphere.position.y = 2;

  // Create a Pysics Imposter around the Sphere, and enable collisions so it interacts with other parts of the scene
  let mySpherePhysicsImposter = new BABYLON.PhysicsImpostor(
    mySphere,
    BABYLON.PhysicsImpostor.BoxImpostor,
    {
      mass: 0.01, 
      friction: 0.1, 
      restitution: .85
    },
    scene
  );
  mySphere.collisionsEnabled = true;
  mySphere.checkCollisions = true;
}

As you can see in the gif below, it works! 😄

If the spheres are not acting the way you want them to, you might want to change the mass, friction, or restitution of the spheres. You may also want to make gravity stronger. See it working in this repl!

Changing a single Mesh

Besides creating new meshes, you can also modify the properties of existing meshes! For example, I could use Actions to change the color of a Mesh whenever I look at it.

Let's do exactly that. First, let's create a Cylinder Mesh.

let cone = createCone(scene);

The createCone function looks something like this

function createCone(scene) {
  // Create the cylinder
  let cone = new BABYLON.MeshBuilder.CreateCylinder("cone", {
    height: 5,
    diameterBottom: 3,
    diameterTop: 0
  });
  cone.position.x = -3;
  cone.position.z = -3;
  cone.position.y = 1;

  // Create a physics imposter and make sure collisiosn are enabled (so the spheres bounce off of it)
  new BABYLON.PhysicsImpostor(
    cone,
    BABYLON.PhysicsImpostor.BoxImpostor,
    {
        mass: 1000,
        friction: 3, 
        restitution: .7
    },
    scene
  );
  cone.collisionsEnabled = true;
  cone.checkCollisions = true;

  let coneMaterial = new BABYLON.StandardMaterial(scene);
  coneMaterial.diffuseColor = new BABYLON.Color3(105 / 256, 256 / 256, 124 / 256); // green
  cone.material = coneMaterial;

  return cone;
}

The function looks pretty similar to what we went over in the first tutorial. The difference is at the bottom - we're changing the color of the cone. We do this by creating a new (Standard) material. To actually change the color, we set the diffuseColor property of the material to a color. Then, we assign that material to our cone.

OK, so we created our cone. Let's make it change color when we hover over it. First, create another action manager. This time, we create an Actionmanager for the cone rather than the scene.

cone.actionManager = new BABYLON.ActionManager(scene);

let coneAction = new BABYLON.ExecuteCodeAction(
    BABYLON.ActionManager.OnPointerOverTrigger,
    function(event) {
        changeConeColor(cone);
    }
);
cone.actionManager.registerAction(coneAction); 

The changeConeColor function will trigger when the mouse has hovered over the cone. If you want to see all of Babylon's triggers, you can check their documentation!

Inside changeConeColor, I just created random red, green, and blue numbers and created a color using Babylon's BABYLON.Color3 constructor. I then set the cone's material to that color (diffuseColor).

function changeConeColor(cone) {
  let r = Math.floor(Math.random() * 256) + 1;
  let g = Math.floor(Math.random() * 256) + 1;
  let b = Math.floor(Math.random() * 256) + 1;
  cone.material.diffuseColor = new BABYLON.Color3(r / 256, g / 256, b / 256);
}

And there you have it! There is a lot more movement in our scene now! If you wish, you can check this repl](https://repl.it/@eankeen/babylon-animation-tutorial-3) to take a look!

I hope you found this tutorial useful, please let me know!

You are viewing a single comment. View All
eankeen (615)

@ebest are you sure? it looks fine when I open it