Hello, a buddy and I are working on a project!
Essentially, we have a planet that you can rotate around with your camera and zoom in and out of. Our current issue is that our UFO controls are extremely dissatisfying for what we need to accomplish our current goals. What we need is a script to move the UFO spherically around the planet based on mouse pointer position on the spherical surface (basically, the UFO needs to follow your mouse while it’s on the spherical surface). Right now we have a controller designed for first person and it does not work well for the scenario described. Here is a included image of what we are dealing with at the moment. We need the ship to stay a particular distance from the planet while also rotating around it based on mouse location.
Will it be the only ship?
If it’s a small PC game, you have a lot of room to breathe. You can raycast down, get the normal of the mesh face, and move the ship’s up vector to it. These are all terms you need to be familiar with to make this kind of game.
While that’s a working Unity configuration that could be improved and expanded it isn’t the most efficient way of doing this, which would probably involve some simple math (I’m all logic, no math ).
Use the Slerp function (spherical linear interpolation). The ship’s position is the starting point, the mouse position is the target point, the percentage (the third parameter to any lerp) is how far between the two points to move (so it’ll depend on framerate via Time.deltaTime and the speed you want the ship to move).
Treat the mouse and ship position as if they’re on the same sphere (“unit” sphere, 1.0 units in diameter) so you don’t involve altitude differences in your slerp, then multiply the resulting up vector to set the ship’s altitude at the new position.
You probably also want some kind of RotateTowards lerp in the mix so the ship turns (around the ship’s up vector) to face the mouse pointer position.
Hi guys! Thanks so much for the quick responses! I’m having trouble figuring out what you mean as to align the ship using raycast. We have objects using AI on the surface via raycast but I don’t know how we could have the ship be a certain distance from the planet and not be stiff and rotate to the surface via raycast… Could you show me how you would do it?
I have this so far but it keeps sucking towards the camera and going away from the planet when we move our mouse away! Any way to fix this?
using UnityEngine;
using System.Collections;
public class MoveToMousePosition : MonoBehaviour
{
public Camera cam;
public Transform target;
public bool useRaycast = false;
public LayerMask maskFilter;
private RaycastHit hit;
private void Update()
{
if(Physics.Raycast(cam.ScreenPointToRay(Input.mousePosition), out hit, maskFilter))
{
target.position = hit.point;
}
}
else
{
target.position = cam.ScreenToWorldPoint(Input.mousePosition + Vector3.forward * distanceToCamera);
}
}
Thanks for all of the help so far btw
As another alternative you can simply parent the UFO to an empty GameObject at the centre of your sphere. Then you can move anywhere you like by just rotating around the empty GameObject.
That wouldn’t work because the ship needs to be at the exact point that the mouse is at on the planet (look at the .gif for reference). https://giphy.com/gifs/l2SpRjYDvwLbUm2nS You can also see an example of the issues described in the .gif
BoredMormon’s solution is probably the most efficient option. An alternative would be to set up planetary gravity and rotate the ship so its up axis is aligned towards the center of the planet. You will of course need a way to keep the ship in the air otherwise it will crash into the planet.
Pseudocode:
public class PlanetBehaviour : MonoBehaviour
{
public float Gravity;
public Rigidbody ShipRigidbody;
void Update()
{
if (ShipRigidbody == null) return;
//get the direction from the center of the planet to the ship
Vector3 direction = (ShipRigidbody.position - transform.position).normalized;
//apply gravity
ShipRigidbody.AddForce(direction * Gravity);
//align the ship
ShipRigidbody.MoveRotation(ShipRigidbody.rotation * Quaternion.FromToRotation(ShipRigidbody.transform.up, direction));
}
}
While the gravity approach might be entertaining to write, I’m not sure I’d recommend it to somebody who doesn’t even know about lerp yet! That’s a rabbit-hole the poor dude will never return from…
I understand that that would fix the ship’s position on the planet but how would that help with the issues shown in the gif? When the mouse is off the planet the ship moves off the planet and when the mouse is close to the camera the ship glitches towards the camera. Please review the gif for reference
Use a RaycastHit to check whether the mouse is over the planet’s Collider. You likely already have this depending on how you’re tracking mouse position (since the GIF demonstrates your code is partially working now).
The close-to-camera thing is some side-effect of your code, I doubt anybody is going to be able to guess what’s wrong.
I still think slerp is the easiest option here. Normalize the UFO position to a unit-sphere distance from the center of the planet, normalize the mouse hit coordinates to a unit-sphere distance (also from the center of the planet), those are your Vector3 start/stop points for the slerp, set the step value (speed based on frame timing in Time.deltaTime) to get the new UFO position, multiply the new position’s .up by the desired altitude, and do it again on the next frame. That’s your pseudo coded answer in a nutshell.
Thank you for the info but i’m confused on how to do that… is there anyway you could show me what you mean?
I’ve drank too many beers to work on my real project tonight, so I’ll whip up an example for you.
Thanks man!
Sorry, sidetracked by dinner.
Here ya go. I found a couple minor shortcuts but this both positions the ship right and rotates it correctly. Read the comments for info on using layers and/or tags for raycast/collider interaction (I bet that was the source of your weirdness when the mouse was “close to the camera” – the ship was between the mouse and the planet.)
Hope it helps.
2748012–198134–Assets.zip (12.3 KB)
OMG! THANK YOU! I had been working on this for two days! Thank you for all the help my drunk friend +1
No problem. Post more about your game as you progress. I assume you get to abduct the cows, or possibly suck out their bones, which seems fairly awesome.
Ok, will do!