{"author_link":"\/users\/mildlydisturbing","author_name":"MildlyDisturbing","author_uid":"mildlydisturbing","comments":[],"epoch":1633637000,"event":"LD49","format":"md","ldjam_node_id":273631,"likes":13,"metadata":{"p_key":"161508","p_author":"MildlyDisturbing","p_authorkey":"1038688","p_urlkey":"384498","p_title":"Building a Simple & Fun Drifty Car Controller!","p_cat":"LDJam ","p_event":"LD49","p_time":"1633637000","p_likes":"13","p_comments":"0","p_status":"WAYBACK","us_key":"1038688","us_name":"MildlyDisturbing","us_username":"mildlydisturbing","event_start":"1633046400","event_key":"119","event_name":"Ludum Dare 49"},"node":{"_collation":{"body_sanitizer":"TextUtils::SanitizeHTML via existing importer","event":"LD49","removed_author":false},"_superparent":258323,"_trust":1,"author":38688,"body":"For [me](https:\/\/twitter.com\/sullysaysyes) and [my brother](https:\/\/twitter.com\/tamdevs)'s game: [**Driving Blind**](https:\/\/ldjam.com\/events\/ludum-dare\/49\/driving-blind)\n\n![ezgif-2-60f5a828ad2d.gif](\/\/\/raw\/027\/9\/z\/47b9a.gif)\n\nWe set out to build a fun arcade-y but chunky physical little car controller, and I was really pleased with the result given how little effort it took to produce, so I thought why not share it with the rest of the wonderful people that participated in this little jam!\n\nThe premise is really simple, take any car model, I modeled one in Blender:\n\n![D4r9H5MWAAAeqKS.png](\/\/\/raw\/027\/9\/z\/47b9b.png)\n\nBut a great starting point if you don't want to model, and also happens to be where I got the rest of the assets from is [Kenney's Incredible & Free Kits](https:\/\/www.kenney.nl\/assets\/car-kit)\n\nThrow that stuff into whatever game engine you are using, I'm using *Unity* it already has many of the physics functions you'll need for this:\n\n![cap2.PNG](\/\/\/raw\/027\/9\/z\/47ba1.png)\n\nTry to setup your asset hierarchy so the VISUALS are seperated from the FUNCTIONS, that way it will be easy to swap out cars down the line:\n\n![cap4.PNG](\/\/\/raw\/027\/9\/z\/47ba3.png)\n\nAdd a Rigidbody to the top most parent (The Functional Parent):\n\n![cap5.PNG](\/\/\/raw\/027\/9\/z\/47ba6.png)\n\nAnd add a Convex mesh collider to the Visual Car (Babby Car)\n\n![Cap6.PNG](\/\/\/raw\/027\/9\/z\/47ba8.png)\n\n_as you may have noticed, I also modelled some wheels seperately, and I slapped some materials on it, but this isn't an art tutorial, you can do all the same stuff with a box_\n\nNext up, add some transforms to where all the wheels should be, and then put ur wheel visuals under that transform.  This will be the point of origin from where we will be firing some Spherecast to hit the ground.  _Make sure the wheels don't have colliders, they're purely visual and anything blocking the cast will cause issues with ground detection_\n\n![cap7.PNG](\/\/\/raw\/027\/9\/z\/47bab.png)\n\n![cap3.PNG](\/\/\/raw\/027\/9\/z\/47ba2.png)\n\nOnce you have all your wheel points placed on your car, if you press play it should just drop to the ground and flop around and do nothing, but it shouldn't fall through the ground.\n\n![T6mUYcWokP.gif](\/\/\/raw\/027\/9\/z\/47bb4.gif)\n\nNow the Meat & Potatoes of this system!  Getting this car to hover off the ground using nothing but physics!\n\nThe premise is simple, we're going to SphereCast down to the ground, and find out how far away we are, and based on that distance, we'll apply more or less force to the point at which the wheel resides.  This will cause our car to hover off the ground if we have our variables set up properly:\n\nMake a Script called \"Wheel\" and add this code to it:\n\n```\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\npublic class Wheel : MonoBehaviour\n{\n    public Rigidbody mainRigid;\n    public float WheelForce;\n    public float WheelTorque = 10;\n    public Transform WheelTransform;\n    public Transform WheelVisual;\n    public float HoverDistance;\n    public float FloatDistance;\n    public LayerMask groundMask;\n    public float castSize = 0.3f;\n    public Vector3 castDisplacement = Vector3.up;\n    public ParticleSystem GroundedParticles;\n\n    public bool grounded = false;\n\n    void Awake()\n    {\n        WheelTransform.SetParent(null);\n    }\n    \n    void FixedUpdate()\n    {\n        \/\/This is intended to push the Car up using physics at the position this transform lies.\n        \n        Ray hitRay = new Ray(transform.position + castDisplacement, Vector3.down);\n\n        RaycastHit hitInfo;\n        if (Physics.SphereCast(hitRay, castSize, out hitInfo, HoverDistance, groundMask))\n        {\n            float distanceMod = 1.0f - Mathf.Clamp(hitInfo.distance \/ FloatDistance, 0.0f, 1.0f);\n            mainRigid.AddForceAtPosition(Vector3.up * WheelForce * distanceMod, transform.position,\n                ForceMode.VelocityChange);\n        }\n    }\n\n    void LateUpdate()\n    {\n        \/\/This is mostly for positioning the wheels where they need to be, seems a bit redundant as it's pretty much the same as above.  \n        \/\/Was having issues removing some of the redundancy as the above needs to happen, and for this object to move, before the late update can cast again\n        \/\/And align the wheels to the ground properly.\n\n        Ray hitRay = new Ray(transform.position + castDisplacement, Vector3.down);\n\n        RaycastHit hitInfo;\n        if (Physics.SphereCast(hitRay, castSize, out hitInfo, HoverDistance, groundMask))\n        {\n            if (hitInfo.distance < FloatDistance)\n            {\n                WheelTransform.position = hitInfo.point + hitInfo.normal * WheelTransform.lossyScale.y * 2.5f;\n                grounded = true;\n            }\n            else\n            {\n                WheelTransform.position = transform.position;\n                grounded = false;\n            }\n        }\n        else\n        {\n            WheelTransform.position = transform.position;\n            grounded = false;\n        }\n        WheelTransform.rotation = transform.rotation;\n\n        if (grounded)\n        {\n            if(!GroundedParticles.isPlaying)GroundedParticles.Play();\n        }\n        else\n        {\n            if (GroundedParticles.isPlaying) GroundedParticles.Stop();\n        }\n    }\n\n    public void SpinWheel(float direction)\n    {\n        \/\/Visual code to rotate the wheel that the car controller uses\n        WheelVisual.transform.Rotate(Vector3.up*direction,Space.Self);\n    }\n\n}\n```\n\n\nLook at the code comments to understand why there is Fixed and Late Update being used.  The basic idea is that Fixed is used to enact physics on the cars body, and the Late is used to position the wheel transforms after the fact.\n\n_Note: This code is optimized for speed of me writing it, not optimization or code elegance, feel free to improve upon it_\n\nAfter you've written that, slap this component onto all the wheels:\n\n![wheelcomponent.PNG](\/\/\/raw\/027\/9\/z\/47bc9.png)\n\n_NOTE: You may notice within the Wheel component inspector, there is a \"Wheel Transform\" and \"Wheel Visual\".  The Wheel transform is actually going to be the one snapping to the ground,but the visual will be the one spinning.  You need both so you can rotate the wheels left and right on the Y axis locally, while allowing the visual wheel to spin freely._\n\nIf you use my settings for the Car rigidbody, and the wheel components, your car should now balance when you press play:\n\n![mYgpDpf6SY.gif](\/\/\/raw\/027\/9\/z\/47bca.gif)\n\nIsn't that just the bees knees! Honestly, the rest of it could kinda go without being said, but all you need to do is loop through any number of wheels, for me, I chose the front wheels, and add force going relative to the Wheel forward:\n\n```\nVector2 movementAxis = new Vector2(Input.GetAxis(\"Horizontal\"), Input.GetAxis(\"Vertical\"));\n\nforeach (Wheel w in FrontWheels)\n{\n    \/\/Handle Rotation of the wheel based on player intent\n    w.transform.localRotation = Quaternion.Euler(0, 45 * movementAxis.x, 90);\n    \n    \/\/If the wheel is grounded, let's add force to the Car rigidbody at the position the front wheels are, in the direction the wheel is pointing!\n    if (w.grounded)\n    {\n        rgbd.AddForceAtPosition(w.transform.forward * w.WheelTorque \/*Add (* movementAxis.y) here if you want to control forward and back as well! *\/, w.transform.position,ForceMode.VelocityChange);\n    }\n}\n```\n\nThat should do it!\n\n![DRIVIN.gif](\/\/\/raw\/027\/9\/z\/47bd2.gif)\n\nYou should be able to drive your car around now.  It's not an entirely full proof solution, a lot of terrain it is not great at doing, but I will be improving on this foundation to have it be able to handle things a lot better.  \n\nHope some of that was helpful!  If it was, follow [me](https:\/\/twitter.com\/sullysaysyes) and [my brother](https:\/\/twitter.com\/tamdevs) for more cool little things like this in the future!\n\nTry [**Driving Blind**](https:\/\/ldjam.com\/events\/ludum-dare\/49\/driving-blind) !\n\n\n\n\n\n\n\n","comments":2,"comments-timestamp":"2021-10-08T00:57:48Z","created":"2021-10-07T18:52:00Z","files":[],"files-timestamp":0,"id":273631,"love":13,"love-timestamp":"2021-10-07T20:57:51Z","meta":[],"modified":"2021-10-08T00:57:48Z","name":"Building a Simple & Fun Drifty Car Controller!","node-timestamp":"2021-10-07T20:03:20Z","parent":271007,"parents":[1,5,9,258323,271007],"path":"\/events\/ludum-dare\/49\/driving-blind\/building-a-simple-fun-drifty-car-controller","published":"2021-10-07T20:03:20Z","scope":"public","slug":"building-a-simple-fun-drifty-car-controller","subsubtype":"","subtype":"","type":"post","version":845270},"node_metadata":{"n_key":"273631","n_urlkey":"384498","n_parent":"271007","n_path":"\/events\/ludum-dare\/49\/driving-blind\/building-a-simple-fun-drifty-car-controller","n_slug":"building-a-simple-fun-drifty-car","n_type":"post","n_subtype":"","n_subsubtype":"","n_author":"38688","n_created":"1633632720","n_modified":"1633654668","n_version":"845270","n_status":"WAYBACK"},"source_url":"https:\/\/ldjam.com\/events\/ludum-dare\/49\/driving-blind\/building-a-simple-fun-drifty-car-controller","text":"For [me](https:\/\/twitter.com\/sullysaysyes) and [my brother](https:\/\/twitter.com\/tamdevs)'s game: [**Driving Blind**](https:\/\/ldjam.com\/events\/ludum-dare\/49\/driving-blind)\n\n![ezgif-2-60f5a828ad2d.gif](\/\/\/raw\/027\/9\/z\/47b9a.gif)\n\nWe set out to build a fun arcade-y but chunky physical little car controller, and I was really pleased with the result given how little effort it took to produce, so I thought why not share it with the rest of the wonderful people that participated in this little jam!\n\nThe premise is really simple, take any car model, I modeled one in Blender:\n\n![D4r9H5MWAAAeqKS.png](\/\/\/raw\/027\/9\/z\/47b9b.png)\n\nBut a great starting point if you don't want to model, and also happens to be where I got the rest of the assets from is [Kenney's Incredible & Free Kits](https:\/\/www.kenney.nl\/assets\/car-kit)\n\nThrow that stuff into whatever game engine you are using, I'm using *Unity* it already has many of the physics functions you'll need for this:\n\n![cap2.PNG](\/\/\/raw\/027\/9\/z\/47ba1.png)\n\nTry to setup your asset hierarchy so the VISUALS are seperated from the FUNCTIONS, that way it will be easy to swap out cars down the line:\n\n![cap4.PNG](\/\/\/raw\/027\/9\/z\/47ba3.png)\n\nAdd a Rigidbody to the top most parent (The Functional Parent):\n\n![cap5.PNG](\/\/\/raw\/027\/9\/z\/47ba6.png)\n\nAnd add a Convex mesh collider to the Visual Car (Babby Car)\n\n![Cap6.PNG](\/\/\/raw\/027\/9\/z\/47ba8.png)\n\n_as you may have noticed, I also modelled some wheels seperately, and I slapped some materials on it, but this isn't an art tutorial, you can do all the same stuff with a box_\n\nNext up, add some transforms to where all the wheels should be, and then put ur wheel visuals under that transform.  This will be the point of origin from where we will be firing some Spherecast to hit the ground.  _Make sure the wheels don't have colliders, they're purely visual and anything blocking the cast will cause issues with ground detection_\n\n![cap7.PNG](\/\/\/raw\/027\/9\/z\/47bab.png)\n\n![cap3.PNG](\/\/\/raw\/027\/9\/z\/47ba2.png)\n\nOnce you have all your wheel points placed on your car, if you press play it should just drop to the ground and flop around and do nothing, but it shouldn't fall through the ground.\n\n![T6mUYcWokP.gif](\/\/\/raw\/027\/9\/z\/47bb4.gif)\n\nNow the Meat & Potatoes of this system!  Getting this car to hover off the ground using nothing but physics!\n\nThe premise is simple, we're going to SphereCast down to the ground, and find out how far away we are, and based on that distance, we'll apply more or less force to the point at which the wheel resides.  This will cause our car to hover off the ground if we have our variables set up properly:\n\nMake a Script called \"Wheel\" and add this code to it:\n\n```\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\npublic class Wheel : MonoBehaviour\n{\n    public Rigidbody mainRigid;\n    public float WheelForce;\n    public float WheelTorque = 10;\n    public Transform WheelTransform;\n    public Transform WheelVisual;\n    public float HoverDistance;\n    public float FloatDistance;\n    public LayerMask groundMask;\n    public float castSize = 0.3f;\n    public Vector3 castDisplacement = Vector3.up;\n    public ParticleSystem GroundedParticles;\n\n    public bool grounded = false;\n\n    void Awake()\n    {\n        WheelTransform.SetParent(null);\n    }\n    \n    void FixedUpdate()\n    {\n        \/\/This is intended to push the Car up using physics at the position this transform lies.\n        \n        Ray hitRay = new Ray(transform.position + castDisplacement, Vector3.down);\n\n        RaycastHit hitInfo;\n        if (Physics.SphereCast(hitRay, castSize, out hitInfo, HoverDistance, groundMask))\n        {\n            float distanceMod = 1.0f - Mathf.Clamp(hitInfo.distance \/ FloatDistance, 0.0f, 1.0f);\n            mainRigid.AddForceAtPosition(Vector3.up * WheelForce * distanceMod, transform.position,\n                ForceMode.VelocityChange);\n        }\n    }\n\n    void LateUpdate()\n    {\n        \/\/This is mostly for positioning the wheels where they need to be, seems a bit redundant as it's pretty much the same as above.  \n        \/\/Was having issues removing some of the redundancy as the above needs to happen, and for this object to move, before the late update can cast again\n        \/\/And align the wheels to the ground properly.\n\n        Ray hitRay = new Ray(transform.position + castDisplacement, Vector3.down);\n\n        RaycastHit hitInfo;\n        if (Physics.SphereCast(hitRay, castSize, out hitInfo, HoverDistance, groundMask))\n        {\n            if (hitInfo.distance < FloatDistance)\n            {\n                WheelTransform.position = hitInfo.point + hitInfo.normal * WheelTransform.lossyScale.y * 2.5f;\n                grounded = true;\n            }\n            else\n            {\n                WheelTransform.position = transform.position;\n                grounded = false;\n            }\n        }\n        else\n        {\n            WheelTransform.position = transform.position;\n            grounded = false;\n        }\n        WheelTransform.rotation = transform.rotation;\n\n        if (grounded)\n        {\n            if(!GroundedParticles.isPlaying)GroundedParticles.Play();\n        }\n        else\n        {\n            if (GroundedParticles.isPlaying) GroundedParticles.Stop();\n        }\n    }\n\n    public void SpinWheel(float direction)\n    {\n        \/\/Visual code to rotate the wheel that the car controller uses\n        WheelVisual.transform.Rotate(Vector3.up*direction,Space.Self);\n    }\n\n}\n```\n\n\nLook at the code comments to understand why there is Fixed and Late Update being used.  The basic idea is that Fixed is used to enact physics on the cars body, and the Late is used to position the wheel transforms after the fact.\n\n_Note: This code is optimized for speed of me writing it, not optimization or code elegance, feel free to improve upon it_\n\nAfter you've written that, slap this component onto all the wheels:\n\n![wheelcomponent.PNG](\/\/\/raw\/027\/9\/z\/47bc9.png)\n\n_NOTE: You may notice within the Wheel component inspector, there is a \"Wheel Transform\" and \"Wheel Visual\".  The Wheel transform is actually going to be the one snapping to the ground,but the visual will be the one spinning.  You need both so you can rotate the wheels left and right on the Y axis locally, while allowing the visual wheel to spin freely._\n\nIf you use my settings for the Car rigidbody, and the wheel components, your car should now balance when you press play:\n\n![mYgpDpf6SY.gif](\/\/\/raw\/027\/9\/z\/47bca.gif)\n\nIsn't that just the bees knees! Honestly, the rest of it could kinda go without being said, but all you need to do is loop through any number of wheels, for me, I chose the front wheels, and add force going relative to the Wheel forward:\n\n```\nVector2 movementAxis = new Vector2(Input.GetAxis(\"Horizontal\"), Input.GetAxis(\"Vertical\"));\n\nforeach (Wheel w in FrontWheels)\n{\n    \/\/Handle Rotation of the wheel based on player intent\n    w.transform.localRotation = Quaternion.Euler(0, 45 * movementAxis.x, 90);\n    \n    \/\/If the wheel is grounded, let's add force to the Car rigidbody at the position the front wheels are, in the direction the wheel is pointing!\n    if (w.grounded)\n    {\n        rgbd.AddForceAtPosition(w.transform.forward * w.WheelTorque \/*Add (* movementAxis.y) here if you want to control forward and back as well! *\/, w.transform.position,ForceMode.VelocityChange);\n    }\n}\n```\n\nThat should do it!\n\n![DRIVIN.gif](\/\/\/raw\/027\/9\/z\/47bd2.gif)\n\nYou should be able to drive your car around now.  It's not an entirely full proof solution, a lot of terrain it is not great at doing, but I will be improving on this foundation to have it be able to handle things a lot better.  \n\nHope some of that was helpful!  If it was, follow [me](https:\/\/twitter.com\/sullysaysyes) and [my brother](https:\/\/twitter.com\/tamdevs) for more cool little things like this in the future!\n\nTry [**Driving Blind**](https:\/\/ldjam.com\/events\/ludum-dare\/49\/driving-blind) !\n\n\n\n\n\n\n\n","title":"Building a Simple & Fun Drifty Car Controller!","wayback_source":[]}