Tutorial: Adding collision properties to your character

Introduction

In this tutorial you are going to learn how to:

  • Enable the Collision Detection System
  • Set collision properties for a 3D entity

Source Code

The files for this tutorial can be found here.

Overview

We are going to expand the project from the previous Tutorial by enabling Collision Detection to the entities.

In the previous Tutorial, you learned how to control the astronaut with the joystick (mouse). The astronaut walked around the screen as if it was not affected by gravity.

In this tutorial, we are going to add a bit more realism by allowing gravity to act on the character. If the astronaut is not standing on top of the island, then it will fall as shown in the following image:

tutorial102.gif

Setting Collision Properties

Let's set Collision Properties for our 3D model.

Open up the Astronaut.mm file and scroll down to the init() method.

Enable collision detection on the character as shown in line 1. Since we do not need the character to bounce too much, let's set its Coefficient of Restitution to 0.5 as shown in line 2.

In this project, we only want to detect if the astronaut is on top of the island. That is, we only want to know if is colliding with the island. Therefore, we don't need to calculate the collision response. Thus, we are going to set the character as a Collision Sensor as shown in line 3.

Finally, we are going to set its Collision tag as shown in line 4.

//Init method
bool Astronaut::init(const char* uModelName, const char* uBlenderFile){

    if(loadModel(uModelName, uBlenderFile)){

    //...Other initialization stuffs here

            //Line 1. Enable Collision Detection
            enableCollisionBehavior();

            //Line 2. Set the coefficient of restitution
            initCoefficientOfRestitution(0.5);

            //Line 3. set as collision sensor
            setIsCollisionSensor(true);

            //Line 4. set collision tag
            setCollidingTag("astronaut");

    //..other initialization stuffs here
    }

}

Adding a new state

Currently, the astronaut has two states. It has an idle and a walk state. We want to add a third state that indicates that our character is falling.

Modify the States Enum

Open up the UserCommonProtocols.h file. Sroll down to the CHARACTERSTATE enum and add the fallState as shown in line 1 below.

enum{

    idleState,
    walkState,
    fallState,   //Line 1. add a fall state

}CHARACTERSTATE;

Modify the changeState Method

Next, we need to determine what will happen when our character goes into the fallState.

Open up Astronaut.mm and scroll down to the changeState() method.

When the astronaut is falling, we want to reset gravity to (0.0,-10.0,0.0) and stop the animation. This is shown in line 2 in the snippet below:

void Astronaut::changeState(int uState){

    //set the current state of the astronaut
    setState(uState);

    switch (uState) {

        case idleState:

            //stop animation
            stopAnimation();

            break;

        case walkState:

            //play animation
            playAnimation();

            break;

        //Line 2. Reset gravity to (0.0,-10.0,0.0) and stop the animation
        case fallState: 

            resetGravity();
            stopAnimation();

            break;

        default:
            break;
    }
}

Checking for collisions

Open up the Astronaut.mm file and scroll down to the update() method.

In the update() method we check if the astronaut is colliding with the island. The Untold Engine provides a method that checks if a 3D model is currently colliding with another object. The method is getModelHasCollided().

The method returns true if there is a collision. We are going to us this method to check if the astronaut is currently colliding with the island (line 1).

If the astronaut is no longer colliding with the island, then we change its state to fallState as shown in line 2.

//Update method
void Astronaut::update(double dt){

    //Line 1. Check if the astronaut is not colliding with the island
    if(getModelHasCollided()!=true && state!=fallState){

        //Line 2. If is not colliding, then change its state
        changeState(fallState);
    }

    //check the current state of the astronaut
    if (state==walkState) {

        //If current state is walk, then apply force
        applyForce(3.0, dt);

    }else if(state==idleState){

        //If current state is idle, then remove velocity
        U4DEngine::U4DVector3n zero(0.0,0.0,0.0);
        setVelocity(zero);
        setAngularVelocity(zero);

    }

}

Run the project

In Xcode click on Run.

If you selected an iOS as your target device, move the joystick. If you selected a Mac as your target device, move the mouse or (arrow keys).

If the astronaut is no longer on top of the island, it will fall as shown below:

tutorial102.gif

Source Code

The files for this tutorial can be found here.