Apply a new/custom Vector3.up to adjust Player normal

Hello Community,

My player (using CharacterController, no rigidbody) is walking on a large somewhat spherical object (no Terrain, its in “space”) which is slowly rotating on the its three axis. As I walk across this object, I want my Player’s…normal? stay basically perpendicular to the asteroid surface so that I don’t walk/fall off. I’ve done some Internet searches and have this so far:

if (mmo.AsteroidWalking = true) {
			desiredUp =;
			for (int i=0; i <8; i++) {
				Vector3 rayStart =
						+ transform.up
						+ Quaternion.AngleAxis(360 * i / 8.0f, transform.up)
						* (transform.right * 0.5f)
						+ desiredVelocity*0.2f;
				Debug.DrawRay(rayStart, transform.up * -5,;
				// Debug.Log(Physics.Raycast(rayStart, transform.up*-48, out hit, 3.0f, groundLayers));
				if ( Physics.Raycast(rayStart, transform.up*-5, out hit, 10.0f, groundLayers) ) {
					desiredUp += hit.normal;
			Debug.Log (desiredUp);


This shoots out 8 rays in a circle around my character to the “ground” and gets me desiredUp but I don’t know what to do with desiredUp or how to apply this to set my Player upright compared to the surface.

I might have bungled the question title as I’m really learning the terms as I work through this, let me know addtional details are needed. Thank you!

I don’t know if your desiredUp calculation is correct, but you can usually use the following code to align a character with a vector:

transform.rotation = Quaternion.FromToRotation(transform.up, desiredUp) * transform.rotation;

cast a ray down at the ground

Ray ray;
ray.origin = player.transform.position;
ray.direction = player.transform.down;
Raycasthit terrainhit;
physics.raycast(ray,out terrainhit);

Axis = Vector3.Cross(player.transform.down, terrainhit.normal);

Angle = Mathf.Atan2(Vector3.Magnitude(Axis), Vector3.Dot(player.transform.down, -terrainhit.normal));

Angle = Mathf.Rad2Deg * Angle;

player.transform.RotateAround(terrainhit.point, Axis, Angle);

have a nice day

if you need a better understanding of why it works let me know

Thanks both for your ideas.

Using the work done already in
I was able to get this working. To that thread, I added my C# translation. For anyone stumbling on this thread looking for similar info, follow the hyperlink.