[SOLVED] Point an empty entity with a sprite child towards mouse

So basically im making a 2d game and I have an empty object called pivot and I want it to turn towards the camera and there is a sprite under it. This pivot object is also under an empty called Player. I tried implementing something but the sprite is just gone when i press play.

here is the code:

var RotateToMouse = pc.createScript('pivot');


RotateToMouse.prototype.initialize = function() {
    this.camera = this.app.root.findByName('Camera'); 
};


RotateToMouse.prototype.update = function(dt) {
    if (!this.camera) return;

 
    var pivotPos = this.entity.getPosition();


    var pivotScreen = this.camera.camera.worldToScreen(pivotPos);

   
    var mouseX = this.app.mouse.x;
    var mouseY = this.app.mouse.y;

   
    var dx = mouseX - pivotScreen.x;
    var dy = mouseY - pivotScreen.y;

   
    var angle = Math.atan2(dy, dx);

  
    this.entity.setEulerAngles(0, 0, pc.math.RAD_TO_DEG * angle); 
   
};

Hi @existism and welcome!

If the sprite disappears when rotating, it could be worth trying the Flip X / Flip Y options on the Sprite component. Rotating the parent can sometimes cause unexpected mirroring.

If this helps, the code will likely need a small adjustment (instead of relying on the flip option) so it also stays correctly oriented in the editor.

It might also help to temporarily add a simple render primitive (box, cylinder, etc.) to the pivot, to better see how it is rotating.

I tried both your suggestions but it didn’t seem to work. would be nice if I could go to editor while playing like unity or something.

What are you actually trying to achieve? Your explanation and the code seem to contradict each other: you mention rotating toward the camera, but the script rotates the pivot toward the mouse position.

If possible, could you share the project or a small repro scene?

oh wait I didnt realize I said camera I meant mouse originally, and yeah ill get a scene

alright tell me if this link works project

Some of the variables in your original script are undefined.
It’s always a good idea to verify this in the browser console (press F12 on Windows), for example:

console.log(this.app.mouse.x);

Below is a working version based on the same idea as your original script, but using the PlayCanvas API correctly to read mouse input and keep everything in the same coordinate space.

var Pivot = pc.createScript('pivot');

Pivot.prototype.initialize = function () {
    this.cameraEntity = this.app.root.findByName('Camera');

    this.mouseX = 0;
    this.mouseY = 0;

    this.app.mouse.on(pc.EVENT_MOUSEMOVE, function (event) {
        this.mouseX = event.x;
        this.mouseY = event.y;
    }, this);
};

Pivot.prototype.update = function () {
    if (!this.cameraEntity) return;

    var camera = this.cameraEntity.camera;
    var pivotPosition = this.entity.getPosition();

    var mouseWorldPosition = new pc.Vec3();
    camera.screenToWorld(this.mouseX, this.mouseY, pivotPosition.z, mouseWorldPosition);

    var deltaX = mouseWorldPosition.x - pivotPosition.x;
    var deltaY = mouseWorldPosition.y - pivotPosition.y;

    var angleDegrees = Math.atan2(deltaY, deltaX) * pc.math.RAD_TO_DEG;

    this.entity.setEulerAngles(0, 0, angleDegrees - 90);
};

By the way, since the rotation depends entirely on mouse input, you can also move this logic into the EVENT_MOUSEMOVE handler instead of recalculating it every frame in update(). This keeps the code simpler and avoids unnecessary per-frame work.

var Pivot = pc.createScript('pivot');

Pivot.prototype.initialize = function () {
    this.cameraEntity = this.app.root.findByName('Camera');

    this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
};

Pivot.prototype.onMouseMove = function (event) {
    if (!this.cameraEntity) return;

    var camera = this.cameraEntity.camera;
    var pivotPosition = this.entity.getPosition();

    var mouseWorldPosition = new pc.Vec3();
    camera.screenToWorld(event.x, event.y, pivotPosition.z, mouseWorldPosition);

    var deltaX = mouseWorldPosition.x - pivotPosition.x;
    var deltaY = mouseWorldPosition.y - pivotPosition.y;

    var angleDegrees = Math.atan2(deltaY, deltaX) * pc.math.RAD_TO_DEG;

    this.entity.setEulerAngles(0, 0, angleDegrees - 90);
};

You’d still want the update() approach if the camera or entity moves continuously, or if you plan to add smoothing, but for direct mouse-driven rotation this is usually the cleaner option.

This is great. Thank you so much.

1 Like