assets and etc.
This commit is contained in:
@@ -34,12 +34,9 @@ public partial class VeloXWheel
|
||||
/// </summary>
|
||||
public float CounterTorque { get; private set; }
|
||||
|
||||
[Property, Sync] public bool AutoSetFriction { get; set; } = true;
|
||||
[Property, Sync] public bool UseGroundVelocity { get; set; } = true;
|
||||
|
||||
[Property, Range( 0, 2 )] public float BrakeMult { get; set; } = 1f;
|
||||
[Property] public Friction ForwardFriction = new();
|
||||
[Property] public Friction SidewayFriction = new();
|
||||
public Friction ForwardFriction = new();
|
||||
public Friction SidewayFriction = new();
|
||||
public Vector3 FrictionForce;
|
||||
|
||||
|
||||
@@ -102,8 +99,6 @@ public partial class VeloXWheel
|
||||
private Vector3 correctiveForce;
|
||||
private void UpdateFriction( float dt )
|
||||
{
|
||||
|
||||
|
||||
var motorTorque = DriveTorque;
|
||||
var brakeTorque = BrakeTorque * BrakeMult;
|
||||
|
||||
@@ -151,7 +146,7 @@ public partial class VeloXWheel
|
||||
float absMotorTorque = Math.Abs( motorTorque );
|
||||
float absBrakeTorque = Math.Abs( brakeTorque );
|
||||
|
||||
float maxForwardForce = Tire.Evaluate( Math.Abs( ForwardFriction.Slip ) ) * Math.Min( peakForwardFrictionForce, forwardForceClamp );
|
||||
float maxForwardForce = Math.Min( peakForwardFrictionForce, forwardForceClamp );
|
||||
|
||||
maxForwardForce = absMotorTorque < absBrakeTorque ? maxForwardForce : peakForwardFrictionForce;
|
||||
ForwardFriction.Force = forwardInputForce > maxForwardForce ? maxForwardForce
|
||||
@@ -204,7 +199,7 @@ public partial class VeloXWheel
|
||||
ForwardFriction.Slip = (ForwardFriction.Speed - AngularVelocity * mRadius) / clampedAbsForwardSpeed;
|
||||
ForwardFriction.Slip *= slipLoadModifier;
|
||||
|
||||
SidewayFriction.Slip = MathF.Atan2( SidewayFriction.Speed, clampedAbsForwardSpeed ).RadianToDegree() * 0.01111f;
|
||||
SidewayFriction.Slip = MathF.Atan2( SidewayFriction.Speed, clampedAbsForwardSpeed );
|
||||
SidewayFriction.Slip *= slipLoadModifier;
|
||||
|
||||
float sideSlipSign = SidewayFriction.Slip > 0 ? 1 : -1;
|
||||
@@ -288,7 +283,8 @@ public partial class VeloXWheel
|
||||
//DebugOverlay.Normal( WorldPosition, hitSidewaysDirection * 10, overlay: true );
|
||||
//DebugOverlay.Normal( WorldPosition, hitForwardDirection * 10, overlay: true );
|
||||
//DebugOverlay.Normal( WorldPosition, FrictionForce / 100, overlay: true );
|
||||
//DebugOverlay.Normal( ContactPosition, ContactNormal * 10, overlay: true );
|
||||
//DebugOverlay.Normal( ContactPosition, Vector3.Up * AngularVelocity, overlay: true );
|
||||
|
||||
//DebugOverlay.Sphere( new( ContactPosition, 4 ), overlay: true );
|
||||
//Vehicle.Body.ApplyForceAt( ContactPosition, FrictionForce );
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ namespace VeloX;
|
||||
|
||||
public partial class VeloXWheel : Component
|
||||
{
|
||||
protected override void DrawGizmos()
|
||||
protected override void DrawGizmos() => GizmoDraw();
|
||||
|
||||
public void GizmoDraw()
|
||||
{
|
||||
|
||||
if ( !Gizmo.IsSelected )
|
||||
@@ -60,15 +62,5 @@ public partial class VeloXWheel : Component
|
||||
}
|
||||
}
|
||||
|
||||
////
|
||||
//// Forward direction
|
||||
////
|
||||
//{
|
||||
// var arrowStart = Vector3.Forward * Radius.MeterToInch();
|
||||
// var arrowEnd = arrowStart + Vector3.Forward * 8f;
|
||||
|
||||
// Gizmo.Draw.Color = Color.Red;
|
||||
// Gizmo.Draw.Arrow( arrowStart, arrowEnd, 4, 1 );
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public partial class VeloXWheel
|
||||
_skidMark.AutoCalculateNormals = false;
|
||||
_skidMark.SplineInterpolation = 4;
|
||||
go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
|
||||
go.Flags = go.Flags.WithFlag( GameObjectFlags.NotNetworked, true );
|
||||
SkidMarks.Enqueue( _skidMark );
|
||||
}
|
||||
|
||||
@@ -84,6 +85,7 @@ public partial class VeloXWheel
|
||||
WorldRotation = Rotation.LookAt( ContactNormal.RotateAround( Vector3.Zero, Rotation.FromRoll( 90 ) ) )
|
||||
};
|
||||
go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
|
||||
go.Flags = go.Flags.WithFlag( GameObjectFlags.NotNetworked, true );
|
||||
_skidMark.Points.Add( go );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,9 @@ public partial class VeloXWheel
|
||||
var val = Math.Abs( LateralSlip ) + Math.Abs( LongitudinalSlip );
|
||||
timeMul = timeMul.LerpTo( val, 0.1f );
|
||||
|
||||
if ( timeMul > 2 )
|
||||
return val;
|
||||
|
||||
return 0;
|
||||
//if ( timeMul > 2 )
|
||||
// return val;
|
||||
return val * 5;
|
||||
}
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
@@ -78,7 +77,7 @@ public partial class VeloXWheel
|
||||
{
|
||||
Type = ParticleFloat.ValueType.Curve,
|
||||
Evaluation = ParticleFloat.EvaluationType.Life,
|
||||
CurveA = new( new List<Curve.Frame>() { new( 0, 10f ), new( 0.8f, 50f ), new( 1f, 160f * sizeMul ) } ),
|
||||
CurveA = new( new List<Curve.Frame>() { new( 0, 10f ), new( 0.8f, 50f ), new( 1f, 160f ) } ),
|
||||
};
|
||||
effect.StartDelay = 0.025f + (1 - smokeMul) * 0.03f;
|
||||
|
||||
@@ -98,7 +97,7 @@ public partial class VeloXWheel
|
||||
ConstantB = 70,
|
||||
};
|
||||
effect.Force = true;
|
||||
effect.InitialVelocity = hitForwardDirection * LongitudinalSlip * 10f;
|
||||
effect.InitialVelocity = Vehicle.Body.Velocity / 3 + hitForwardDirection * LongitudinalSlip * 10f;
|
||||
effect.ForceDirection = 0;
|
||||
effect.SheetSequence = true;
|
||||
effect.SequenceSpeed = 0.5f;
|
||||
|
||||
@@ -24,15 +24,10 @@ public partial class VeloXWheel : Component
|
||||
|
||||
public float BaseInertia => Mass * (Radius * Radius); // kg·m²
|
||||
[Property] public float Inertia { get; set; } = 1.5f; // kg·m²
|
||||
public float SideSlip => SlipAngle;
|
||||
public float ForwardSlip => DynamicSlipRatio;
|
||||
[Sync] public float Torque { get; set; }
|
||||
[Sync, Range( 0, 1 )] public float Brake { get; set; }
|
||||
[Property] public bool IsFront { get; protected set; }
|
||||
[Property] public float SteerMultiplier { get; set; }
|
||||
|
||||
public float RPM { get => AngularVelocity * 60f / MathF.Tau; set => AngularVelocity = value / (60 / MathF.Tau); }
|
||||
[Sync] internal float DistributionFactor { get; set; }
|
||||
|
||||
private Vector3 StartPos { get; set; }
|
||||
private static Rotation CylinderOffset = Rotation.FromRoll( 90 );
|
||||
@@ -40,25 +35,19 @@ public partial class VeloXWheel : Component
|
||||
[Sync] public bool IsOnGround { get; private set; }
|
||||
|
||||
|
||||
[Property] public float DriveTorque => Torque;
|
||||
[Property] public float BrakeTorque => Brake * 5000f;
|
||||
[Property] public float DriveTorque { get; set; }
|
||||
[Property] public float BrakeTorque { get; set; }
|
||||
|
||||
public float Compression { get; protected set; } // meters
|
||||
public float LastLength { get; protected set; } // meters
|
||||
public float Fz { get; protected set; } // N
|
||||
public float AngularVelocity { get; protected set; } // rad/s
|
||||
public float Fx { get; protected set; } // N
|
||||
public float Fy { get; protected set; } // N
|
||||
public float RollAngle { get; protected set; } // degrees
|
||||
|
||||
|
||||
private VeloXBase Vehicle;
|
||||
[Sync] public Vector3 ContactNormal { get; protected set; }
|
||||
[Sync] public Vector3 ContactPosition { get; protected set; }
|
||||
public float SlipRatio { get; protected set; }
|
||||
public float SlipAngle { get; protected set; }
|
||||
public float DynamicSlipRatio { get; protected set; }
|
||||
public float DynamicSlipAngle { get; protected set; }
|
||||
Rotation TransformRotationSteer => Vehicle.WorldTransform.RotationToWorld( Vehicle.SteerAngle * SteerMultiplier );
|
||||
|
||||
protected override void OnAwake()
|
||||
@@ -96,15 +85,9 @@ public partial class VeloXWheel : Component
|
||||
internal void StepPhys( VeloXBase vehicle, in float dt )
|
||||
{
|
||||
|
||||
var _rigidbody = vehicle.Body;
|
||||
const int numSamples = 3;
|
||||
float halfWidth = Width.MeterToInch() * 0.5f;
|
||||
|
||||
var ang = vehicle.WorldTransform.RotationToWorld( vehicle.SteerAngle * SteerMultiplier );
|
||||
|
||||
Vector3 right = Vector3.VectorPlaneProject( ang.Right, Vector3.Up ).Normal;
|
||||
|
||||
|
||||
int hitCount = 0;
|
||||
WheelTraceData wheelTraceData = new();
|
||||
for ( int i = 0; i < numSamples; i++ )
|
||||
@@ -123,7 +106,6 @@ public partial class VeloXWheel : Component
|
||||
|
||||
IsOnGround = true;
|
||||
|
||||
//// Average all contacts
|
||||
Fz = Math.Max( wheelTraceData.Force / hitCount, 0 );
|
||||
Compression = wheelTraceData.Compression / hitCount;
|
||||
ContactNormal = (wheelTraceData.ContactNormal / hitCount).Normal;
|
||||
@@ -131,32 +113,7 @@ public partial class VeloXWheel : Component
|
||||
//DoSuspensionSounds( vehicle, (RestLength - Compression) * 0.8f);
|
||||
LastLength = RestLength - Compression;
|
||||
|
||||
//DebugOverlay.Normal( ContactPosition, ContactNormal * Fz / 1000 );
|
||||
// Apply suspension force
|
||||
//_rigidbody.ApplyForceAt( ContactPosition, ContactNormal * Fz.MeterToInch() );
|
||||
|
||||
UpdateHitVariables();
|
||||
// Friction
|
||||
|
||||
Vector3 forward = ContactNormal.Cross( right ).Normal;
|
||||
right = Rotation.FromAxis( ContactNormal, 90f ) * forward;
|
||||
|
||||
var velAtContact = _rigidbody.GetVelocityAtPoint( ContactPosition + vehicle.Body.MassCenter ) * 0.0254f;
|
||||
float vx = Vector3.Dot( velAtContact, forward );
|
||||
float vy = Vector3.Dot( velAtContact, right );
|
||||
float wheelLinearVel = AngularVelocity * Radius;
|
||||
|
||||
float creepVel = 0.5f;
|
||||
SlipRatio = (wheelLinearVel - vx) / (MathF.Abs( vx ) + creepVel);
|
||||
SlipAngle = MathX.RadianToDegree( MathF.Atan2( vy, MathF.Abs( vx ) + creepVel ) );
|
||||
|
||||
float latCoeff = 1.0f - MathF.Exp( -MathF.Max( MathF.Abs( vx ), 1f ) * dt / 0.01f );
|
||||
float longCoeff = 1.0f - MathF.Exp( -MathF.Max( MathF.Abs( vx ), 1f ) * dt / 0.01f );
|
||||
|
||||
DynamicSlipAngle += (SlipAngle - DynamicSlipAngle) * latCoeff;
|
||||
DynamicSlipRatio += (SlipRatio - DynamicSlipRatio) * longCoeff;
|
||||
|
||||
|
||||
UpdateFriction( dt );
|
||||
}
|
||||
else
|
||||
@@ -165,8 +122,6 @@ public partial class VeloXWheel : Component
|
||||
// Wheel is off the ground
|
||||
Compression = 0f;
|
||||
Fz = 0f;
|
||||
Fx = 0f;
|
||||
Fy = 0f;
|
||||
ContactNormal = Vector3.Up;
|
||||
ContactPosition = WorldPosition;
|
||||
}
|
||||
@@ -225,22 +180,20 @@ public partial class VeloXWheel : Component
|
||||
{
|
||||
if ( IsProxy )
|
||||
return;
|
||||
StepRotation( Vehicle, dt );
|
||||
if ( AutoSimulate )
|
||||
StepPhys( Vehicle, dt );
|
||||
StepRotation( Vehicle, dt );
|
||||
}
|
||||
|
||||
const float HubCoulombNm = 20f;
|
||||
const float HubViscous = 0.1f;
|
||||
private void StepRotation( VeloXBase vehicle, in float dt )
|
||||
{
|
||||
float inertia = MathF.Max( 1f, Inertia );
|
||||
|
||||
float roadTorque = Fx * Radius;
|
||||
float roadTorque = ForwardFriction.Speed * Radius;
|
||||
float externalTorque = DriveTorque - roadTorque;
|
||||
float rollingResistanceTorque = Fz * Radius * SurfaceResistance;
|
||||
|
||||
const float HubCoulombNm = 20f;
|
||||
const float HubViscous = 0.1f;
|
||||
|
||||
float coulombTorque = BrakeTorque + rollingResistanceTorque + HubCoulombNm;
|
||||
|
||||
float omega = AngularVelocity;
|
||||
@@ -251,11 +204,8 @@ public partial class VeloXWheel : Component
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// viscous decay
|
||||
if ( HubViscous > 0f ) omega *= MathF.Exp( -(HubViscous / inertia) * dt );
|
||||
|
||||
// Coulomb drag
|
||||
if ( coulombTorque > 0f && omega != 0f )
|
||||
{
|
||||
float dir = MathF.Sign( omega );
|
||||
@@ -266,7 +216,7 @@ public partial class VeloXWheel : Component
|
||||
|
||||
if ( MathF.Abs( omega ) < 0.01f ) omega = 0f;
|
||||
}
|
||||
AngularVelocity = omega; // wider sanity range
|
||||
AngularVelocity = omega;
|
||||
|
||||
RollAngle += MathX.RadianToDegree( AngularVelocity ) * dt;
|
||||
RollAngle = (RollAngle % 360f + 360f) % 360f;
|
||||
|
||||
Reference in New Issue
Block a user