Having trouble finding a direction up and down a sphere

I’ve been working on this for over a week now and can’t really find anything pertaining to my problem. I’ll try and explain it the best I can.

I am working with a sphere prefab created in Unity. I have a player that can run around it. I already have the gravity figured out and the correct rotation for the up vector. What I’m trying to do is determine the forward movement direction based off of the angle of the joystick.

JoystickUp = 0;
JoystickDown = 180;
JoystickRight = 90;
JoystickLeft = 270;
(I will be using every angle in between as well)

I’ve got the movement that I want figured out but that movement is based off of the players forward vector which isn’t what I want. I am going to have a fixed camera that doesn’t rotate with the player like a 3rd person camera would. Basically it will always be pointed at the character much like “Zelda - A Link to the Past” where joystick up moves the player up and down goes down, etc… The camera will rotate with the player around the world but will always look like it’s the same angle.

Below is what I have so far. Notice the "moveDirection = transform.TransformDirection(Vector3.forward); line. I believe this is my biggest problem. Unfortunately I’m not a math or programming wiz and might possibly have more wrong here.

This will get the movement to be correct in the world but I can’t rotate my player to this direction because if I rotate my player the forward vector changes and just makes him spin.

Some of the known variables I have that I think might be useful are:
Vector3 surfaceNormal
sphere.transform.up, left, right etc…

Ok, so trying to get to the short question.

How can I get a move direction based on my joystick angle that will rotate with the spheres curve and that I can always rotate my player without changing this rotation? Pressing the joystick down will always cause the player to go to the bottom of the sphere.

I know there are other things I will run into like what happens when I pass the bottom of the sphere and start going back up but I think I can figure that part out if I can get the correct move direction.

Sorry this is hard to explain. I made a crude image of what I mean. Any help is greatly appreciated.

Thanks,

Artie

10845-problem_image.png

Vector3 GetMoveDirection(Vector2 input)
{
	// Set this as the previous direction so it gets retained if we
	// aren't moving
	Vector3 moveDirection = _moveDirection;
		
	if(_isMoving)
	{	
		// Start over at our current forward direction
		moveDirection = transform.TransformDirection(Vector3.forward);
			
		//Gets the input angle of the joystick in degrees.
		// I Needed to negate the horizontal input to get the correct rotation angle.  
		// Basically the up was down and vice versa.  needed it switched
		float inputAngle = Mathf.Atan2(input.y, -input.x) * 180 / Mathf.PI;
			
		if(inputAngle < 0)
			inputAngle += 360;
			
		// Need to rotate the input angle by -90 degrees to get it
		// into the correct world rotation
		inputAngle -= 90;
						
		// Sets our movement direction based on input. 
		// The angle is based on the joystick angle.
		moveDirection = Quaternion.AngleAxis(inputAngle, transform.TransformDirection(Vector3.up)) * moveDirection;
	}		
		
	// We lerp the new move direction with the previous move direction
	// so we get a smoother transition.
	return Vector3.Lerp(_moveDirection, moveDirection, .5f);
}

Here is a suggestion that might simplify the problem. I might suggest you have a position gameobject and a rotation gameobject

Hierarchy:
Player (position)
- Model (rotation)

So you can rotate model to look at the direction the control is facing and the move player that way you can use horizontal and vertical input items for position then get a rotation based of a Vector created from those inputs.

Here is some code that might lead you in a successful direction or at least you can give me some feedback so I more fully understand your problem.

using UnityEngine;
using System.Collections;

public class SphereMove : MonoBehaviour {
	
	public Transform sphere;
	public float speed = 40.0f;

	void Update () {
		Vector3 v3 = transform.position - sphere.position;
		Vector3 axis = Vector3.Cross (v3,Vector3.down);
		Quaternion q = Quaternion.AngleAxis(Input.GetAxis ("Vertical") * speed * Time.deltaTime, axis);
		v3 = q * v3;
		
		q = Quaternion.AngleAxis(-Input.GetAxis ("Horizontal") * speed * Time.deltaTime, Vector3.up);
		v3 = q * v3;
		
		transform.position = v3 + sphere.position;
		v3 = (transform.position - sphere.position).normalized;
		transform.rotation = Quaternion.FromToRotation(Vector3.up, v3);
	}
}

Attach this to an object sitting on the sphere. Drag the sphere object to the sphere variable.