Skip to content

Commit

Permalink
feat: Support tiled wheels (like BMW?)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vatsal Ambastha committed Sep 20, 2020
1 parent 2398186 commit 58e944d
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 53 deletions.
70 changes: 31 additions & 39 deletions Assets/Tork/Runtime/Core/TorkWheel.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
using UnityEngine;
/*
* NOTE (A)
* A car with wheels of diameter ~55cm usually has axle of diameter 2.2cm. That's a ratio of 25.
Could not get values of real cars to verify the 55 and 2.2 cm claim but hat's what I've read somewhere
in a physics problem. This gets me good results. For example: A Civic has 170Nm of torque, at the first
gear that's about 530Nm of torque after transmission with a gear ratio of 3.1. If I set the max toque
in the motor at 530, I get an acceleration that I'd expect when someone in a Civic floors it.
I'd imagine heavier vehicles have thicker axles, but their wheels are also large, so may be the
ratio would still hold. Or maybe it won't. Please change the value as you prefer.
*/

using UnityEngine;

namespace Adrenak.Tork {
public class TorkWheel : MonoBehaviour {
// See at the bottom of the file for NOTE (A) to read about this.
// See at the top of the file for NOTE (A) to read about this.
const float engineShaftToWheelRatio = 25;

[Tooltip("The radius of the wheel")]
Expand Down Expand Up @@ -121,7 +133,8 @@ public class TorkWheel : MonoBehaviour {

Ray m_Ray;
new Rigidbody rigidbody;
public const float k_RayStartHeight = 1;
public const float k_ExtraRayLegnth = 1;
public float RayLength => suspensionDistance + radius + k_ExtraRayLegnth;

void Start() {
m_Ray = new Ray();
Expand All @@ -136,9 +149,13 @@ void Start() {
}

void FixedUpdate() {
Velocity = rigidbody.GetPointVelocity(Hit.point);
Velocity = rigidbody.GetPointVelocity(transform.position); // Now

transform.localEulerAngles = new Vector3(0, SteerAngle, 0);
transform.localEulerAngles = new Vector3(
transform.localEulerAngles.x,
SteerAngle,
transform.localEulerAngles.z
);
CalculateSuspension();
CalculateFriction();
CalculateRPM();
Expand All @@ -151,23 +168,20 @@ void CalculateRPM() {
}

void CalculateSuspension() {
float rayLen = GetRayLen();
m_Ray.direction = -transform.up.normalized;
m_Ray.origin = transform.position + transform.up * k_RayStartHeight;
m_Ray.direction = -transform.up;
m_Ray.origin = transform.position + transform.up * k_ExtraRayLegnth;

IsGrounded = WheelRaycast(rayLen, ref m_Hit);
IsGrounded = WheelRaycast(RayLength, ref m_Hit);
// If we did not hit, relax the spring and return
if (!IsGrounded) {
m_PrevCompressionDist = CompressionDistance;
CompressionDistance = CompressionDistance - Time.fixedDeltaTime * relaxRate;
CompressionDistance = Mathf.Clamp(CompressionDistance, 0, suspensionDistance);

IsGrounded = false;
return;
}

var force = 0.0f;
CompressionDistance = rayLen - Hit.distance;
CompressionDistance = RayLength - Hit.distance;
CompressionDistance = Mathf.Clamp(CompressionDistance, 0, suspensionDistance);
CompressionRatio = CompressionDistance / suspensionDistance;

Expand All @@ -179,30 +193,24 @@ void CalculateSuspension() {
float rate = (m_PrevCompressionDist - CompressionDistance) / Time.fixedDeltaTime;
m_PrevCompressionDist = CompressionDistance;

float damperForce = rate * stiffness * (1 - dampingFactor);
force -= damperForce;
float dampingForce = rate * stiffness * dampingFactor;
force -= dampingForce;

force *= Vector3.Dot(Hit.normal, transform.up);
SuspensionForce = transform.up * force;

// Apply suspension force
rigidbody.AddForceAtPosition(SuspensionForce, (Hit.point));
}

bool WheelRaycast(float maxDistance, ref RaycastHit nearestHit) {
RaycastHit hit;

if (Physics.Raycast(m_Ray.origin, m_Ray.direction, out hit, maxDistance, m_RaycastLayers)) {
nearestHit = hit;
bool WheelRaycast(float maxDistance, ref RaycastHit hit) {
if (Physics.Raycast(m_Ray.origin, m_Ray.direction, out hit, maxDistance, m_RaycastLayers))
return true;
}
return false;
}

void CalculateFriction() {
if (!IsGrounded) return;


// Contact basis (can be different from wheel basis)
Vector3 normal = Hit.normal;
Vector3 side = transform.right;
Expand Down Expand Up @@ -240,21 +248,5 @@ void CalculateFriction() {
rigidbody.AddForceAtPosition(gripResistanceForce, Hit.point);
rigidbody.AddForceAtPosition(forward * MotorTorque / radius * forwardGrip * engineShaftToWheelRatio, Hit.point);
}

public float GetRayLen() {
return suspensionDistance + radius + k_RayStartHeight;
}
}
}

/*
* NOTE (A)
* A car with wheels of diameter ~55cm usually has axle of diameter 2.2cm. That's a ratio of 25.
Could not get values of real cars to verify the 55 and 2.2 cm cliam but hat's what I've read somewhere
in a physics problem. This gets me good results. For example: A Civic has 170Nm of torque, at the first
gear that's about 530Nm of torque after transmission with a gear ratio of 3.1. If I set the max toque
in the motor at 530, I get an acceleration that I'd expect when someone in a Civic floors it.
I'd imagine heavier vehicles have thicker axles, but their wheels are also large, so may be the
ratio would still hold. Or maybe it won't. Please change the value as you prefer.
*/
}
2 changes: 1 addition & 1 deletion Assets/Tork/Runtime/Vehicle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Adrenak.Tork {
public class Vehicle : MonoBehaviour {
[SerializeField] Rigidbody rigidbody;
[SerializeField] new Rigidbody rigidbody;
public Rigidbody Rigidbody { get { return rigidbody; } }

[Header("Core Components")]
Expand Down
6 changes: 3 additions & 3 deletions Assets/Tork/Runtime/Viz/WheelViz.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ void OnDrawGizmos() {
Handles.DrawWireDisc(t.position, t.right, target.radius);

Handles.color = Color.red;
var p1 = t.position + t.up * TorkWheel.k_RayStartHeight;
var p2 = t.position - t.up * (target.GetRayLen() - TorkWheel.k_RayStartHeight);
var p1 = t.position + t.up * TorkWheel.k_ExtraRayLegnth;
var p2 = t.position - t.up * (target.RayLength - TorkWheel.k_ExtraRayLegnth);
Handles.DrawLine(p1, p2);

var pos = t.position + (-t.up * (target.GetRayLen() - TorkWheel.k_RayStartHeight - target.CompressionDistance - target.radius));
var pos = t.position + (-t.up * (target.RayLength - TorkWheel.k_ExtraRayLegnth - target.CompressionDistance - target.radius));
Handles.DrawWireDisc(pos, t.right, target.radius);
}
}
Expand Down
18 changes: 9 additions & 9 deletions Assets/Tork/Samples/Scripts/DemoInputSource.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
using UnityEngine;

using UnityEngine;

namespace Adrenak.Tork {
public class DemoInputSource : MonoBehaviour {
[SerializeField] Vehicle m_Vehicle;

public class DemoInputSource : MonoBehaviour {
[SerializeField] Vehicle m_Vehicle;

public void SetVehicle(Vehicle vehicle){
m_Vehicle = vehicle;
}

}

void Update(){
m_Vehicle.Motor.value = Input.GetAxis("Vertical");
m_Vehicle.Steering.value = Input.GetAxis("Horizontal");
m_Vehicle.Brake.value = Input.GetKey(KeyCode.Space) ? 1 : 0;
}
}
}
}
}
2 changes: 1 addition & 1 deletion ProjectSettings/ProjectSettings.asset
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ PlayerSettings:
incrementalIl2cppBuild: {}
allowUnsafeCode: 0
additionalIl2CppArgs:
scriptingRuntimeVersion: 0
scriptingRuntimeVersion: 1
apiCompatibilityLevelPerPlatform: {}
m_RenderingPath: 1
m_MobileRenderingPath: 1
Expand Down

0 comments on commit 58e944d

Please sign in to comment.