[SOLVED] Set position by script

I try to put my player back with the script, but when the player looks the other way, it moves on the x-axis instead of the z-axis. I have tried using on local but so far I am not getting the right result.

this.entity.setPosition(new pc.Vec3(this.entity.getPosition().x, this.groundPoint.y, this.entity.getPosition().z + 1));

Does the player have dynamic rigidbody? If so, you will need to use rigidbody teleport. Either that or you have some logic that handles movement based on other variables that have not been reset.

No the player entity itself has no rigidbody. A child has a kinematic rigidbody.
Maybe I rotate the player on a wrong way earlier in the script.

When the player is start climbing I use this code:

    this.entity.setPosition(new pc.Vec3(this.climbPoint.x, player.getPosition().y+0.5, this.climbPoint.z));

and when the player is stop climbing i try to use this code, but that gives a wrong result:

    this.entity.setLocalEulerAngles(this.entity.getEulerAngles().x, this.entity.getEulerAngles().y + 180, this.entity.getEulerAngles().z);
    this.entity.setPosition(new pc.Vec3(this.entity.getPosition().x, this.groundPoint.y, this.entity.getPosition().z + 1));

What does the code of the player movement look like? What does it depend on to decide what direction to move in?

    this.entity.setLocalEulerAngles(this.entity.getEulerAngles().x, this.entity.getEulerAngles().y + 180, this.entity.getEulerAngles().z);

This looks odd as well. Sounds like you are trying to rotate 180 degrees, if so as you are getting the euler angles from global space, you should also set them in global space (use this.entity.setEulerAngles).

However, as the euler angles may flip, I would use rotate instead https://developer.playcanvas.com/en/api/pc.Entity.html#rotate

Yes that is what I do, so if the player stops climbing because he is reaching the ground I rotate the player with his back to the wall and a little bit from the wall (to prevent the player from immediately climbing again without this being the intention).

So with the first lines of code I set the player on the wall by start climbing and with the last line of code I set the player back on the ground by stop climbing.

I have the problem also by start climbing if I want to use an offset.

    this.entity.setPosition(new pc.Vec3(this.climbPoint.x, player.getPosition().y + 0.5, this.climbPoint.z + 0.1));

With the offset 0.1 on the z-axis I get an offset on the x-axis in the game (when the y rotation of the entity is 90 or -90).

So right now it’s only working as I want when you reach the wall from the front.

I couldn’t get the player to climb properly in the game when I run it so I’m just looking at the code for moment.

    this.entity.setPosition(new pc.Vec3(this.climbPoint.x, player.getPosition().y+0.5, this.climbPoint.z + 0.1));

The X and Z position should be relative to the climable object rotation rather than world position off the raycast.

You can do this by getting the raycast point off the climbable entity and then offset it along local Z/-Z axis (in this case) of the climable.

Here’s an example that moves the blue marker 0.2 units away from the wall based on the normal of the raycast intersection.

In fact, thinking about it, you could use the normal to rotate the player in the correct direction based off the normal instead of having 4 collision volumes per climbable cube. :thinking:

Where? :yum:

That sounds like a better way indeed. Is there an example available somewhere how to do that?

Oops: https://playcanvas.com/project/687519/overview/climable-example

I see if I can put something together.

Okay, that would be nice!

Updated example: https://playcanvas.com/editor/scene/923457

Edit: there’s still a bug with this so bear with me here
Edit2: fixed!

1 Like

Good morning @Yaustar,

I implanted your example in my project and this works great! Much better than how it was. Thank you so much for that!

Only for ending the climbing I still have the same problem. I try to use the position and rotation of the hitMarkerEntity (in my case climbPoint) to put the player back on the ground but the offset only takes place on the good axis and in the good direction if I approached the object from the front.

this.entity.setPosition(new pc.Vec3(this.climbPoint.getPosition().x, this.groundPoint.y, this.climbPoint.getPosition().z + 1));

It’s the same problem as the climbing and should use a similar solution. It’s using absolute world coordinates and offsets when it should be positioned relative to the orientation of the wall and ground.

And if I do this:

this.entity.setPosition(new pc.Vec3(this.entity.getPosition().x, this.groundPoint.y, this.entity.getPosition().z + 1));

At what axis will the +1 be set if the rotation of my enity is (0, 90, 0)?

Little tip - you’re needlessly calling getPosition twice. You should be careful to minimize calls to the API. And you are needlessly creating a pc.Vec3. So:

var pos = this.entity.getPosition();
this.entity.setPosition(pos.x, this.groundPoint.y, pos.z + 1);

This code is functionally equivalent but much faster.

Oke, thank you @will!

var pos = this.entity.getPosition();

Do I need to use this before every task or can u call this once in the intialize?

It depends on whether you expect it to change over time. If it’s a stationary entity, sure, you could cache the position in the initialize function. But if the entity changes its position over time, then you’ll need to call getPosition whenever you need the latest position.

1 Like
this.entity.translateLocal(0, 0, 1);

This moves the entity backwards on the z-axis according to the rotation of the entity. Why isn’t that with set position?

Sorry, I don’t understand the question. Can you rephrase please?