Search Unity

Tire wobbles and bounces, any way to smooth it out?

Discussion in 'Physics' started by BongMcPuffin, Oct 29, 2017.

  1. BongMcPuffin

    BongMcPuffin

    Joined:
    Oct 16, 2017
    Posts:
    26
    Hi there, I'm completely new to coding/game design in general, and I'm just messing around trying to get what I thought was a pretty simple project completed and its turning out to be a nightmare to figure out.

    So my project is to get a tire to roll smoothly across the ground using AddForce, using an orbit camera to dictate the direction of the added force to make "forward" always the camera's forward. I've gotten all the basic functionality implemented but my issue is that when I roll the tire it starts to wobble and if I apply a physics material to make it bouncy it bounces as it rolls due to the faceted nature of the mesh collider I'm using.

    I've tested out things with a sphere collider and it rolls perfectly smooth with that, so I know what I'm running into is a collider issue. I can't use a sphere, box, or capsule collider for this, at least as far as I've been able to see. If I try to smash the capsule together to form a cylinder it just makes a sphere instead, and after reading into it some, it appears that making a cylinder collider is apparently as difficult as dividing by zero and accurately predicting tomorrows lotto numbers.

    The wheel collider sounds exactly like what I need, but it doesn't behave anything like how I thought it would, and apparently you need 4 of them for it to work correctly (I could be wrong about this, please correct me if I'm wrong).

    I bought the asset "ExtendedColliders3D" because it has a cylinder collider function, but that didn't help at all and still gave the exact same problems, even if I turned the triangle count on the mesh up super high to make it as smooth as possible.

    Here is a video showing the behavior I'm talking about with the wobbles and bounces. If you look closely it looks as though the tire is slightly bobbing up and down as its rolling forward before the wobbles start and it slightly moves left/right right before the big wobbles set in. I am not applying anything but forward force and it is somehow causing the tire to turn, bounce and wobble. I need to figure out why its doing this and how to smooth it out without sacrificing maneuverability. You can see by mouse mouse (top right of the screen) that I am NOT moving the camera at all. The only button I'm holding is W to go forward.



    I'm using a rigidbody and mesh collider for the tire, but if there is a better way with a character controller or whatever, I'm open to ideas. I'm open to buying things from the asset store if necessary but I'd like to have more certainty in whether or not its going to solve my problems, since I've already wasted $5 on one package already.

    Desired Game-play elements:
    I need the tire to roll straight and true without wobbles or bouncing if I'm looking directly behind the tire and applying forward force. I want the tire to be able to lay flat on its side if it falls over, this is why I was going with a cylinder instead of a capsule and I want the tire to bounce a little when it hits other solid things and the ground so turning bounciness off isn't a solution. This is important if I'm going to be attempting to cross narrow bridges or pathways with any kind of accuracy where a wobbly and unpredictably bouncy tire could send you to your doom. Its a huge pain in the rear to have to stop every 10 feet and let the tire re-stabilize just because it rolls funny across flat ground.
     
  2. nat42

    nat42

    Joined:
    Jun 10, 2017
    Posts:
    353
    Not something I have tried, but I saw Bullet physics is available to use as an alternative to Unity's (PhysX) solution. Bullet does have a cylinder shape so you can perhaps rule out accuracy issues with the shape with it.

    Though the effect shown in your YouTube clip looks remarkably like the kind of motion a coin will exhibit after being spun but before it stops flat, could it be that parameters like mass and friction are way off and causing the effect?
     
  3. BongMcPuffin

    BongMcPuffin

    Joined:
    Oct 16, 2017
    Posts:
    26
    That is entirely possible, since I have no idea what I'm doing anyways... I wouldn't know what "way off" is even if it bit me in the butt.

    I'm going to check out the Bullet physics though, see if that might be a solution, thanks for the lead!
     
  4. Plystire

    Plystire

    Joined:
    Oct 30, 2016
    Posts:
    142
    This looks similar to the way a tire would normally start favoring one side over the other when rolled, eventually turning and spiraling until it fell over and stopped.

    I suspect the wobble is arising because you're constantly putting energy into the tire to keep it moving forward, so after the tire starts to tilt you're now effectively rolling a tilted tire, which looks like a wobble.

    What does your code look like?
     
  5. BongMcPuffin

    BongMcPuffin

    Joined:
    Oct 16, 2017
    Posts:
    26
    Here is my control script:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class TireControl : MonoBehaviour
    5. {
    6.  
    7.     public float speed;
    8.     public float torque;
    9.     public Rigidbody rb;
    10.     public float jumpForce;
    11.  
    12.     void Start()
    13.     {
    14.         rb = GetComponent<Rigidbody>();
    15.     }
    16.  
    17.     void FixedUpdate()
    18.     {
    19.             float rollForward = Input.GetAxis("Vertical");
    20.             Vector3 movement = new Vector3(0.0f, 0.0f, rollForward);
    21.             movement = Camera.main.transform.TransformDirection(movement);
    22.             rb.AddForce((movement * speed), ForceMode.Acceleration);
    23.  
    24.         if (Input.GetButton("Horizontal")){
    25.             float turn = Input.GetAxis("Horizontal");
    26.             rb.AddRelativeTorque(Vector3.back * torque * turn);
    27.             }
    28.         if (Input.GetButtonUp("Jump")) {
    29.             rb.AddForce(new Vector3(0, jumpForce, 0), ForceMode.Impulse);
    30.         }
    31.     }
    32. }
    One thing I've noticed is that if I rotate my camera 90 degrees up so it looks straight down at the tire and terrain it will apply all its force as if its pressing down into the terrain. I don't want the camera to "add extra gravity" while the tire rolls if that makes sense. I just want the camera to dictate which direction horizontally the force is applied, while W (forwards) dictates the amount of force going into the tire to push it, while gravity solely is the thing that pushes the tire downwards.

    Think of it like this... you're a ball thrown out of an airplane and you're falling to the ground below. You can't make yourself fall any faster because gravity is doing its own thing to bring you down. You might be able to spin on all your axis, but you won't be able to propel yourself any faster downwards. Once you are on the ground and stop bouncing, you can be rolled along the ground but you can't be pushed any harder into the ground than gravity is currently doing (unless something heavy lands on you and pushes you into the ground). In this case I'm imagining a golf ball being putted across the green toward a hole... zero downward force is applied by the putter but instead its simple horizontal energy, while gravity applies the vertical force, keeping it hugging the contours of the green. I'd like my tire to behave somewhat similar to this, where the camera isn't driving the tire into the terrain if the camera gets tilted upwards (think in Grand Theft Auto if you're driving a car and you raise the camera up to see above traffic, it doesn't affect the driving physics at all, it just adjusts the camera position and the forward speed and gravity of the car is the same no matter which direction you are looking.

    I know I'm all over the map here, but if you've ever played Arma 3 and used the mouse-steering feature in a vehicle that is what I'm looking for... W/S are forward/brake, A/D are tire rotation (to upright the tire after falling), and the mouse dictates which way the car steers as you slide the mouse left and right while vertical input simply controls the cameras position. I know the physics/mechanism are completely different for a car than they are for a single tire, but the gist is the same in terms of over all desired control.

    I don't have Arma 3 installed at the moment but if anyone wants more footage of what I'm talking about I'll be happy to install it and record what I'm talking about.
     
  6. Plystire

    Plystire

    Joined:
    Oct 30, 2016
    Posts:
    142
    Try using:
    Code (csharp):
    1. movement.y = 0;
    2. movement = movement.normalized;
    That will negate the y movement being applied from your camera angle, and then normalize your movement vector so it keeps a magnitude of 1.
     
  7. Fu11English

    Fu11English

    Joined:
    Feb 27, 2012
    Posts:
    258
    Use a cylinder but don't actually rotate it to make it move, instead just push it along. Maybe put a configurable joint on it and lock it's local rotation in the relevant axis. Then you need some basic wheel collider style code to calculate slips, friction and forces etc to make it behave realistically. There's a script here which you can adapt for your needs.

    Then have your visual mesh as a child object of this and calculate it's needed rotation speed based on the parent colliders / rigidbody forward velocity.
     
    Last edited: Oct 29, 2017
  8. BongMcPuffin

    BongMcPuffin

    Joined:
    Oct 16, 2017
    Posts:
    26
    This works great, took me a minute to realize I had to set the camera to lock to no more than 89 degrees though because at a full 90 degrees it didn't know which why I was looking, but after switching to 89 it works great.

    It doesn't do anything for the wobble at all unfortunately though.

    From that wiki page you linked, they say "The VWheelColliders do not add any spring forces, so to keep the wheels from falling through the terrain, you need to place a sphere-collider (or equivalent) for each wheel, with its radius set to the wheel's radius." which would make my tire roll like a marble if I had to put a sphere collider on it to make it work.

    Maybe I'm missing something, but I can't make sense of how this would work. Thanks for the help regardless though!
     
  9. Fu11English

    Fu11English

    Joined:
    Feb 27, 2012
    Posts:
    258
    Yes forget the sphere you use a convex cylinder collider just like you want. Trust me I have done it myself for a motorbike using the same basic code with my own additions :)
     
  10. BoogieD

    BoogieD

    Joined:
    Jun 8, 2016
    Posts:
    236
    I like the way it wobbles because that's exactly what rolling tires do.
    You could try using a sphere collider then setting the Rigidbody->Constraints->Freeze Rotation settings. Rotate the tire on the X and freeze Z and perhaps Y too.
     
  11. BongMcPuffin

    BongMcPuffin

    Joined:
    Oct 16, 2017
    Posts:
    26
    So I did some tests (and modeled a newer, arguably less ugly tire) and one of the tests I did was to tilt the plane to a 45 degree angle and let the tire roll under its own weight and it eventually starts to wobble, so I'm not sure what to make of that, if that is realistic or not, and its not like I can roll a tire down a really long hill over and over again to check it out in real life without probably racking up a few felonies. This pretty much is the same thing I get as if I was pushing the tire forward with AddForce.



    One thing that bugs me about this is that theoretically, if an infinite plane existed and is as flat and smooth as an ice hockey rink, and theoretically my tire is a perfectly circular and symetrical cylinder, the tire should roll forever without wobbling, yet in my example the tire wobbles which doesn't make any sense to me. Maybe its correct behavior, but it seems un-intuitive to me.

    Another test I did was to change the AddForce to AddRelativeTorque and that seems to fix the wobbly tire, but no matter what value I set for the speed it just kind of maxes out at a relatively slow pace and it messes up my ability to steer the tire since its no longer being pushed in the direction the camera is looking, instead its only rotating around its X axis.



    As you can see the tire rolls fairly slowly, even if I crank the speed up to something crazy like 5,000,000 units.

    What I THINK I want is to power the tire by AddRelativeTorque, but have the steering be done by AddTorque relative to my OrbitCam, but that doesn't make any sense to me how to combine the two and make it feel realistic/intuitive and have it so the AddToque doesn't add any power to the tire. AddRelativeTorque also seems like a good way to make it so the tire can do a burn out by applying a brake to the tire and making it spin faster than friction can hold it in place, which is a behavior I would like to eventually try to implement anyways. The tire did in fact do a little tiny bit of a burn out before gaining traction and rolling along in my test, which was cool. The only problem is I'd like the tire to be able to roll a bit faster to see if it really fixes the wobble.

    What I think is happening is this... AddForce with my OrbitCam just pushes the tire along in a straight line relative to where my camera is looking regardless of the tires rotation/orientation, and the rotation the tire is experiencing is simply caused by gravity and the friction of the tire and the ground. This is NOT how a tire behaves in real life when being driven by a motor. In real life the tire is being spun around its axis by torque that the axle of the car generates which is powered by the motor. The car isn't pushing the tire, its torquing it.

    At low speeds with AddForce my tire works perfectly fine, but once I crank the speed up past 20 thats when the wobbles start with the AddForce effect.

    This is all without any PhysicsMaterials either... which I fear as soon as I add bounciness to my tire its going to mess everything up all over again.

    I know this is a common thing that new Devs say all the time, but I had no idea this was going to be so complicated to get right, lol, the idea was so simple when it was all in my head as a mere day dream.

    Edit: Here is my control script with the AddRelativeTorque code.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class TireControl : MonoBehaviour
    5. {
    6.  
    7.     public float speed;
    8.     public float torque;
    9.     public Rigidbody rb;
    10.     public float jumpForce;
    11.  
    12.     void Start()
    13.     {
    14.         rb = GetComponent<Rigidbody>();
    15.     }
    16.  
    17.     void FixedUpdate()
    18.     {
    19.     if (Input.GetButton("Vertical")){
    20.     float rollForward = Input.GetAxis("Vertical");
    21.             Vector3 movement = new Vector3(0.0f, 0.0f, rollForward);
    22.             movement = Camera.main.transform.TransformDirection(movement);
    23.         movement.y = 0;
    24.         movement = movement.normalized;
    25.     rb.AddRelativeTorque(Vector3.forward * speed, ForceMode.Acceleration);
    26.     }
    27.  
    28.         if (Input.GetButton("Horizontal")){
    29.             float turn = Input.GetAxis("Horizontal");
    30.             rb.AddRelativeTorque(Vector3.up * torque * turn);
    31.         }
    32.         if (Input.GetButtonUp("Jump")) {
    33.             rb.AddForce(new Vector3(0, jumpForce, 0), ForceMode.Impulse);
    34.         }
    35.     }
    36. }
     
    Last edited: Nov 13, 2017