I know there are already some threads about this, but my problem isn't exactly with the algorithm itself. I was able to use RayCast and get the ground normal, using it to store the rotation necessary to align to the ground in a quaternion using:
slopeRotation = Quaternion.FromToRotation (transform.up, hit.normal);
Where hit.normal is the normal of the ground. After this, I check whether the player is moving (the user is moving the joystick axis) or standing still. If it's standing still, I align it with the ground using:
transform.rotation = Quaternion.Slerp(transform.rotation,slopeRotation * transform.rotation,10*Time.deltaTime);
When the player is moving, I rotate using:
transform.rotation = Quaternion.Slerp (transform.rotation,slopeRotation *camRotation*movementRotation , 10 * Time.deltaTime);
Where camRotation is simply the rotation of the MainCamera(a third person one) on the Y axis and movementRotation is the rotation of the joystick axis, also on the Y axis, calculated using:
movementRotation = Quaternion.LookRotation (new Vector3(Input.GetAxis ("Horizontal"), 0, Input.GetAxis ("Vertical")));
camRotation = Quaternion.Euler (0, cam.transform.rotation.eulerAngles.y, 0);
Although the code above makes sense in my head, it doesn't work as expected, as seen in the picture below:
As you can see, it works fine when you're standing still, which means that the ground normal and the slopeRotation are correctly calculated. When the player moves though, the combination of all the quaternions seems to cause some kind of problem that makes the player slightly deviate from the correct rotation. It might be worth noting that camRotation and moveRotation also work completely fine on their own, so the player moves correctly according to both the rotation of the camera and of the joystick, both on the floor and on ramps.