Intermediate Tutorial


Three Ways to Click an Entity


15 minutes

Posted on: October 21, 2017

Learn Sumerian
Three Ways to Click an Entity

Tags

picking
Hardware picking
raycasting
performance
state machine

In this tutorial you will learn about:

Hardware picking
Bounding box raycasting
collider raycasting

Note: Due to some changes to the Amazon Sumerian Scripting API, we do not recommend using this tutorial. While some of the approaches may still work, they will not be reliable.

There are many situations in which you want your scene to initiate an action when an entity is clicked. You can do this in several ways, but the approach you choose depends on your scenario. In this tutorial, you learn the three “clicking” options in Amazon Sumerian:

  • Hardware picking
  • Bounding box raycasting
  • Collider raycasting

Prerequisites

You should have completed the following tasks and tutorials:

Scene Setup

From the Dashboard, create a scene from the Default Lighting template.

Solution 1: Hardware Picking

Hardware picking is perfect when your scene is waiting for a single click, by a mouse or a virtual reality (VR) controller, on a visible entity. The easiest way to implement hardware picking is to use the Click/Tap on entity action in the State Machine. The Click/Tap on entity action transitions when the entity is “hardware picked” (by the mouse or VR controller).

  1. Add a State Machine component to the entity you want to click, and then add a new behavior.

  2. Add a Click/Tap on entity action in the the default State 1.

  3. Create a new state and add another reactive action to define what should happen when an entity is clicked (or “picked”). For this exercise, search for and then add Fire FX, which will cause our entity to burst into flames.

  4. Create a Transition in the State Graph by selecting your Pick state and dragging it over to the Fire state.

  5. Press play, and then click your entity. Your click should set it on fire.

Solution 2: Bounding Box Raycasting

This option is good when you need more performance than hardware picking. However, this method isn’t as precise as hardware picking.

Put the following script on the entity for which you want to detect a click.

var setup = function(args, ctx) {
    ctx.ray = new sumerian.Ray();

    ctx.onClick = function(evt){
        var dpr = ctx.world.sumerianRunner.renderer.devicePixelRatio;
        var x = evt.clientX * dpr;
        var y = evt.clientY * dpr;
        var activeCamera = ctx.activeCameraEntity.cameraComponent.camera;
        activeCamera.getPickRay(x, y, ctx.viewportWidth, ctx.viewportHeight, ctx.ray);
        var isHit = ctx.entity.meshRendererComponent.worldBound.intersectsRay(ctx.ray);
        if(isHit){
            sumerian.SystemBus.emit(args.channel);
        }
    };

    ctx.domElement.addEventListener('click', ctx.onClick);
};

var cleanup = function(args, ctx) {
    ctx.domElement.removeEventListener('click', ctx.onClick);
};

var parameters = [{
    key: 'channel',
    type: 'string',
    'default': 'pick'
}];

Now you can listen for a Pick event in scripts or in the State Machine (set the channel in your listening state to “pick”).

Solution 3: Collider Raycasting

If you need performance, but also more precision than bounding box raycasting offers, you should use collider raycasting.

  1. Put a Collider component on the entity on which you want to detect a click.

  2. Put the following script on the same entity.

 var setup = function(args, ctx) {
    ctx.ray = new sumerian.Ray();
    ctx.physicsSystem = ctx.world.getSystem('PhysicsSystem');
    ctx.result = new sumerian.RaycastResult();

    ctx.onClick = function(evt){
        var dpr = ctx.world.sumerianRunner.renderer.devicePixelRatio;
        var x = evt.clientX * dpr;
        var y = evt.clientY * dpr;
        var activeCamera = ctx.activeCameraEntity.cameraComponent.camera;

        activeCamera.getPickRay(x, y, ctx.viewportWidth, ctx.viewportHeight, ctx.ray);
        ctx.physicsSystem.raycastClosest(ctx.ray.origin, ctx.ray.direction, args.maxDistance, {}, ctx.result);
        if(ctx.result.entity === ctx.entity){
            sumerian.SystemBus.emit(args.channel);
        }
        ctx.result.reset();
    };

    ctx.domElement.addEventListener('click', ctx.onClick);
};

var cleanup = function(args, ctx) {
    ctx.domElement.removeEventListener('click', ctx.onClick);
};

var parameters = [{
    key: 'channel',
    type: 'string',
    'default': 'pick'
},{
    key: 'maxDistance',
    type: 'float',
    'default': 10000,
    min: 0
}];

Now you can listen for a Pick event in the script editor or in the State Machine (set the channel in your listening state to “pick”).

Now publish and share your scene!

You should now have a much better understanding of clicking, or picking, options: Hardware picking, bounding box raycasting, and collider raycasting. For more information on this topic, check out the following tutorials:

Back to Tutorials

© 2019 Amazon Web Services, Inc or its affiliates. All rights reserved.