Is this possible?

Hello all,
I am working on a game that deals with characters on spheres, is there a way to get the angle of the plane/whatever us underneath of it? Like if it is on a sphere it would auto-set its rotation to match the angle of the sphere.

Thanks for any help you can give!

Of course. If the sphere has a center C and the character is at position P, the vector (P-C) is a normal of the plane.

You could also probably just use entity.LookAt to make your character face the C.

Can you explain that further?

What does that mean?

Chat GPT explains it this way:

To handle characters on a sphere and automatically set their rotation to match the surface in PlayCanvas, here’s a structured approach:

1. Use the Sphere’s Normal for Orientation

  • The vector (P - C), where C is the center of the sphere and P is the position of the character, represents the normal of the plane at the character’s location on the sphere.
  • This normal can be used to orient the character to “stand” on the sphere by aligning the character’s up vector with this normal.

Implementation:

javascript

Copy code

var characterPosition = characterEntity.getPosition();
var sphereCenter = sphereEntity.getPosition();

// Get the normal vector (P - C)
var normal = new pc.Vec3().sub2(characterPosition, sphereCenter).normalize();

// Create a lookAt matrix that uses this normal
var up = normal.clone();  // Align character's up with the normal
characterEntity.lookAt(sphereCenter, up);

This aligns the character so that its “up” vector is pointing along the normal of the sphere. You can adjust this approach to suit specific game mechanics.

2. Use entity.lookAt()

  • If you want to simplify things, you can directly use entity.lookAt to make the character face the center of the sphere (C). This ensures the character will be correctly oriented to the surface of the sphere as well.

javascript

Copy code

characterEntity.lookAt(sphereCenter);

By using lookAt, the character will rotate to face the center of the sphere, ensuring it stays “upright” relative to the surface. However, depending on the model and gameplay needs, you might need to tweak the character’s forward direction or up vector.

3. Combine LookAt and Additional Rotation for Movement

If the character needs to move across the surface while maintaining the proper orientation:

  • Use the lookAt method as shown, then adjust the character’s forward direction or heading based on input or other factors (e.g., where it is moving to on the sphere).

javascript

Copy code

// Make character face the center and rotate based on movement
var targetPosition = characterEntity.getPosition();
targetPosition.x += moveX;  // Input-based movement example
targetPosition.z += moveZ;

characterEntity.lookAt(targetPosition, normal);  // Orient based on movement while matching sphere's normal

4. Handling Spherical Movement

To smoothly move the character across the sphere surface while maintaining correct rotation:

  • Calculate the tangent vector for movement (the direction on the sphere’s surface).
  • Update the character’s position along this tangent while continuously aligning the normal with the lookAt method to maintain orientation.

Summary:

  • Use (P - C) as the normal to orient the character.
  • Use lookAt to make the character face the center of the sphere for simple orientation.
  • If movement is involved, combine the normal-based orientation with tangent-based movement.

These approaches should allow you to manage the character’s rotation and movement naturally on a spherical surface in PlayCanvas.

Thanks! I’ll test this out when I can and get back to you!

Sorry I took so long, ive had a busy couple of days.

Here is the script I am using so far:

var TestGrav = pc.createScript('testGrav');
TestGrav.attributes.add('characterEntity',{type:"entity"});
TestGrav.attributes.add('sphereEntity',{type:"entity"});

var characterPosition = new pc.Vec3();

var sphereCenter = new pc.Vec3();

// Get the normal vector (P - C)
var normal = new pc.Vec3().sub2(characterPosition, sphereCenter).normalize();

// Create a lookAt matrix that uses this normal
var up = normal.clone();  // Align character's up with the normal


var targetPosition = new pc.Vec3();

// initialize code called once per entity
TestGrav.prototype.initialize = function() {
};

// update code called every frame
TestGrav.prototype.update = function(dt) {
    characterPosition = this.characterEntity.getPosition();
sphereCenter = this.sphereEntity.getPosition();

// Get the normal vector (P - C)
normal = new pc.Vec3().sub2(characterPosition, sphereCenter).normalize();

// Create a lookAt matrix that uses this normal
up = normal.clone();  // Align character's up with the normal
this.characterEntity.lookAt(sphereCenter, up);
this.characterEntity.lookAt(sphereCenter);

//////////////////
/////MOVEMENT/////
//////////////////

if(this.app.keyboard.isPressed(pc.KEY_W)){
targetPosition.x += 1;
this.characterEntity.lookAt(targetPosition, normal);  // Orient based on movement while matching sphere's normal
};

};

// uncomment the swap method to enable hot-reloading for this script
// update the method body to copy state from the old instance
// TestGrav.prototype.swap = function(old) { };

// learn more about scripting here:
// https://developer.playcanvas.com/user-manual/scripting/

And it is kinda scuffed…
(Note, when the capsule is moving W is being pressed)

Im not used to these APIs so any help would be beneficial