Modifying Gravity for Local Player

Hello everyone - I’m working on a personal project that involves a character moving around a horizontal cylinder while moving in a set direction. The gravity for the character needs to be constantly pulling them towards the center of the cylinder (which does appear to be working correctly), but when I move the character along their forward vector, I am seeing it ‘slide’ either farther up (+Y) or down (-Y) the cylinder.

If I remove the forward movement, the character stays oriented correctly and doesn’t slide in either direction (which is what I would expect/want). As soon as I do though…well, hence the problem.

The object’s rigidbody has all rotational axis locked, and I am not using gravity.

Any insight or help would be appreciated.

Thanks!

Code Snippet:

    //----------------------------------------
    // Class Variables
    //----------------------------------------
    // Private
    private float _RotationSpeedMod = 1f;
    private float _RotationSpeedBase = 120f;
    private float _RotationSpeedMax = 165f;
    private Vector3 _VecGravity = new Vector3();
	private Transform _MyTransform;
	
    // Public
	public float _RotationSpeed = 0;
	public float _Gravity = -9.81f;
	public float _MovementSpeed = 10.0f;
	public float _MaxVelocity = 2.0f;
	
	// Awake
	void Awake()
	{
		_MyTransform = transform;	
	}

	// Update is called once per frame
	void Update ()
    {
		// DeltaTime Value
		float DeltaTime = Time.deltaTime;

		// Rotate Left
        if (Input.GetKey(KeyCode.LeftArrow))
        {
			transform.RotateAround(Vector3.zero, Vector3.right, DeltaTime * _RotationSpeed );
				
            _RotationSpeed += _RotationSpeedMod;
            if (_RotationSpeed > _RotationSpeedMax)
            {
                _RotationSpeed = _RotationSpeedMax;
            }
        }
		// Rotate Right
        else if (Input.GetKey(KeyCode.RightArrow))
        {
			transform.RotateAround(Vector3.zero, Vector3.right, DeltaTime * -_RotationSpeed );
			
            _RotationSpeed += _RotationSpeedMod;
            if (_RotationSpeed > _RotationSpeedMax)
            {
                _RotationSpeed = _RotationSpeedMax;
            }
        }
        else
        {
            _RotationSpeed = _RotationSpeedBase;
        }
	}

	// Physics Update
	void FixedUpdate()
	{
		// DeltaTime Value
		float DeltaTime = Time.deltaTime;
		
		// Compute Gravity Vector
		Vector3 VecUp = _MyTransform.up;
		Vector3 VecFwd = _MyTransform.forward;
		Vector3 VecTemp = new Vector3();
		float GravityRate = _Gravity * DeltaTime;
		float MovementRate = _MovementSpeed * DeltaTime;
		
		Vector3 VecGravity = new Vector3(VecUp.x * GravityRate, VecUp.y * GravityRate, VecUp.z * GravityRate);	
		Vector3 VecMovement = new Vector3(VecFwd.x * MovementRate, VecFwd.y * MovementRate, VecFwd.z * MovementRate);

		Debug.Log( "VecGravity: " + VecGravity );
		Debug.Log( "VecMovement: " + VecMovement );
		
		VecTemp = VecMovement + VecGravity;
		//VecTemp = VecGravity;
		
		Debug.Log( "VecTemp: " + VecTemp );
		
		_MyTransform.rigidbody.velocity += VecTemp;
		
		Debug.Log( "Vel: " + _MyTransform.rigidbody.velocity );
			
		// Limiter
		if( _MyTransform.rigidbody.velocity.magnitude > _MaxVelocity )
		{
			VecTemp = _MyTransform.rigidbody.velocity;
			VecTemp.Normalize();
			VecTemp.Set( VecTemp.x * _MaxVelocity, VecTemp.y * _MaxVelocity, VecTemp.z * _MaxVelocity );
			_MyTransform.rigidbody.velocity = VecTemp;
		}
		
		Debug.Log( "Magnitude: " + _MyTransform.rigidbody.velocity.magnitude );		
	}

I think the problem is the calculation of your vectors VecUp and Fwd. You’re using the player’s transform, you should use [closest point on cylinder’s axis from the player] → the player’s pos, for the up.

Also, you should use Time.fixedDeltaTime in FixedUpdate.