Object Selection and Send Back

Hi! I am new to PlayCanvas and have been reading over the forums and tutorials. Currently I am working on creating an object selector/viewer. I have 3 main cubes (Red, Blue, and Yellow) that can be selected and viewed. I want to be able to select another cube and send the previous one being viewed back to its original position. My plan was to read the name of the entity in the Raycast script and send the other two objects to their original positions. However, I am struggling on calling the other entities from the Raycast script.

var Raycast = pc.createScript('raycast');

var red = this.app.root.findByName('RedCube');
var blue = this.app.root.findByName('BlueCube');
var yellow = this.app.root.findByName('YellowCube');

Raycast.prototype.initialize = function() {
    this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.doRaycast, this);
};

Raycast.prototype.doRaycast = function(mouseEvent){
    var from = this.entity.getPosition();
    var to = this.entity.camera.screenToWorld(mouseEvent.x, mouseEvent.y, this.entity.camera.farClip);
    var result = this.app.systems.rigidbody.raycastFirst(from, to);
    if(result){        
        if(result.entity.name == 'BlueCube'){
            result.entity.setPosition(0,1.5,2.5);
        }
        else if(result.entity.name == 'RedCube'){
            result.entity.setPosition(0,1.5,2.5);
        }
        else if(result.entity.name == 'YellowCube'){
            result.entity.setPosition(0,1.5,2.5);
        }
        this.entity.script.orbitCamera.enabled = true;
    }
};

My error is ’ Cannot read properties of undefined (reading ‘root’)'. I read through the Uncaught TypeError: Cannot read property 'root' of undefined post and I’m still lost. Is there a better way to do this? Thanks for the help : )
Editor: PlayCanvas | HTML5 Game Engine
Code: PlayCanvas | HTML5 Game Engine

First, let me explain the root error.
In the line var red = this.app.root.findByName('RedCube');,
‘this’ refers to the window object. That means we have stepped outside the scope of the PC we want to use. The correct scope is inside the function.

So, it should be like this:

Raycast.prototype.initialize = function() {
    this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.doRaycast, this);
    this.red = this.app.root.findByName('RedCube');
};

Then, Here is my thought on the idea.

I used event.

  1. Add the cube.js script to each cube.
  2. This script subscribes to an event called ‘update:position’.
  3. Use raycasting to get the name or unique ID of the selected entity.
  4. Call the ‘update:position’ event with the accquired ID as a parameter.
  5. Each cube, when the event is triggered, adjusts its position to the center if it matches its ID; otherwise, it resets to the default position.

This, although not the correct answer, is also another idea.
This is a project based on the mentioned idea. I hope it proves helpful.

Project: @3ModelViewer | PlayCanvas | 3D HTML5 & WebGL Game Engine

Thanks so much! That makes a lot more sense. I was really confused about how the scope works, but your explanation helped a lot.

1 Like