Stopping Rigidbody Movement/Rotation Around A Sphere

So what I am trying to do is simple, have an object move around the outside of a sphere and stop when it comes in contact with another object/wall. I have the movement working and I will provide that script below, but my problem is that when the moving object comes into contact with another, even when the force stops, it moves and rotates the object around.

Here is a pic of my current set up: Imgur: The magic of the Internet

Here is my current code:

[RequireComponent(typeof(Rigidbody))]
public class SphereMotor : MonoBehaviour
{
    public Vector3 eulerAngleVelocity;
    public Rigidbody rb;
    private float speed = 1f;
 
    void Start() {
        rb = GetComponent<Rigidbody>();
    }
 
    void Update()
    {
        if(Input.GetKey(KeyCode.W))
        {
            Quaternion deltaRotation = Quaternion.Euler(speed,0,0);// * Time.deltaTime);
            rb.MoveRotation(rb.rotation * deltaRotation);
         
        }
     
        if(Input.GetKey(KeyCode.S))
        {
            Quaternion deltaRotation = Quaternion.Euler(-speed,0,0);// * Time.deltaTime);
            rb.MoveRotation(rb.rotation * deltaRotation);
         
        }
 
    }
}

Edit: I figured I should mention I have this code attached to an empty game object in the middle of the sphere on screen that the object is a child of.

Any advice you could give would be greatly appreciated!

ayy I am doing the same thing. Except I am getting Gimbol Lock…

Like it freezing the Rigidbody in space and you not being able to move it? I’ve run into that problem as well. Would you mind posting your code? Maybe we can combine forces and figure this out.

1 Like

TerrainMotor is an abstract so I can have AI / Projectiles move about weird terrain.
TerrainMotor .cs

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
[RequireComponent(typeof(Rigidbody))]
public abstract class TerrainMotor : MonoBehaviour {
    [SerializeField] protected float m_speed = 10.0F; // Max Speed
    [SerializeField] protected float m_acceleration = 1.0F; // Acceleration
    [SerializeField] protected float m_checkDistance = 1.0F; // Length of Ray cast

    protected Vector3 m_direction = Vector3.zero; // Cache direction
    protected Rigidbody m_rigidbody; // Rigidbody

    protected virtual void Awake() {
        this.m_rigidbody = this.GetComponent<Rigidbody>();
    }

    protected virtual void FixedUpdate() {
        Ray ray = new Ray(this.transform.position, -this.transform.up); // Ray at current position facing down relative to the Transform
        RaycastHit hit; // RaycastHit reference

        // Check if were are on anything...
        if(Physics.Raycast(ray, out hit, this.m_checkDistance)) {
            // Turn gravity off so we can move around oriented terain.
            this.m_rigidbody.useGravity = false;

            // Causes Gimbol Lock when on the side of a sphere
            this.transform.rotation *= Quaternion.FromToRotation(this.transform.up, hit.normal);

            // Velocity in the direction relative to local space.
            Vector3 velocity = this.Direction * this.m_speed;
            // Do not change the Y velocity
            velocity.y = this.m_rigidbody.velocity.y;
            // Accelerate to the new velocity
            this.m_rigidbody.velocity = Vector3.Lerp(this.m_rigidbody.velocity, velocity, this.m_acceleration);

            // Add a force opposite to the normal so we can stay on any terrain surface
            this.m_rigidbody.AddForce(-hit.normal, ForceMode.Impulse);
        } else {
            // Turn gravity back on
            this.m_rigidbody.useGravity = true;

            // Rotate back to normal rotation
            this.transform.rotation = Quaternion.Lerp(this.transform.rotation, Quaternion.identity, 0.1F);
        }
    }

    protected virtual void Update() {
#if UNITY_EDITOR
        Debug.DrawRay(this.transform.position, -this.transform.up * this.m_checkDistance, Color.red);
#endif
    }

    protected virtual Vector3 Direction {
        get {
            return this.transform.TransformVector(this.m_direction);
        }
    }
}

An Example controller for testing purposes
ExController.cs

using UnityEngine;


using System.Collections;

public class ExController : TerrainMotor {
    [SerializeField] protected string m_horizontal = "Horizontal";
    [SerializeField] protected string m_vertical = "Vertical";

    protected override void Update() {
        base.Update();

        this.m_direction = new Vector3(Input.GetAxis(this.m_horizontal), 0.0F, Input.GetAxis(this.m_vertical));
    }
}

I included a .unitypackage so you can look at the scene.

2367928–160797–Sphere Movement.unitypackage (6.95 KB)

So I tried loading your package up but cant seem to get it working, it might be because I am using Unity 5 and this was made in 4.Ill try and mess around with it some more today and ill update this page with what I find.

Really? I am using Unity 5.1.1F1

oh man really? Then I have no idea why it wasnt working, it was trying to open in Unity 4 for me but ill force it into 5 and give it another go

Edit: Unfortunately I wasnt able to find a solution to our problem