- Home /
Rotate to ground normal and steering direction for a Bicycle?
Hello, so I'm trying to make a bicycle script but I am having trouble with the rotation. I want to rotate the bicycle to my steering direction (where my Front Wheel is facing) while also adjusting itself in Angle to whatever surface the bicycle is on. I have the following code:
Vector3 smoothNormal = Vector3.up;
void RotateToSteerAndNormal()
{
float rayDistance = 3f;
RaycastHit hit;
Vector3 steerDirection;
Vector3 normal = Vector3.up;
if (Physics.Raycast(frontWheel.position, -Vector3.up, out hit, rayDistance))
{
normal = hit.normal;
}
// Smooth out the new Normal target
smoothNormal = Vector3.Lerp(smoothNormal, normal, 3f * Time.deltaTime);
// Set Steering Direction
steerDirection = frontWheel.position - frontWheelCOM.position;
steerDirection.y = 0; // zero y to keep only the horizontal direction
// Set Rotations
var normalRotation = Quaternion.FromToRotation(Vector3.up, smoothNormal);
var steerRotation = Quaternion.FromToRotation(Vector3.forward, steerDirection);
// Combine and apply rotations
transform.rotation = steerRotation * normalRotation;
}
It works for steering, but the Angle adjustment to the ground normal is bugging out. Here's a video GIF I converted of the problem in action:
Does anyone know how this should be done properly? I need a solution that doesn't affect the steering itself, while still angling to the ground normal as you'd expect.
Try reversing the order of operations on the last line:
transform.rotation = normalRotation * steerRotation;
That's what I tried originally. It fixes the wrong ground normal orientation, but for some reason it makes the bicycle "slide" away while driving straight onto the ramps. Look here, each time I'm only pressing forward and it slides off by itself:
Hmmm... that's definitely closer.
Can you please explain this line of code?:
steerDirection = frontWheel.position - frontWheelCO$$anonymous$$.position;
That's the only thing I can see that may cause the sliding, depending on what those two transforms represent.
Answer by toddisarockstar · May 04, 2017 at 10:51 PM
have you tryed just setting up colliders and rigidbody restraints to let the physics engine naturally do its work to bring the back wheel down?
i would start by putting two empty child object on both the bottom of the front wheel and back wheel for location reference near where they should be touching the ground.
and then raycast down from each tire to get two points. then calculate the bikes x axis from the two points!
this would be much more accurate than using the grounds normal at one point if the gound has different curves underneath.
Sorry this is untested cause i dont have a bike but this would be the Concept im thinking of:
Transform frontWheel;
Transform backWheel;
Vector3 vf;
Vector3 vb;
float myX;
// get two points under EACH tire
RaycastHit hit;
if (Physics.Raycast(frontWheel.position, -Vector3.up, out hit))
{vf = hit.point;}
if (Physics.Raycast(backWheel.position, -Vector3.up, out hit))
{vb = hit.point;}
//get Vector3 direction between two points
vf = vf - vb;
// convert to angle an get the X axis
myX = Quaternion.LookRotation(vf).eulerAngles.x;
print ("the X rotation of your bike in eular angles should be : " + myX);
Hi Todd, leaving it to Rigidbody/Physics doesn't really work, because if not all 3 Axis are restrained it will easily fall over etc. while leaving only the X Axis unrestrained will lead to jitters since the other Axis still are constrained but want to apply other values to themselves.
I like that you try to average out the two wheels ins$$anonymous$$d of just the one with your code, but I don't see how you'd intend to use it? It doesn't factor in my steering rotations and doesn't get applied to anything. Could you be more specific?
EDIT: I figured it out. This works to apply it:
Quaternion finalRotation = Quaternion.LookRotation(steerDirection);
Vector3 finalEuler = finalRotation.eulerAngles;
finalEuler.x = myX;
finalEuler.z = 0;
finalRotation = Quaternion.Euler(finalEuler);
transform.rotation = finalRotation;
It now does everything as it's supposed to do and I'll mark your answer as accepted. Thank you very much!
Sorry i didn't get back to you sooner. I just had a moment to throw the idea out there at the time. It's cool you got it working. eventually I'm sure you will want the bike to jump of edges or jump ramps. You also might want to think of limiting the distance of the downward raycast so that if the bike or one of it's wheels is ever airborne, It wont keep responding to the ground!
also I noticed in your video that the pivot point of your bike is in the middle of the frame. causing the back wheel to slide slightly left and right when turning. in reality this wouldnt happen with the real phyisics of a bike. The y pivot point of the bike would actually be the back wheel and the front of the bike swings around it based on the steering.
watch a video of someone riding a bike slowly and turning very sharp. The frame is actually rotating around the back wheel!
Of course this would be opposite for something like a fork truck that has the steering in the back. then the back would swing.
Your answer
Follow this Question
Related Questions
How to use quaternions to apply an offset to a rotation to calibrate a controller 1 Answer
2D animation : problem with rotation interpolation 1 Answer
Look at rotation at a moving object while moving (C#)(2D) 3 Answers
Where can I learn about quaternions and how to manage rotations in Unity 2 Answers
Rotation changing in untouched axis 1 Answer