So I made this script to rotate the normals of any object with this script to match the normals of the closest surface beneath the object. The desired effect would not be too dissimilar from Super Mario Galaxy, however rather than a gravitational effect based on large planetoids pulling you to them, its more based on the normals of the surface beneath the player. More like how sonic can run up walls if he has enough velocity and there is a ramp. In this case, scratch the velocity requirement, its all about if the surface to be traversed has an appropriate angle.
For example
The player is the cube, the blue arrow is the player’s up normal, and the purple is the surface’s normal. The script changes the blue arrow to match the purple arrow. The player will rotate and have his gravity changed based on the normals of the surface as long as the surface’s normals and the current surface’s normals are less than 45 degrees (thus the player wont run up 90 degree angled walls, fall off a surface and rotate to the back of the surface, etc) However, there was a problem with maintaining velocities. For example:
The player would jump by adding velocity, then shortly after the gravity force would pull the player down on its negative upward normal. So jumping on a flat plane works fine, but trying to jump up a curve hardly does. The player would jump, rotate mid air, and then slightly hit the ground with the front bottom of the cube/player.
Not only this, but when objects are rotated 90 degrees, the objects spin or slowly drift downward as if it is still being affected by gravity on the Vector3.up rather than transform.up.
I’ve been working on reworking this script over and over, and so far all this script does is rotate objects according to normals. How can I do what Im trying to do and add gravity that doesn’t freak out or cause objects to randomly spin or rotate, and maintains a jump rather than cause one to jump into the floor?
Here is the current script. If I need to post any more information let me know.
using UnityEngine;
using System.Collections;
public class LocalGravity : MonoBehaviour {
private const float UGD = 20f; //universal gravitational distance
private const float UGA = 0.8f; //universal gravitational angle
private Vector3 pointHit;
private RaycastHit objHit;
private float originalDistanceToSurface;
private float newDistanceToSurface;
void Update () {
Debug.DrawRay(transform.position, transform.up * 10f, Color.green);
Debug.DrawRay(transform.position, -transform.up * 20f, Color.red);
Debug.DrawRay(transform.position, pointHit * 10f, Color.yellow);
Debug.DrawRay(objHit.transform.position, objHit.transform.up * 10f, Color.magenta);
Debug.Log("or " + originalDistanceToSurface + " | new " + newDistanceToSurface);
}
void FixedUpdate(){
Physics.Raycast(transform.position, -transform.up, out objHit, UGD); //TO DO: SPECIFY LAYER MASK = SUPER IMPORTANT
pointHit = objHit.normal;
originalDistanceToSurface = (pointHit - transform.position).magnitude;
if(Vector3.Dot(transform.up, pointHit) > UGA && transform.up != pointHit){
Quaternion newRot = Quaternion.FromToRotation(transform.up, pointHit) * transform.rotation;
transform.rotation = Quaternion.Slerp(transform.rotation, newRot, Time.deltaTime * 16f);
newDistanceToSurface = (pointHit - transform.position).magnitude;
if(newDistanceToSurface < originalDistanceToSurface){
Debug.Log("true");
transform.position += transform.up * (1/(originalDistanceToSurface - newDistanceToSurface));
}
}
}
}

