applying visual wheels according to position left/right
I have found tutorial on https://docs.unity3d.com/Manual/WheelColliderTutorial.html very useful, but after applying my own custom meshes, I have noticed that they are all rotated I the same direction (facing right, in my case).
Is there a way that I can edit the code given on the link in such way that I can rotate the meshes using two boolean variables, left and right, mutually exclusive to each other, to make them face either to the left or right ?
the top picture is showing my vehicle from the from-right side, while the bottom shows it from from-left side. notice the mesh on the wheels.
Answer by DCordoba · Feb 10, 2019 at 10:59 AM
Since visualWheel
is a child of each wheel to have the wheel collider (who really affect the weel behavior) you can change the code visuals whithout affect the physics.
We can do a better performance handling quaternions directly, but since I don't want to mess the code (and my mind) with quaternions, lets use euler (degrees) angles.
According the instructions of the tutorial, the axis of the weels is X axis, and up is Y, we need to rotate Y axis 180 degrees, but, accordingly with the car orientation. To not reinvent the wheel, we will use transform.Rotate
So, lets change first ApplyLocalPositionToVisuals adding a bool
, as you desire, to determine if wheel is right or left, and rotate 180° all the left, on your case.
public void ApplyLocalPositionToVisuals(WheelCollider collider, bool isAtLeft)
{
if (collider.transform.childCount == 0) {
return;
}
Transform visualWheel = collider.transform.GetChild(0);
Vector3 position;
Quaternion rotation;
collider.GetWorldPose(out position, out rotation);
visualWheel.transform.position = position;
visualWheel.transform.rotation = rotation;
if(isAtLeft)
//@CROnerd64 use local forward there, local up didn't seem to work properly
visualWheel.transform.Rotate(0, 0, 180f, Space.Self);
}
now you can use it on the FixedUpdate
code, just modify the line:
ApplyLocalPositionToVisuals(axleInfo.leftWheel, true);
ApplyLocalPositionToVisuals(axleInfo.rightWheel, false);
if found any problem with this code, please comment :)
@CROnerd64 nice mars rover btw
EDIT: @CROnerd64 found two errors in the original answer, modifying it to the final script
the visuals are working perfectly, until I start moving around. to be more precise, when I turn vehicle around the axis; all the wheels on the left start going haywire. I would assume its because its trying to rotate it around local axis.
@DCordoba thanks for the rover. if you are interested in the models, I could send you tinkercad link privately.
ok, I think I solved it. the issue was that it was trying to rotate it according to self, which is constantly rotating. So ins$$anonymous$$d of:
if(isAtLeft)
//please note that I use local up there, no matter if car isn't up, or if the wheel is tilted
visualWheel.transform.Rotate (visualWheel.transform.up, 180);
}
I have put:
if(isAtLeft)
//please note that I use local up there, no matter if car isn't up, or if the wheel is tilted
visualWheel.transform.Rotate (transform.up, 180);
}
this, if I am understanding correctly, will rotate it by 180 degs according to the wheel object that has wheelcollider attached to it, giving it a consistent pivot to rely upon.
@DCordoba could you please modify your answer to to match what I have written here, so I can accept it?
as it turns out, above code will still fail if the vehicle starts turning around the z axis, that is, if it flips on the side, or climbs up for eg. a rock, it will rotate incorrectly. so after a lot of head banging and crying, I found a solution to that too; ins$$anonymous$$d of:
visualWheel.transform.Rotate (transform.up, 180);
write:
visualWheel.transform.eulerAngles=new Vector3(visualWheel.transform.eulerAngles.x,visualWheel.transform.eulerAngles.y,visualWheel.transform.eulerAngles.z+180);
sure, its a bit longer, and probably inelegant, but it works nonetheless
@DCordoba one last edit pls ?
my friend, this is the same to do:
visualWheel.transform.Rotate(0, 0, 180f, Space.Self);
or
visualWheel.transform.Rotate (visualWheel.transform.forward, 180);
how is possible to this work one way and not by another...?
I mean transform.up and transform.forward are both orthogonal to the left vector, I choose up because think to this was more readable, sorry
but I still dont understand why dont work...
neither do I. I can only present you with my observations on the behaviour or code, and this is what I've got:
the visualWheel.transform.Rotate(0, 0, 180f, Space.Self);
and visualWheel.transform.eulerAngles=new Vector3(visualWheel.transform.eulerAngles.x,visualWheel.transform.eulerAngles.y,visualWheel.transform.eulerAngles.z+180);
have proven to work fine for now, but
visualWheel.transform.Rotate (visualWheel.transform.forward, 180);
does this wonky thing when rotated around Y axis (I have turned off useGravity on rigidBody component of the main player, and used unitys rotation tool to achieve this during runtime, but it can be done without this during playtime to achieve it, this way is just easier for me to snapshot it):
awhile the
visualWheel.transform.Rotate (transform.up, 180);
does this thing when rotated by the Z axis:
Im not sure why any of this is happening, and its slowly starting to get on my nerves, but I'm pretty use it has to do with the reference axis we are using, which is why I wrote that long line of code: it takes old variables on X and Y axis and only adds 180 to the Z axis.
Answer by Schemaposse · Feb 19, 2019 at 06:36 PM
visualWheel.transform.Rotate (Vector3.up, 180);
@Schemaposse umm, we already have an accepted answer, and that has already proven dysfunctional. please check the comment section of the first answer