cumulative update
This commit is contained in:
parent
e12b75be45
commit
66fcc6a2bb
@ -12,6 +12,7 @@
|
|||||||
"NetworkMode": 2,
|
"NetworkMode": 2,
|
||||||
"NetworkInterpolation": true,
|
"NetworkInterpolation": true,
|
||||||
"NetworkOrphaned": 0,
|
"NetworkOrphaned": 0,
|
||||||
|
"NetworkTransmit": true,
|
||||||
"OwnerTransfer": 1,
|
"OwnerTransfer": 1,
|
||||||
"Components": [],
|
"Components": [],
|
||||||
"Children": [
|
"Children": [
|
||||||
@ -28,6 +29,7 @@
|
|||||||
"NetworkMode": 2,
|
"NetworkMode": 2,
|
||||||
"NetworkInterpolation": true,
|
"NetworkInterpolation": true,
|
||||||
"NetworkOrphaned": 0,
|
"NetworkOrphaned": 0,
|
||||||
|
"NetworkTransmit": true,
|
||||||
"OwnerTransfer": 1,
|
"OwnerTransfer": 1,
|
||||||
"Components": [
|
"Components": [
|
||||||
{
|
{
|
||||||
@ -197,7 +199,7 @@
|
|||||||
"FaceVelocity": false,
|
"FaceVelocity": false,
|
||||||
"FogStrength": 1,
|
"FogStrength": 1,
|
||||||
"LeadingTrail": true,
|
"LeadingTrail": true,
|
||||||
"Lighting": false,
|
"Lighting": true,
|
||||||
"MotionBlur": false,
|
"MotionBlur": false,
|
||||||
"OnComponentDestroy": null,
|
"OnComponentDestroy": null,
|
||||||
"OnComponentDisabled": null,
|
"OnComponentDisabled": null,
|
||||||
@ -206,6 +208,7 @@
|
|||||||
"OnComponentStart": null,
|
"OnComponentStart": null,
|
||||||
"OnComponentUpdate": null,
|
"OnComponentUpdate": null,
|
||||||
"Opaque": false,
|
"Opaque": false,
|
||||||
|
"PlaybackSpeed": 1,
|
||||||
"RenderOptions": {
|
"RenderOptions": {
|
||||||
"GameLayer": true,
|
"GameLayer": true,
|
||||||
"OverlayLayer": false,
|
"OverlayLayer": false,
|
||||||
@ -215,7 +218,7 @@
|
|||||||
"RotationOffset": 0,
|
"RotationOffset": 0,
|
||||||
"Scale": 1,
|
"Scale": 1,
|
||||||
"Shadows": true,
|
"Shadows": true,
|
||||||
"SortMode": "Unsorted",
|
"SortMode": "ByDistance",
|
||||||
"Sprite": {
|
"Sprite": {
|
||||||
"$compiler": "embed",
|
"$compiler": "embed",
|
||||||
"$source": null,
|
"$source": null,
|
||||||
@ -228,7 +231,8 @@
|
|||||||
"LoopMode": "Loop",
|
"LoopMode": "Loop",
|
||||||
"Frames": [
|
"Frames": [
|
||||||
{
|
{
|
||||||
"Texture": "textures/smoketexturesheet.vtex"
|
"Texture": "textures/smoketexturesheet.vtex",
|
||||||
|
"BroadcastMessages": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,10 @@ namespace VeloX;
|
|||||||
|
|
||||||
public abstract partial class VeloXBase
|
public abstract partial class VeloXBase
|
||||||
{
|
{
|
||||||
[Feature( "Input" )] internal InputResolver Input { get; set; } = new();
|
internal InputResolver Input { get; set; } = new();
|
||||||
[Feature( "Input" )] public Connection Driver { get => Input.Driver; set => Input.Driver = value; }
|
public Connection Driver { get => Input.Driver; set => Input.Driver = value; }
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsDriver => Connection.Local == Driver;
|
||||||
private bool IsDriverActive => Driver is not null;
|
private bool IsDriverActive => Driver is not null;
|
||||||
|
|
||||||
public Vector2 MouseDelta => IsDriverActive ? Input.MouseDelta : default;
|
public Vector2 MouseDelta => IsDriverActive ? Input.MouseDelta : default;
|
||||||
|
|||||||
@ -52,12 +52,8 @@ public abstract partial class VeloXBase
|
|||||||
v.BrakeTorque = HandbrakeForce;
|
v.BrakeTorque = HandbrakeForce;
|
||||||
}
|
}
|
||||||
|
|
||||||
v.Update( this, in dt );
|
|
||||||
v.DoPhysics( in dt );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Body.Velocity = vehVel;
|
Body.Velocity = vehVel;
|
||||||
Body.AngularVelocity = vehAngVel;
|
Body.AngularVelocity = vehAngVel;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ using System;
|
|||||||
namespace VeloX;
|
namespace VeloX;
|
||||||
|
|
||||||
|
|
||||||
public abstract partial class VeloXBase : Component
|
public abstract partial class VeloXBase : Component, IGameObjectNetworkEvents
|
||||||
{
|
{
|
||||||
[Sync, Change( nameof( OnEngineIgnitionChange ) )]
|
[Sync, Change( nameof( OnEngineIgnitionChange ) )]
|
||||||
public bool EngineIgnition { get; set; }
|
public bool EngineIgnition { get; set; }
|
||||||
@ -26,18 +26,24 @@ public abstract partial class VeloXBase : Component
|
|||||||
|
|
||||||
[Sync( SyncFlags.Interpolate )] public Angles SteerAngle { get; set; }
|
[Sync( SyncFlags.Interpolate )] public Angles SteerAngle { get; set; }
|
||||||
|
|
||||||
public Vector3 LocalVelocity;
|
[Sync( SyncFlags.Interpolate )] public Vector3 LocalVelocity { get; set; }
|
||||||
|
[Sync( SyncFlags.Interpolate )] public Vector3 Velocity { get; set; }
|
||||||
public float ForwardSpeed;
|
public float ForwardSpeed;
|
||||||
public float TotalSpeed;
|
public float TotalSpeed;
|
||||||
|
|
||||||
protected override void OnFixedUpdate()
|
protected override void OnFixedUpdate()
|
||||||
{
|
{
|
||||||
|
if ( !IsProxy )
|
||||||
|
{
|
||||||
|
LocalVelocity = WorldTransform.PointToLocal( WorldPosition + Body.Velocity );
|
||||||
|
Velocity = Body.Velocity;
|
||||||
|
}
|
||||||
|
ForwardSpeed = LocalVelocity.x;
|
||||||
|
|
||||||
|
TotalSpeed = LocalVelocity.Length;
|
||||||
|
|
||||||
if ( IsProxy )
|
if ( IsProxy )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LocalVelocity = WorldTransform.PointToLocal( WorldPosition + Body.Velocity );
|
|
||||||
ForwardSpeed = LocalVelocity.x;
|
|
||||||
TotalSpeed = LocalVelocity.Length;
|
|
||||||
Body.PhysicsBody.Mass = Mass;
|
Body.PhysicsBody.Mass = Mass;
|
||||||
|
|
||||||
FixedUpdate();
|
FixedUpdate();
|
||||||
@ -50,4 +56,10 @@ public abstract partial class VeloXBase : Component
|
|||||||
PhysicsSimulate();
|
PhysicsSimulate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void IGameObjectNetworkEvents.NetworkOwnerChanged( Connection newOwner, Connection previousOwner )
|
||||||
|
//{
|
||||||
|
|
||||||
|
// Driver = newOwner;
|
||||||
|
// EngineIgnition = Driver is not null;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,9 +4,6 @@ namespace VeloX;
|
|||||||
|
|
||||||
public struct Friction
|
public struct Friction
|
||||||
{
|
{
|
||||||
public float SlipCoef { get; set; }
|
|
||||||
public float ForceCoef { get; set; }
|
|
||||||
|
|
||||||
public float Force { get; set; }
|
public float Force { get; set; }
|
||||||
public float Slip { get; set; }
|
public float Slip { get; set; }
|
||||||
public float Speed { get; set; }
|
public float Speed { get; set; }
|
||||||
|
|||||||
@ -35,8 +35,6 @@ public partial class VeloXWheel
|
|||||||
public float CounterTorque { get; private set; }
|
public float CounterTorque { get; private set; }
|
||||||
|
|
||||||
//[Property, Range( 0, 2 )] public float BrakeMult { get; set; } = 1f;
|
//[Property, Range( 0, 2 )] public float BrakeMult { get; set; } = 1f;
|
||||||
public Friction ForwardFriction = new();
|
|
||||||
public Friction SidewayFriction = new();
|
|
||||||
public Vector3 FrictionForce;
|
public Vector3 FrictionForce;
|
||||||
|
|
||||||
|
|
||||||
@ -47,20 +45,32 @@ public partial class VeloXWheel
|
|||||||
public Vector3 ContactRight => hitSidewaysDirection;
|
public Vector3 ContactRight => hitSidewaysDirection;
|
||||||
public Vector3 ContactForward => hitForwardDirection;
|
public Vector3 ContactForward => hitForwardDirection;
|
||||||
|
|
||||||
public float LongitudinalSlip => ForwardFriction.Slip;
|
public float LongitudinalSlip => sx;
|
||||||
|
public float LongitudinalSpeed => vx;
|
||||||
public float LongitudinalSpeed => ForwardFriction.Speed;
|
|
||||||
public bool IsSkiddingLongitudinally => NormalizedLongitudinalSlip > 0.35f;
|
public bool IsSkiddingLongitudinally => NormalizedLongitudinalSlip > 0.35f;
|
||||||
public float NormalizedLongitudinalSlip => Math.Clamp( Math.Abs( LongitudinalSlip ), 0, 1 );
|
public float NormalizedLongitudinalSlip => Math.Clamp( Math.Abs( LongitudinalSlip ), 0, 1 );
|
||||||
|
|
||||||
|
public float LateralSlip => sy;
|
||||||
public float LateralSlip => SidewayFriction.Slip;
|
public float LateralSpeed => vy;
|
||||||
public float LateralSpeed => SidewayFriction.Speed;
|
|
||||||
public bool IsSkiddingLaterally => NormalizedLateralSlip > 0.35f;
|
public bool IsSkiddingLaterally => NormalizedLateralSlip > 0.35f;
|
||||||
public float NormalizedLateralSlip => Math.Clamp( Math.Abs( LateralSlip ), 0, 1 );
|
public float NormalizedLateralSlip => Math.Clamp( Math.Abs( LateralSlip ), 0, 1 );
|
||||||
|
|
||||||
public bool IsSkidding => IsSkiddingLaterally || IsSkiddingLongitudinally;
|
public bool IsSkidding => IsSkiddingLaterally || IsSkiddingLongitudinally;
|
||||||
public float NormalizedSlip => (NormalizedLateralSlip + NormalizedLongitudinalSlip) / 2f;
|
public float NormalizedSlip => (NormalizedLateralSlip + NormalizedLongitudinalSlip) / 2f;
|
||||||
|
|
||||||
|
|
||||||
|
// speed
|
||||||
|
[Sync] private float vx { get; set; }
|
||||||
|
[Sync] private float vy { get; set; }
|
||||||
|
|
||||||
|
// force
|
||||||
|
[Sync] private float fx { get; set; }
|
||||||
|
[Sync] private float fy { get; set; }
|
||||||
|
|
||||||
|
// slip
|
||||||
|
[Sync] private float sx { get; set; }
|
||||||
|
[Sync] private float sy { get; set; }
|
||||||
|
|
||||||
private void UpdateHitVariables()
|
private void UpdateHitVariables()
|
||||||
{
|
{
|
||||||
if ( IsOnGround )
|
if ( IsOnGround )
|
||||||
@ -70,13 +80,13 @@ public partial class VeloXWheel
|
|||||||
hitForwardDirection = ContactNormal.Cross( TransformRotationSteer.Right ).Normal;
|
hitForwardDirection = ContactNormal.Cross( TransformRotationSteer.Right ).Normal;
|
||||||
hitSidewaysDirection = Rotation.FromAxis( ContactNormal, 90f ) * hitForwardDirection;
|
hitSidewaysDirection = Rotation.FromAxis( ContactNormal, 90f ) * hitForwardDirection;
|
||||||
|
|
||||||
ForwardFriction.Speed = hitContactVelocity.Dot( hitForwardDirection ).InchToMeter();
|
vx = hitContactVelocity.Dot( hitForwardDirection ).InchToMeter();
|
||||||
SidewayFriction.Speed = hitContactVelocity.Dot( hitSidewaysDirection ).InchToMeter();
|
vy = hitContactVelocity.Dot( hitSidewaysDirection ).InchToMeter();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ForwardFriction = new();
|
vx = 0;
|
||||||
SidewayFriction = new();
|
vy = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,9 +122,9 @@ public partial class VeloXWheel
|
|||||||
float slipLoadModifier = 1f - loadPercent * 0.4f;
|
float slipLoadModifier = 1f - loadPercent * 0.4f;
|
||||||
|
|
||||||
float mass = Vehicle.Body.Mass;
|
float mass = Vehicle.Body.Mass;
|
||||||
float absForwardSpeed = Math.Abs( ForwardFriction.Speed );
|
float absForwardSpeed = Math.Abs( vx );
|
||||||
float forwardForceClamp = mass * LoadContribution * absForwardSpeed * invDt;
|
float forwardForceClamp = mass * LoadContribution * absForwardSpeed * invDt;
|
||||||
float absSideSpeed = Math.Abs( SidewayFriction.Speed );
|
float absSideSpeed = Math.Abs( vy );
|
||||||
float sideForceClamp = mass * LoadContribution * absSideSpeed * invDt;
|
float sideForceClamp = mass * LoadContribution * absSideSpeed * invDt;
|
||||||
|
|
||||||
float forwardSpeedClamp = 1.5f * (dt / 0.005f);
|
float forwardSpeedClamp = 1.5f * (dt / 0.005f);
|
||||||
@ -124,7 +134,7 @@ public partial class VeloXWheel
|
|||||||
float peakForwardFrictionForce = 11000 * (1 - MathF.Exp( -0.00014f * forwardLoadFactor ));
|
float peakForwardFrictionForce = 11000 * (1 - MathF.Exp( -0.00014f * forwardLoadFactor ));
|
||||||
float absCombinedBrakeTorque = Math.Max( 0, brakeTorque + RollingResistanceTorque );
|
float absCombinedBrakeTorque = Math.Max( 0, brakeTorque + RollingResistanceTorque );
|
||||||
|
|
||||||
float signedCombinedBrakeTorque = absCombinedBrakeTorque * -Math.Sign( ForwardFriction.Speed );
|
float signedCombinedBrakeTorque = absCombinedBrakeTorque * (vx > 0 ? -1 : 1);
|
||||||
float signedCombinedBrakeForce = signedCombinedBrakeTorque * invRadius;
|
float signedCombinedBrakeForce = signedCombinedBrakeTorque * invRadius;
|
||||||
float motorForce = motorTorque * invRadius;
|
float motorForce = motorTorque * invRadius;
|
||||||
float forwardInputForce = motorForce + signedCombinedBrakeForce;
|
float forwardInputForce = motorForce + signedCombinedBrakeForce;
|
||||||
@ -134,7 +144,7 @@ public partial class VeloXWheel
|
|||||||
float maxForwardForce = Math.Min( peakForwardFrictionForce, forwardForceClamp );
|
float maxForwardForce = Math.Min( peakForwardFrictionForce, forwardForceClamp );
|
||||||
|
|
||||||
maxForwardForce = absMotorTorque < absBrakeTorque ? maxForwardForce : peakForwardFrictionForce;
|
maxForwardForce = absMotorTorque < absBrakeTorque ? maxForwardForce : peakForwardFrictionForce;
|
||||||
ForwardFriction.Force = forwardInputForce > maxForwardForce ? maxForwardForce
|
fx = forwardInputForce > maxForwardForce ? maxForwardForce
|
||||||
: forwardInputForce < -maxForwardForce ? -maxForwardForce : forwardInputForce;
|
: forwardInputForce < -maxForwardForce ? -maxForwardForce : forwardInputForce;
|
||||||
|
|
||||||
wheelIsBlocked = false;
|
wheelIsBlocked = false;
|
||||||
@ -153,14 +163,14 @@ public partial class VeloXWheel
|
|||||||
AngularVelocity += combinedWheelForce * mRadius * invInertia * dt;
|
AngularVelocity += combinedWheelForce * mRadius * invInertia * dt;
|
||||||
|
|
||||||
// Surface (corrective) force
|
// Surface (corrective) force
|
||||||
float noSlipAngularVelocity = ForwardFriction.Speed * invRadius;
|
float noSlipAngularVelocity = vx * invRadius;
|
||||||
float angularVelocityError = AngularVelocity - noSlipAngularVelocity;
|
float angularVelocityError = AngularVelocity - noSlipAngularVelocity;
|
||||||
|
|
||||||
float angularVelocityCorrectionForce = Math.Clamp( -angularVelocityError * inertia * invRadius * invDt, -maxForwardForce, maxForwardForce );
|
float angularVelocityCorrectionForce = Math.Clamp( -angularVelocityError * inertia * invRadius * invDt, -maxForwardForce, maxForwardForce );
|
||||||
if ( absMotorTorque < absBrakeTorque && Math.Abs( wheelForceClampOverflow ) > Math.Abs( angularVelocityCorrectionForce ) )
|
if ( absMotorTorque < absBrakeTorque && Math.Abs( wheelForceClampOverflow ) > Math.Abs( angularVelocityCorrectionForce ) )
|
||||||
{
|
{
|
||||||
wheelIsBlocked = true;
|
wheelIsBlocked = true;
|
||||||
AngularVelocity += ForwardFriction.Speed > 0 ? 1e-10f : -1e-10f;
|
AngularVelocity += vx > 0 ? 1e-10f : -1e-10f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -178,24 +188,24 @@ public partial class VeloXWheel
|
|||||||
|
|
||||||
float absAngularVelocity = AngularVelocity < 0 ? -AngularVelocity : AngularVelocity;
|
float absAngularVelocity = AngularVelocity < 0 ? -AngularVelocity : AngularVelocity;
|
||||||
float maxCounterTorque = inertia * absAngularVelocity;
|
float maxCounterTorque = inertia * absAngularVelocity;
|
||||||
CounterTorque = Math.Clamp( (signedCombinedBrakeForce - ForwardFriction.Force) * mRadius, -maxCounterTorque, maxCounterTorque );
|
CounterTorque = Math.Clamp( (signedCombinedBrakeForce - fx) * mRadius, -maxCounterTorque, maxCounterTorque );
|
||||||
|
|
||||||
ForwardFriction.Slip = (ForwardFriction.Speed - AngularVelocity * mRadius) / clampedAbsForwardSpeed;
|
sx = (vx - AngularVelocity * mRadius) / clampedAbsForwardSpeed;
|
||||||
ForwardFriction.Slip *= slipLoadModifier;
|
sx *= slipLoadModifier;
|
||||||
|
|
||||||
SidewayFriction.Slip = MathF.Atan2( SidewayFriction.Speed, clampedAbsForwardSpeed );
|
sy = MathF.Atan2( vy, clampedAbsForwardSpeed );
|
||||||
SidewayFriction.Slip *= slipLoadModifier;
|
sy *= slipLoadModifier;
|
||||||
|
|
||||||
float sideSlipSign = SidewayFriction.Slip > 0 ? 1 : -1;
|
float sideSlipSign = sy > 0 ? 1 : -1;
|
||||||
float absSideSlip = Math.Abs( SidewayFriction.Slip );
|
float absSideSlip = Math.Abs( sy );
|
||||||
float peakSideFrictionForce = 18000 * (1 - MathF.Exp( -0.0001f * sideLoadFactor ));
|
float peakSideFrictionForce = 18000 * (1 - MathF.Exp( -0.0001f * sideLoadFactor ));
|
||||||
|
|
||||||
float sideForce = -sideSlipSign * Tire.Evaluate( absSideSlip ) * peakSideFrictionForce;
|
float sideForce = -sideSlipSign * Tire.Evaluate( absSideSlip ) * peakSideFrictionForce;
|
||||||
SidewayFriction.Force = Math.Clamp( sideForce, -sideForceClamp, sideForceClamp );
|
fy = Math.Clamp( sideForce, -sideForceClamp, sideForceClamp );
|
||||||
|
|
||||||
// Calculate effect of camber on friction
|
// Calculate effect of camber on friction
|
||||||
float camberFrictionCoeff = Math.Max( 0, Vehicle.WorldRotation.Up.Dot( ContactNormal ) );
|
float camberFrictionCoeff = Math.Max( 0, Vehicle.WorldRotation.Up.Dot( ContactNormal ) );
|
||||||
SidewayFriction.Force *= camberFrictionCoeff;
|
fy *= camberFrictionCoeff;
|
||||||
|
|
||||||
if ( IsOnGround && absForwardSpeed < 0.12f && absSideSpeed < 0.12f )
|
if ( IsOnGround && absForwardSpeed < 0.12f && absSideSpeed < 0.12f )
|
||||||
{
|
{
|
||||||
@ -225,9 +235,9 @@ public partial class VeloXWheel
|
|||||||
|
|
||||||
if ( wheelIsBlocked && absAngularVelocity < 0.5f )
|
if ( wheelIsBlocked && absAngularVelocity < 0.5f )
|
||||||
{
|
{
|
||||||
ForwardFriction.Force += correctiveForce.Dot( hitForwardDirection );
|
fx += correctiveForce.Dot( hitForwardDirection );
|
||||||
}
|
}
|
||||||
SidewayFriction.Force += correctiveForce.Dot( hitSidewaysDirection );
|
fy += correctiveForce.Dot( hitSidewaysDirection );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -235,52 +245,21 @@ public partial class VeloXWheel
|
|||||||
lowSpeedReferenceIsSet = false;
|
lowSpeedReferenceIsSet = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fx = Math.Clamp( fx, -peakForwardFrictionForce, peakForwardFrictionForce );
|
||||||
|
fy = Math.Clamp( fy, -peakSideFrictionForce, peakSideFrictionForce );
|
||||||
|
|
||||||
//float forwardSlipPercent = -ForwardFriction.Slip / Tire.GetPeakSlip();
|
if ( absForwardSpeed > 0.01f || absAngularVelocity > 0.01f )
|
||||||
//float sideSlipPercent = SidewayFriction.Slip / Tire.GetPeakSlip();
|
{
|
||||||
//float slipCircleLimit = MathF.Sqrt( forwardSlipPercent * forwardSlipPercent + sideSlipPercent * sideSlipPercent );
|
var f = MathF.Sqrt( fx * fx + fy * fy );
|
||||||
//if ( slipCircleLimit > 1f )
|
var d = Math.Abs( new Vector2( sx, sy ).Normal.y );
|
||||||
//{
|
fy = f * d * Math.Sign( fy );
|
||||||
// float beta = MathF.Atan2( sideSlipPercent, forwardSlipPercent * 1.05f );
|
|
||||||
// float sinBeta = MathF.Sin( beta );
|
|
||||||
// float cosBeta = MathF.Cos( beta );
|
|
||||||
|
|
||||||
// float absForwardForce = ForwardFriction.Force < 0 ? -ForwardFriction.Force : ForwardFriction.Force;
|
|
||||||
|
|
||||||
// float absSideForce = SidewayFriction.Force < 0 ? -SidewayFriction.Force : SidewayFriction.Force;
|
|
||||||
// float f = absForwardForce * cosBeta * cosBeta + absSideForce * sinBeta * sinBeta;
|
|
||||||
|
|
||||||
// ForwardFriction.Force = 0.5f * ForwardFriction.Force - f * cosBeta;
|
|
||||||
// SidewayFriction.Force = 0.5f * SidewayFriction.Force - f * sinBeta;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//var slipVector = new Vector2(
|
|
||||||
// ForwardFriction.Slip,
|
|
||||||
// SidewayFriction.Slip
|
|
||||||
//);
|
|
||||||
//if ( slipVector.Length > 0.001f )
|
|
||||||
//{
|
|
||||||
// var frictionDirection = slipVector.Normal;
|
|
||||||
|
|
||||||
// float frictionMagnitude = MathF.Sqrt(
|
|
||||||
// ForwardFriction.Force * ForwardFriction.Force +
|
|
||||||
// SidewayFriction.Force * SidewayFriction.Force
|
|
||||||
// );
|
|
||||||
|
|
||||||
// ForwardFriction.Force = Math.Abs( frictionDirection.x ) * frictionMagnitude * Math.Sign( ForwardFriction.Force );
|
|
||||||
// SidewayFriction.Force = Math.Abs( frictionDirection.y ) * frictionMagnitude * Math.Sign( SidewayFriction.Force );
|
|
||||||
//}
|
|
||||||
|
|
||||||
var f = MathF.Sqrt( ForwardFriction.Force * ForwardFriction.Force + SidewayFriction.Force * SidewayFriction.Force );
|
|
||||||
var d = Math.Abs( new Vector2( ForwardFriction.Slip, SidewayFriction.Slip ).Normal.y );
|
|
||||||
SidewayFriction.Force = f * d * Math.Sign( SidewayFriction.Force );
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
if ( IsOnGround )
|
if ( IsOnGround )
|
||||||
{
|
{
|
||||||
FrictionForce.x = (hitSidewaysDirection.x * SidewayFriction.Force + hitForwardDirection.x * ForwardFriction.Force).MeterToInch();
|
FrictionForce.x = (hitSidewaysDirection.x * fy + hitForwardDirection.x * fx).MeterToInch();
|
||||||
FrictionForce.y = (hitSidewaysDirection.y * SidewayFriction.Force + hitForwardDirection.y * ForwardFriction.Force).MeterToInch();
|
FrictionForce.y = (hitSidewaysDirection.y * fy + hitForwardDirection.y * fx).MeterToInch();
|
||||||
FrictionForce.z = (hitSidewaysDirection.z * SidewayFriction.Force + hitForwardDirection.z * ForwardFriction.Force).MeterToInch();
|
FrictionForce.z = (hitSidewaysDirection.z * fy + hitForwardDirection.z * fx).MeterToInch();
|
||||||
|
|
||||||
//DebugOverlay.Normal( WorldPosition, hitSidewaysDirection * 10, overlay: true, color: Color.Red );
|
//DebugOverlay.Normal( WorldPosition, hitSidewaysDirection * 10, overlay: true, color: Color.Red );
|
||||||
//DebugOverlay.Normal( WorldPosition, hitForwardDirection * 10, overlay: true, color: Color.Green );
|
//DebugOverlay.Normal( WorldPosition, hitForwardDirection * 10, overlay: true, color: Color.Green );
|
||||||
|
|||||||
@ -34,7 +34,7 @@ public partial class VeloXWheel
|
|||||||
{
|
{
|
||||||
GameObject go = new()
|
GameObject go = new()
|
||||||
{
|
{
|
||||||
WorldPosition = ContactPosition + Vehicle.WorldRotation.Down * (Radius.MeterToInch() - 0.01f),
|
WorldPosition = ContactPosition + Vehicle.WorldRotation.Down * (Radius.MeterToInch() - 1f),
|
||||||
WorldRotation = Rotation.LookAt( hitSidewaysDirection )
|
WorldRotation = Rotation.LookAt( hitSidewaysDirection )
|
||||||
};
|
};
|
||||||
_skidMark = go.AddComponent<LineRenderer>();
|
_skidMark = go.AddComponent<LineRenderer>();
|
||||||
@ -53,8 +53,7 @@ public partial class VeloXWheel
|
|||||||
|
|
||||||
protected void UpdateSkid()
|
protected void UpdateSkid()
|
||||||
{
|
{
|
||||||
if ( IsProxy )
|
|
||||||
return;
|
|
||||||
while ( SkidMarks.Count > MaxSkid )
|
while ( SkidMarks.Count > MaxSkid )
|
||||||
{
|
{
|
||||||
SkidMarks.Dequeue()?.DestroyGameObject();
|
SkidMarks.Dequeue()?.DestroyGameObject();
|
||||||
@ -81,7 +80,7 @@ public partial class VeloXWheel
|
|||||||
GameObject go = new()
|
GameObject go = new()
|
||||||
{
|
{
|
||||||
Parent = _skidMark.GameObject,
|
Parent = _skidMark.GameObject,
|
||||||
WorldPosition = ContactPosition + Vehicle.WorldRotation.Down * Radius.MeterToInch(),
|
WorldPosition = ContactPosition + Vehicle.WorldRotation.Down * (Radius.MeterToInch() - 1f),
|
||||||
WorldRotation = Rotation.LookAt( ContactNormal.RotateAround( Vector3.Zero, Rotation.FromRoll( 90 ) ) )
|
WorldRotation = Rotation.LookAt( ContactNormal.RotateAround( Vector3.Zero, Rotation.FromRoll( 90 ) ) )
|
||||||
};
|
};
|
||||||
go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
|
go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
|
||||||
|
|||||||
@ -8,9 +8,8 @@ namespace VeloX;
|
|||||||
|
|
||||||
public partial class VeloXWheel
|
public partial class VeloXWheel
|
||||||
{
|
{
|
||||||
private static readonly GameObject SmokePrefab = GameObject.GetPrefab( "prefabs/particles/tire_smoke.prefab" );
|
|
||||||
|
private GameObject SmokeObject;
|
||||||
private GameObject SmokeObject { get; set; }
|
|
||||||
public const float MIN_DRIFT_ANGLE = 10f;
|
public const float MIN_DRIFT_ANGLE = 10f;
|
||||||
public const float MIN_DRIFT_SPEED = 30f;
|
public const float MIN_DRIFT_SPEED = 30f;
|
||||||
public const float MAX_DRIFT_ANGLE = 110f;
|
public const float MAX_DRIFT_ANGLE = 110f;
|
||||||
@ -19,11 +18,13 @@ public partial class VeloXWheel
|
|||||||
protected override void OnStart()
|
protected override void OnStart()
|
||||||
{
|
{
|
||||||
base.OnStart();
|
base.OnStart();
|
||||||
if ( IsProxy )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( !SmokeObject.IsValid() )
|
SmokeObject = GameObject.GetPrefab( "prefabs/particles/tire_smoke.prefab" ).Clone( new CloneConfig() { Parent = GameObject, StartEnabled = true } );
|
||||||
SmokeObject = GameObject.GetPrefab( "prefabs/particles/tire_smoke.prefab" ).Clone( new CloneConfig() { Parent = GameObject, StartEnabled = true } );
|
SmokeObject.Flags = SmokeObject.Flags.WithFlag( GameObjectFlags.NotNetworked, true );
|
||||||
|
|
||||||
|
var emitter = SmokeObject.Components.Get<ParticleSphereEmitter>( FindMode.EverythingInSelfAndDescendants );
|
||||||
|
emitter.Enabled = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
public float GetSlip()
|
public float GetSlip()
|
||||||
{
|
{
|
||||||
@ -36,12 +37,8 @@ public partial class VeloXWheel
|
|||||||
// return val;
|
// return val;
|
||||||
return val * 5;
|
return val * 5;
|
||||||
}
|
}
|
||||||
protected override void OnUpdate()
|
private void UpdateSmoke()
|
||||||
{
|
{
|
||||||
base.OnUpdate();
|
|
||||||
if ( IsProxy )
|
|
||||||
return;
|
|
||||||
UpdateSkid();
|
|
||||||
SmokeObject.WorldPosition = ContactPosition + Vehicle.WorldRotation.Down * Radius.MeterToInch();
|
SmokeObject.WorldPosition = ContactPosition + Vehicle.WorldRotation.Down * Radius.MeterToInch();
|
||||||
smokeMul = Math.Max( 0, GetSlip() - 3 );
|
smokeMul = Math.Max( 0, GetSlip() - 3 );
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public partial class VeloXWheel : Component
|
|||||||
|
|
||||||
public float RPM { get => AngularVelocity * 60f / MathF.Tau; set => AngularVelocity = value / (60 / MathF.Tau); }
|
public float RPM { get => AngularVelocity * 60f / MathF.Tau; set => AngularVelocity = value / (60 / MathF.Tau); }
|
||||||
|
|
||||||
private Vector3 StartPos { get; set; }
|
[Sync] private Vector3 StartPos { get; set; }
|
||||||
private static Rotation CylinderOffset = Rotation.FromRoll( 90 );
|
private static Rotation CylinderOffset = Rotation.FromRoll( 90 );
|
||||||
|
|
||||||
[Sync] public bool IsOnGround { get; private set; }
|
[Sync] public bool IsOnGround { get; private set; }
|
||||||
@ -39,13 +39,13 @@ public partial class VeloXWheel : Component
|
|||||||
[Property] public float BrakeTorque { get; set; }
|
[Property] public float BrakeTorque { get; set; }
|
||||||
|
|
||||||
public float Compression { get; protected set; } // meters
|
public float Compression { get; protected set; } // meters
|
||||||
public float LastLength { get; protected set; } // meters
|
[Sync( SyncFlags.Interpolate )] public float LastLength { get; protected set; } // meters
|
||||||
public float Fz { get; protected set; } // N
|
public float Fz { get; protected set; } // N
|
||||||
public float AngularVelocity { get; protected set; } // rad/s
|
public float AngularVelocity { get; protected set; } // rad/s
|
||||||
public float RollAngle { get; protected set; } // degrees
|
[Sync( SyncFlags.Interpolate )] public float RollAngle { get; protected set; }
|
||||||
|
|
||||||
|
|
||||||
private VeloXBase Vehicle;
|
public VeloXBase Vehicle { get; private set; }
|
||||||
[Sync] public Vector3 ContactNormal { get; protected set; }
|
[Sync] public Vector3 ContactNormal { get; protected set; }
|
||||||
[Sync] public Vector3 ContactPosition { get; protected set; }
|
[Sync] public Vector3 ContactPosition { get; protected set; }
|
||||||
Rotation TransformRotationSteer => Vehicle.WorldTransform.RotationToWorld( Vehicle.SteerAngle * SteerMultiplier );
|
Rotation TransformRotationSteer => Vehicle.WorldTransform.RotationToWorld( Vehicle.SteerAngle * SteerMultiplier );
|
||||||
@ -59,15 +59,9 @@ public partial class VeloXWheel : Component
|
|||||||
Inertia = BaseInertia;
|
Inertia = BaseInertia;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Update( VeloXBase vehicle, in float dt )
|
private void UpdateVisuals()
|
||||||
{
|
{
|
||||||
UpdateVisuals( vehicle, dt );
|
WorldRotation = Vehicle.WorldTransform.RotationToWorld( Vehicle.SteerAngle * SteerMultiplier ).RotateAroundAxis( Vector3.Right, -RollAngle );
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateVisuals( VeloXBase vehicle, in float dt )
|
|
||||||
{
|
|
||||||
WorldRotation = vehicle.WorldTransform.RotationToWorld( vehicle.SteerAngle * SteerMultiplier ).RotateAroundAxis( Vector3.Right, -RollAngle );
|
|
||||||
LocalPosition = StartPos + Vector3.Down * LastLength.MeterToInch();
|
LocalPosition = StartPos + Vector3.Down * LastLength.MeterToInch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,4 +207,15 @@ public partial class VeloXWheel : Component
|
|||||||
RollAngle += MathX.RadianToDegree( AngularVelocity ) * dt;
|
RollAngle += MathX.RadianToDegree( AngularVelocity ) * dt;
|
||||||
RollAngle = (RollAngle % 360f + 360f) % 360f;
|
RollAngle = (RollAngle % 360f + 360f) % 360f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnFixedUpdate()
|
||||||
|
{
|
||||||
|
|
||||||
|
UpdateSmoke();
|
||||||
|
}
|
||||||
|
protected override void OnUpdate()
|
||||||
|
{
|
||||||
|
UpdateVisuals();
|
||||||
|
UpdateSkid();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using Sandbox;
|
using Sandbox;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using static Sandbox.Services.Inventory;
|
|
||||||
namespace VeloX;
|
namespace VeloX;
|
||||||
|
|
||||||
internal sealed class WheelManager : GameObjectSystem
|
internal sealed class WheelManager : GameObjectSystem
|
||||||
@ -23,17 +22,17 @@ internal sealed class WheelManager : GameObjectSystem
|
|||||||
if ( !wheels.Any() ) return;
|
if ( !wheels.Any() ) return;
|
||||||
|
|
||||||
var timeDelta = Time.Delta;
|
var timeDelta = Time.Delta;
|
||||||
Sandbox.Utility.Parallel.ForEach( wheels, item =>
|
//Sandbox.Utility.Parallel.ForEach( wheels, item =>
|
||||||
{
|
//{
|
||||||
if ( !item.IsProxy && item.IsValid() )
|
|
||||||
item.DoPhysics( timeDelta );
|
|
||||||
} );
|
|
||||||
//foreach ( var item in wheels )
|
|
||||||
// if ( !item.IsProxy && item.IsValid() )
|
// if ( !item.IsProxy && item.IsValid() )
|
||||||
// item.DoPhysics( timeDelta );
|
// item.DoPhysics( timeDelta );
|
||||||
|
//} );
|
||||||
|
foreach ( var item in wheels )
|
||||||
|
if ( item.IsValid() && !item.IsProxy )
|
||||||
|
item.DoPhysics( timeDelta );
|
||||||
|
|
||||||
foreach ( var wheel in wheels )
|
foreach ( var wheel in wheels )
|
||||||
if ( !wheel.IsProxy && wheel.IsValid() )
|
if ( wheel.IsValid() && !wheel.IsProxy)
|
||||||
wheel.UpdateForce();
|
wheel.UpdateForce();
|
||||||
|
|
||||||
//sw.Stop();
|
//sw.Stop();
|
||||||
@ -50,15 +49,15 @@ internal sealed class WheelManager : GameObjectSystem
|
|||||||
if ( !engines.Any() ) return;
|
if ( !engines.Any() ) return;
|
||||||
|
|
||||||
var timeDelta = Time.Delta;
|
var timeDelta = Time.Delta;
|
||||||
Sandbox.Utility.Parallel.ForEach( engines, item =>
|
//Sandbox.Utility.Parallel.ForEach( engines, item =>
|
||||||
{
|
//{
|
||||||
foreach ( var wheel in engines )
|
// foreach ( var wheel in engines )
|
||||||
if ( !wheel.IsProxy && wheel.IsValid() )
|
// if ( !wheel.IsProxy && wheel.IsValid() )
|
||||||
wheel.UpdateEngine( timeDelta );
|
// wheel.UpdateEngine( timeDelta );
|
||||||
} );
|
//} );
|
||||||
//foreach ( var wheel in engines )
|
foreach ( var wheel in engines )
|
||||||
// if ( !wheel.IsProxy && wheel.IsValid() )
|
if ( wheel.IsValid() )
|
||||||
// wheel.UpdateEngine( timeDelta );
|
wheel.UpdateEngine( timeDelta );
|
||||||
|
|
||||||
|
|
||||||
//sw.Stop();
|
//sw.Stop();
|
||||||
|
|||||||
@ -7,23 +7,14 @@ namespace VeloX;
|
|||||||
[Title( "VeloX - Car" )]
|
[Title( "VeloX - Car" )]
|
||||||
public partial class VeloXCar : VeloXBase
|
public partial class VeloXCar : VeloXBase
|
||||||
{
|
{
|
||||||
|
|
||||||
protected override void FixedUpdate()
|
|
||||||
{
|
|
||||||
|
|
||||||
UpdateInput();
|
|
||||||
PhysicsSimulate();
|
|
||||||
UpdateABS();
|
|
||||||
UpdateESC();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnFixedUpdate()
|
protected override void OnFixedUpdate()
|
||||||
{
|
{
|
||||||
if ( IsProxy )
|
|
||||||
return;
|
|
||||||
|
|
||||||
base.OnFixedUpdate();
|
base.OnFixedUpdate();
|
||||||
|
|
||||||
|
if ( IsProxy )
|
||||||
|
return;
|
||||||
|
UpdateABS();
|
||||||
|
UpdateESC();
|
||||||
var dt = Time.Delta;
|
var dt = Time.Delta;
|
||||||
//EngineThink( dt );
|
//EngineThink( dt );
|
||||||
SimulateAerodinamics( dt );
|
SimulateAerodinamics( dt );
|
||||||
|
|||||||
@ -10,7 +10,7 @@ namespace VeloX;
|
|||||||
public class EngineStreamPlayer( EngineStream stream ) : IDisposable
|
public class EngineStreamPlayer( EngineStream stream ) : IDisposable
|
||||||
{
|
{
|
||||||
|
|
||||||
private static readonly Mixer EngineMixer = Mixer.FindMixerByName( "Car Engine" );
|
private static readonly Mixer EngineMixer = Mixer.FindMixerByName( "Engine" );
|
||||||
public EngineStream Stream { get; set; } = stream;
|
public EngineStream Stream { get; set; } = stream;
|
||||||
|
|
||||||
public EngineState EngineState { get; set; }
|
public EngineState EngineState { get; set; }
|
||||||
@ -26,7 +26,7 @@ public class EngineStreamPlayer( EngineStream stream ) : IDisposable
|
|||||||
|
|
||||||
public void Update( float deltaTime, Vector3 position, bool isLocal = false )
|
public void Update( float deltaTime, Vector3 position, bool isLocal = false )
|
||||||
{
|
{
|
||||||
|
|
||||||
var globalPitch = 1.0f;
|
var globalPitch = 1.0f;
|
||||||
|
|
||||||
// Gear wobble effect
|
// Gear wobble effect
|
||||||
@ -51,7 +51,7 @@ public class EngineStreamPlayer( EngineStream stream ) : IDisposable
|
|||||||
foreach ( var (id, layer) in Stream.Layers )
|
foreach ( var (id, layer) in Stream.Layers )
|
||||||
{
|
{
|
||||||
EngineSounds.TryGetValue( layer, out var channel );
|
EngineSounds.TryGetValue( layer, out var channel );
|
||||||
|
|
||||||
if ( !channel.IsValid() && layer.AudioPath.IsValid() )
|
if ( !channel.IsValid() && layer.AudioPath.IsValid() )
|
||||||
{
|
{
|
||||||
channel = Sound.PlayFile( layer.AudioPath );
|
channel = Sound.PlayFile( layer.AudioPath );
|
||||||
@ -103,6 +103,7 @@ public class EngineStreamPlayer( EngineStream stream ) : IDisposable
|
|||||||
channel.Position = position;
|
channel.Position = position;
|
||||||
channel.ListenLocal = isLocal;
|
channel.ListenLocal = isLocal;
|
||||||
channel.Paused = EngineSoundPaused || layer.IsMuted;
|
channel.Paused = EngineSoundPaused || layer.IsMuted;
|
||||||
|
channel.FollowParent = true;
|
||||||
channel.TargetMixer = EngineMixer;
|
channel.TargetMixer = EngineMixer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user