Untitled

📰Getting Started | ⭐**Updates |** 📝 Guides | 🔢 API | ❓FAQ

Guides Overview

<aside> 💡 This is a new and developing feature!

</aside>

Rigidbody

The Rigidbody API allows you to interact with an Element’s Rigidbody Component, if it has been imported to Enklu from Unity with one, and create dynamic physics-based interactions and events in your experience.

<aside> ⬇️ Optimal Import Settings

</aside>

What is “Rigidbody”?

Setup and Known Behaviors

Before you start working with the Rigidbody API, you’ll probably want to setup a scene that makes your physics objects easy to work with.

When you first create an Element and attach a Rigidbody-enabled Asset, you’ll probably see that Asset fall through the floor into the infinite abyss…

This is normal. There just isn’t anything acting as the ground! Try placing the Public Asset “Occluder Cube” right below the Element containing the Rigidbody-enabled Asset. Now reload the experience and see if the Occluder Cube catches the Asset before it falls. You may need to adjust it further.

A Rigidbody-enabled Asset will collide with any other Asset that has a non-trigger collider.

<aside> 💡 In general, do not use objects with Colliders that are marked as Triggers with the Rigidbody API. Some Rigidbody functions do not work with Trigger Colliders.

</aside>

You will also notice that the Rigidbody-enabled Asset seems to move independently from the position of the Element. After the Asset moves, the transform of the Element does not move. This is normal!

Try moving the Element. You’ll see that it moves with the Asset in tow, no matter where the Asset is, as if it’s parented to the Element.

Once your object is no longer falling through the ground, and it’s comfortably visible, you should be good to start making some physics magic happen!

Accessing the API

The Rigidbody API can be accessed on any Elements that contain an Asset with an added Rigidbody Component. Similar to other APIs like Animator, access the API like so:

const self = this;
var rb = self.rigidbody;

In this example, the variable rb now refers to the Rigidbody API of that Element, which will interact with the Asset’s Rigidbody Component under the hood, and allow you to play around with that Asset using physics!

It’s always good to null check in case there is some error finding the Rigidbody Component, or you have changed to a different Asset that doesn’t have a Rigidbody Component but has the same script. This may also tell you if the Asset was not properly exported with the Rigidbody Component.

if (!rb) {
    log.error('Asset missing rigidbody!');
		return;
}

Getting and Setting Rigidbody Properties

The Rigidbody API allows you to manually get or set properties of an Asset’s Rigidbody Component, to further customize your physics interactions. For example, you may want objects to be super heavy, or have everything float around for a space-themed experience!

There are three properties available:

Interacting with these properties is as simple as referencing the property from the Rigidbody API and assigning a new value or using the returned value.

const self = this;
var rb = self.rigidbody;

enter() 
{
	rb.mass = 5.0;
	log.info(rb.mass);

	rb.useGravity = true;
	log.info(rb.useGravity);

	rb.isKinematic = false;
	log.info(rb.isKinematic);
}

Check the Module Methods section at the bottom of this page for more details about each of these properties and what data types they use.

Adding Forces

One of the main ways you would interact with Rigidbody-enabled Assets is by adding forces to them. If you want to launch a rocket into the sky, or shoot an object to hit another, you’ll need to use the functions below.

At any time, you can apply force to a Rigidbody-enabled Asset using the addForce() method, which applies a defined force type to the Asset in a world x, y, and z direction.

There is also addRelativeForce() which has identical syntax, but applies force in the local coordinate axis of the Asset.

These functions take in four parameters: the individual x, y and z components of the force direction vector, and a forcemode, the type of force you would like to apply.

<aside> 💡 Note that this will only affect Assets that are not kinematic (i.e. isKinematic = false). Kinematic objects are not affected by gravity or forces.

</aside>

There are four Force Modes available.

The Force Mode parameter is inputted as a string - note the casing. Their specific syntaxes are shown below and can also be found in Module Methods.

const self = this;
var rb = self.rigidbody;

rb.addForce(0.5, 0, 0, "impulse");
rb.addForce(0.5, 0, 0, "force");
rb.addForce(0, 0, 0.5, "acceleration");
rb.addForce(0, 0, 0.5, "velocityChange");

// syntax is basically identical for addRelativeForce, besides the name of the function.
// syntax for the forcemode is identical.
rb.addRelativeForce(0.5, 0, 0, "impulse"); 

Registering Collision Callbacks

You will probably want something to happen when Rigidbody-enabled Assets collide with things. You can do that by registering collision callbacks!

To do so, write a function of your choosing, and then provide the name of your function to the registerCallback() method as a parameter.

This will “register” your function as the function that will be called whenever this asset collides with something. Make sure to unregisterCallback() in exit() or when you are done with it.

<aside> 💡 You can only register one collision callback at a time.

</aside>

You would usually call registerCallback() in the enter() function so that the callback is registered from the moment you start playing the experience, though you can use registerCallback() at any time, and even set it on the fly.

The example below will print the message whenever this Asset collides with another.

const self = this;
var rb = self.rigidbody;

enter() 
{
	registerCallback(printOnCollision);
}

function printOnCollision() {
	log.info(“asset hit something!");
}

exit()
{
	unregisterCallback();
}

You might also want information about the collision to add additional functionality. Where did the collision occur so I can activate a particle effect? What is the identity of the other object in the collision so that I can make it do something when the collision happens?

The collision callbacks provide access to an optional parameter that gives you all this information. Here is the information that is available:

In your custom function, simply add a single parameter with a name of your choosing. Now, this parameter will be filled with information about the collision that you can use when the collision occurs. Do whatever you want with that information!

const self = this;
var rb = self.rigidbody;

enter() 
{
	registerCallback(showOtherObjectInCollision);
}

function showOtherObjectInCollision(collision) {
	log.info(“a collision occurred");
	log.info(collision.location); 
	// here, we could move an element with a particle effect to the location of the other object in the collision.
	
	log.info(collision.other);
	// the 2 following lines are Elements API methods.
	log.info(collision.other.name);
	log.info(collision.other.transform.position);

	log.info(collision.relativeVelocity);
}

exit()
{
	unregisterCallback();
}

<aside> 💡 Be sure to unregister your callback in exit() or at least when you are done using it! Callbacks left unregistered might keep executing in the background. If this happens, make sure that unregisterCallback() is called in exit() and reload the experience.

</aside>

Making Rigidbody-enabled Assets Grabbable

<aside> 💡 Note that you can only interact with this feature in the HoloLens - however, you will need to use the Web Editor to set it up.

</aside>

The Rigidbody API also provides support for grabbing and releasing Rigidbody-enabled Assets with your hands, in the HoloLens!

It’s pretty simple to make an Asset grabbable (or not grabbable). If an Asset has a Rigidbody Component, simply use these lines:

const self = this;
var rb = self.rigidbody;

enter()
{
	rb.isGrabbable(true);
}

function turnOffGrabbable()
{
	rb.isGrabbable(false);
}

And voilĂ , the Asset has been made grabbable!

How to grab the Asset:

Registering Release Callbacks

You will likely want something to happen when grabbable Assets are released, such as checking how close to a drop area you have let go of the object. You can do that by registering release callbacks!

It is very similar to how you set up collision callbacks, but note the syntax differences!

Write a function of your choosing, and then provide the name of your function to the registerReleaseCallback() method as a parameter.

This will “register” your function as the function that will be called whenever this Asset is released. Make sure to unregisterReleaseCallback() in exit() or when you are done with it.

<aside> 💡 You can only register one release callback at a time.

</aside>

You would usually call registerReleaseCallback() in the enter() function so that the callback is registered from the moment you start playing the experience, though you can use registerReleaseCallback() at any time, and even set it on the fly.

The example below will print a message whenever this Asset is released.

const self = this;
var rb = self.rigidbody;

enter() 
{
	registerReleaseCallback(printOnRelease);
}

function printOnRelease() {
	log.info(“asset was dropped!");
}

exit()
{
	unregisterReleaseCallback();
}

You might also want information about the release to add additional functionality. What is the name of the object I released, so I can do something special when I release this particular object in the drop area?

The release callbacks provide access to an optional parameter that gives you a reference to the Elements API of the grabbable Asset you released.

In your custom function, simply add a single parameter with a name of your choosing. Now, this parameter will be filled with a reference to the Elements API of the Asset you release.

const self = this;
var rb = self.rigidbody;

enter() 
{
	registerReleaseCallback(showObjectReleased);
}

function showObjectReleased(element) 
{
	// these are Elements API methods.
	log.info(element.name);
	// note that this will give the transform of the ELEMENT this Asset is attached to, not the Rigidbody-enabled Asset's location itself.
	log.info(element.transform.position);
}

exit()
{
	unregisterReleaseCallback();
}

The second comment in the above example raises another point - what if you wanted to reference the position of the Asset itself? After all, the Asset moves independently of the Element.

This information is not provided in the callback because it is redundant with a function that already exists in the Rigidbody API. You can use the function getPosition() to get a Vec3 of the position of the Rigidbody Asset at any time.

This, then, can be used in conjunction with the callback!

const self = this;
var rb = self.rigidbody;

enter() 
{
	registerReleaseCallback(showObjectReleased);
}

function showObjectReleased(element) 
{
	// these are Elements API methods.
	log.info(element.name);
	// note that this will give the transform of the ELEMENT this Asset is attached to, not the Rigidbody-enabled Asset's location itself.
	log.info(element.transform.position);

	// show the position of the Rigidbody Asset itself.
	log.info(rb.getPosition());
}

exit()
{
	unregisterReleaseCallback();
}

Look at the Module Methods at the bottom of the page for other functions that may be applicable to release callbacks that are not provided in the parameter.

<aside> 💡 Be sure to unregister your callback in exit() or at least when you are done using it! Callbacks left unregistered might keep executing in the background. If this happens, make sure that unregisterReleaseCallback() is called in exit() and reload the experience.

</aside>

Module Methods


Untitled