[SOLVED] Tweening to World Coordinates Instead of Local Coordinates

Hi all!

Been working with PlayCanvas for a good couple of months now and getting really comfortable with it. Though, I had a question about the tween script found in this tutorial:

http://developer.playcanvas.com/en/tutorials/tweening/

I am able to get it working in my own project very easily, however I would like to tween entities to a specific location on the screen. The example code, however, tweens using the local position:

entity.tween(entity.getLocalPosition()).to({x: 10, y: 0, z: 0}, 1, pc.SineOut);

In my project, the entity in question can appear in various places on the screen but I would like it to always tween to the same world position regardless of where it starts. Is that possible with this tween script? I tried using entity.getPosition instead of entity.getLocalPosition, but the entity doesn’t budge when I try the tween out in that case.

Thanks in advance!

Hello

Sorry for the long delay! So this entity that you are tweening does it change parents or is it always under the same parent?

Hi there, not a problem!

The entity always stays under the same parent. I have done a workaround where I just hard code the positions in local space for each symbol, as there are 9 fixed spots where the entities can start from, so I just needed 9 individual endpoints. Would still be useful to know if there is a way to get around this in case the entities can start in any random position.

Thanks so much!

So if you know where you want the Entity to end up it doesn’t matter where it starts from. Only problem is that you have to use the local position of the entity so if you can just figure out where in local space some ‘world position’ is then you should be fine.

So if my Entity starts at any random local position e.g. x1, y1, z1, then I need to figure out where I want it to go in world space and then convert that to local space. Let’s call the end position in local space x2, y2, z2. Then you can do entity.tween(entity.getLocalPosition()).to({x: x2, y: y2, z: z2); This will tween the entity from wherever it currently is up to the target position.

So how do you convert some arbitrary world position to local space? Well you could do the Math to get the parent’s world transform, invert it and then transform the world position to local space with the inverted transform. Or you could just add a dummy Entity under the same parent as the tweened entity and call setPosition(worldPosition) on the dummy Entity. Then call getLocalPosition() on the dummy entity and you’ll get the target local position to use as the tween target.

1 Like

Ah, dummy entity. Why didn’t I think of that? Very clever, thanks! I will definitely try that approach. I guess I was holding out for something more trivial like a localToGlobal function like what exists in Actionscript 3.

Thanks for the response, much appreciated!!

hey @vaios
do you think that the dummie approach would work also for rotation?
tween works with localRotation, but I work with global Euler angle to rotate my player…
so should I add a box or somethig and rotate it with my player, than use its localrotation as target?

ok I can answer myself: yes it is the same :slight_smile:

1 Like

Here’s some code for the dummy method

Draggable.prototype.tweenTo = function (worldPos) {
    // create dummy if not available...
    if(!this.dummy)
    {
        this.dummy = new pc.Entity();
        this.entity.addChild(this.dummy);
    }

    // kill existing tweens
    if(this.dummy.moveTween) 
        this.dummy.moveTween.stop();

    // black magic... 
    // we're using the dummy to grab the world position, but applying it locally
    // since we can only tween local stuff...
    this.dummy.setLocalPosition(this.entity.getPosition());
    this.dummy.moveTween = this.dummy.tween(this.dummy.getLocalPosition())
        .to(worldPos,0.15, pc.Linear)
    ;
    this.dummy.moveTween.on("update", function(){this.entity.setPosition(this.dummy.getLocalPosition());},this);
    this.dummy.moveTween.start();
};

you don’t even need a dummy entity for that:

var start = this.entityToMove.getPosition();
var dest = this.destEntity.getPosition();

// create an object to tween its properties
var p = {
    x: start.x,
    y: start.y
};
var tween = this.app.tween(p).to({x: dest.x, y: dest.y}, 1, pc.Linear);
tween.on('update', function() {
    this.entityToMove.setPosition(p.x, p.y, start.z);
}.bind(this));
tween.start();

@vaios What is stopping the tween library to work on the world coordinates? getPosition and getLocalPosition return the same type.

Don’t know if this has been solved yet, doesn’t seem like it.

But AFAIK the reason that getPosition() doesn’t work is because the entity.position does not reference any tanglible values. It just seems to be holding arbitrary values calculated from getPosition() while localPosition actually affects the position of the object. So in the tween library when it starts tweening the position values they really don’t do anthing to the objects’ actual position.

For short:
localPosition.set(x, y, z) <— changes object position
position.set(x, y, z) <— does nothing to object position

1 Like