greatly simplify movement logic
This commit is contained in:
parent
06e368dad5
commit
6d53bf8018
@ -131,6 +131,7 @@ GameObject:
|
|||||||
- component: {fileID: 330585545}
|
- component: {fileID: 330585545}
|
||||||
- component: {fileID: 330585544}
|
- component: {fileID: 330585544}
|
||||||
- component: {fileID: 330585547}
|
- component: {fileID: 330585547}
|
||||||
|
- component: {fileID: 330585548}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Main Camera
|
m_Name: Main Camera
|
||||||
m_TagString: MainCamera
|
m_TagString: MainCamera
|
||||||
@ -179,7 +180,7 @@ Camera:
|
|||||||
height: 1
|
height: 1
|
||||||
near clip plane: 0.3
|
near clip plane: 0.3
|
||||||
far clip plane: 1000
|
far clip plane: 1000
|
||||||
field of view: 60
|
field of view: 60.000004
|
||||||
orthographic: 0
|
orthographic: 0
|
||||||
orthographic size: 5
|
orthographic size: 5
|
||||||
m_Depth: -1
|
m_Depth: -1
|
||||||
@ -205,8 +206,8 @@ Transform:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 330585543}
|
m_GameObject: {fileID: 330585543}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0.18910757, y: -0.000000014030909, z: 0.0000000027021065, w: 0.9819564}
|
||||||
m_LocalPosition: {x: 0, y: 1, z: -10}
|
m_LocalPosition: {x: 2.631, y: 3.709, z: -3.085}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
@ -256,6 +257,38 @@ MonoBehaviour:
|
|||||||
m_MipBias: 0
|
m_MipBias: 0
|
||||||
m_VarianceClampScale: 0.9
|
m_VarianceClampScale: 0.9
|
||||||
m_ContrastAdaptiveSharpening: 0
|
m_ContrastAdaptiveSharpening: 0
|
||||||
|
--- !u!114 &330585548
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 330585543}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 72ece51f2901e7445ab60da3685d6b5f, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
ShowDebugText: 0
|
||||||
|
ShowCameraFrustum: 1
|
||||||
|
IgnoreTimeScale: 0
|
||||||
|
WorldUpOverride: {fileID: 0}
|
||||||
|
ChannelMask: -1
|
||||||
|
UpdateMethod: 2
|
||||||
|
BlendUpdateMethod: 1
|
||||||
|
LensModeOverride:
|
||||||
|
Enabled: 0
|
||||||
|
DefaultMode: 2
|
||||||
|
DefaultBlend:
|
||||||
|
Style: 1
|
||||||
|
Time: 2
|
||||||
|
CustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve: []
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
CustomBlends: {fileID: 0}
|
||||||
--- !u!1 &343153336
|
--- !u!1 &343153336
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -517,35 +550,16 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 438e8be3307824743b12d4e4f02825ea, type: 3}
|
m_Script: {fileID: 11500000, guid: 438e8be3307824743b12d4e4f02825ea, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
baseStats:
|
hoverHeight: 2.5
|
||||||
TopSpeed: 10
|
hoverForce: 100
|
||||||
Acceleration: 5
|
groundLayer:
|
||||||
ReverseSpeed: 5
|
|
||||||
ReverseAcceleration: 5
|
|
||||||
AccelerationCurve: 1
|
|
||||||
Braking: 10
|
|
||||||
CoastingDrag: 4
|
|
||||||
Grip: 0.95
|
|
||||||
floatHeight: 3
|
|
||||||
minimumFloatHeight: 0.5
|
|
||||||
Steer: 5
|
|
||||||
AddedGravity: 1
|
|
||||||
m_VisualWheels: []
|
|
||||||
CenterOfMass: {fileID: 439250409}
|
|
||||||
AirborneReorientationCoefficient: 3
|
|
||||||
DriftGrip: 0.4
|
|
||||||
DriftAdditionalSteer: 5
|
|
||||||
MinAngleToFinishDrift: 10
|
|
||||||
MinSpeedPercentToFinishDrift: 0.5
|
|
||||||
DriftControl: 10
|
|
||||||
DriftDampening: 10
|
|
||||||
SuspensionHeight: 0.2
|
|
||||||
SuspensionSpring: 20000
|
|
||||||
SuspensionDamp: 500
|
|
||||||
WheelsPositionVerticalOffset: 0
|
|
||||||
GroundLayers:
|
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_Bits: 51
|
m_Bits: 4294967295
|
||||||
|
hoverDampening: 5
|
||||||
|
forwardSpeed: 30
|
||||||
|
turnSpeed: 3
|
||||||
|
strafeSpeed: 15
|
||||||
|
drag: 0.5
|
||||||
--- !u!4 &439250409
|
--- !u!4 &439250409
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -572,7 +586,7 @@ Rigidbody:
|
|||||||
serializedVersion: 4
|
serializedVersion: 4
|
||||||
m_Mass: 1
|
m_Mass: 1
|
||||||
m_Drag: 0
|
m_Drag: 0
|
||||||
m_AngularDrag: 0.05
|
m_AngularDrag: 0.5
|
||||||
m_CenterOfMass: {x: 0, y: 0, z: 0}
|
m_CenterOfMass: {x: 0, y: 0, z: 0}
|
||||||
m_InertiaTensor: {x: 1, y: 1, z: 1}
|
m_InertiaTensor: {x: 1, y: 1, z: 1}
|
||||||
m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
@ -587,7 +601,7 @@ Rigidbody:
|
|||||||
m_UseGravity: 1
|
m_UseGravity: 1
|
||||||
m_IsKinematic: 0
|
m_IsKinematic: 0
|
||||||
m_Interpolate: 0
|
m_Interpolate: 0
|
||||||
m_Constraints: 0
|
m_Constraints: 80
|
||||||
m_CollisionDetection: 0
|
m_CollisionDetection: 0
|
||||||
--- !u!65 &439250411
|
--- !u!65 &439250411
|
||||||
BoxCollider:
|
BoxCollider:
|
||||||
@ -2208,6 +2222,131 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!1 &2109556991
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 2109556995}
|
||||||
|
- component: {fileID: 2109556994}
|
||||||
|
- component: {fileID: 2109556993}
|
||||||
|
- component: {fileID: 2109556992}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: CinemachineCamera
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!114 &2109556992
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2109556991}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: f38bda98361e1de48a4ca2bd86ea3c17, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
Composition:
|
||||||
|
ScreenPosition: {x: 0, y: 0}
|
||||||
|
DeadZone:
|
||||||
|
Enabled: 0
|
||||||
|
Size: {x: 0.2, y: 0.2}
|
||||||
|
HardLimits:
|
||||||
|
Enabled: 0
|
||||||
|
Size: {x: 0.8, y: 0.8}
|
||||||
|
Offset: {x: 0, y: 0}
|
||||||
|
CenterOnActivate: 1
|
||||||
|
TargetOffset: {x: 0, y: 0, z: 0}
|
||||||
|
Damping: {x: 0.5, y: 0.5}
|
||||||
|
Lookahead:
|
||||||
|
Enabled: 0
|
||||||
|
Time: 0
|
||||||
|
Smoothing: 0
|
||||||
|
IgnoreY: 0
|
||||||
|
--- !u!114 &2109556993
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2109556991}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: b617507da6d07e749b7efdb34e1173e1, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
TrackerSettings:
|
||||||
|
BindingMode: 3
|
||||||
|
PositionDamping: {x: 1, y: 1, z: 1}
|
||||||
|
AngularDampingMode: 0
|
||||||
|
RotationDamping: {x: 1, y: 1, z: 1}
|
||||||
|
QuaternionDamping: 1
|
||||||
|
FollowOffset: {x: 0, y: 2, z: -5}
|
||||||
|
--- !u!114 &2109556994
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2109556991}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: f9dfa5b682dcd46bda6128250e975f58, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
Priority:
|
||||||
|
Enabled: 0
|
||||||
|
m_Value: 0
|
||||||
|
OutputChannel: 1
|
||||||
|
StandbyUpdate: 2
|
||||||
|
m_StreamingVersion: 20241001
|
||||||
|
m_LegacyPriority: 0
|
||||||
|
Target:
|
||||||
|
TrackingTarget: {fileID: 439250409}
|
||||||
|
LookAtTarget: {fileID: 0}
|
||||||
|
CustomLookAtTarget: 0
|
||||||
|
Lens:
|
||||||
|
FieldOfView: 60.000004
|
||||||
|
OrthographicSize: 5
|
||||||
|
NearClipPlane: 0.3
|
||||||
|
FarClipPlane: 1000
|
||||||
|
Dutch: 0
|
||||||
|
ModeOverride: 0
|
||||||
|
PhysicalProperties:
|
||||||
|
GateFit: 2
|
||||||
|
SensorSize: {x: 21.946, y: 16.002}
|
||||||
|
LensShift: {x: 0, y: 0}
|
||||||
|
FocusDistance: 10
|
||||||
|
Iso: 200
|
||||||
|
ShutterSpeed: 0.005
|
||||||
|
Aperture: 16
|
||||||
|
BladeCount: 5
|
||||||
|
Curvature: {x: 2, y: 11}
|
||||||
|
BarrelClipping: 0.25
|
||||||
|
Anamorphism: 0
|
||||||
|
BlendHint: 0
|
||||||
|
--- !u!4 &2109556995
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2109556991}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0.18910754, y: -0.000000014030908, z: 0.000000002702106, w: 0.9819564}
|
||||||
|
m_LocalPosition: {x: 2.631, y: 3.709, z: -3.085}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1660057539 &9223372036854775807
|
--- !u!1660057539 &9223372036854775807
|
||||||
SceneRoots:
|
SceneRoots:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -2219,3 +2358,4 @@ SceneRoots:
|
|||||||
- {fileID: 1095225674}
|
- {fileID: 1095225674}
|
||||||
- {fileID: 439250409}
|
- {fileID: 439250409}
|
||||||
- {fileID: 1273423010}
|
- {fileID: 1273423010}
|
||||||
|
- {fileID: 2109556995}
|
||||||
|
@ -7,498 +7,80 @@ namespace SRL
|
|||||||
{
|
{
|
||||||
public class ArcadeKart : MonoBehaviour
|
public class ArcadeKart : MonoBehaviour
|
||||||
{
|
{
|
||||||
[System.Serializable]
|
|
||||||
public class StatPowerup
|
|
||||||
{
|
|
||||||
public ArcadeKart.Stats modifiers;
|
|
||||||
public string PowerUpID;
|
|
||||||
public float ElapsedTime;
|
|
||||||
public float MaxTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
[System.Serializable]
|
|
||||||
public struct Stats
|
|
||||||
{
|
|
||||||
[Header("Movement Settings")]
|
|
||||||
[Min(0.001f), Tooltip("Top speed attainable when moving forward.")]
|
|
||||||
public float TopSpeed;
|
|
||||||
|
|
||||||
[Tooltip("How quickly the kart reaches top speed.")]
|
|
||||||
public float Acceleration;
|
|
||||||
|
|
||||||
[Min(0.001f), Tooltip("Top speed attainable when moving backward.")]
|
|
||||||
public float ReverseSpeed;
|
|
||||||
|
|
||||||
[Tooltip("How quickly the kart reaches top speed, when moving backward.")]
|
|
||||||
public float ReverseAcceleration;
|
|
||||||
|
|
||||||
[Tooltip("How quickly the kart starts accelerating from 0. A higher number means it accelerates faster sooner.")]
|
|
||||||
[Range(0.2f, 1)]
|
|
||||||
public float AccelerationCurve;
|
|
||||||
|
|
||||||
[Tooltip("How quickly the kart slows down when the brake is applied.")]
|
|
||||||
public float Braking;
|
|
||||||
|
|
||||||
[Tooltip("How quickly the kart will reach a full stop when no inputs are made.")]
|
|
||||||
public float CoastingDrag;
|
|
||||||
|
|
||||||
[Range(0.0f, 1.0f)]
|
|
||||||
[Tooltip("The amount of side-to-side friction.")]
|
|
||||||
public float Grip;
|
|
||||||
[Tooltip("The target height to float above the ground.")]
|
|
||||||
public float floatHeight;
|
|
||||||
[Tooltip("The minimum height to float above the ground.")]
|
|
||||||
public float minimumFloatHeight;
|
|
||||||
|
|
||||||
[Tooltip("How tightly the kart can turn left or right.")]
|
|
||||||
public float Steer;
|
|
||||||
|
|
||||||
[Tooltip("Additional gravity for when the kart is in the air.")]
|
|
||||||
public float AddedGravity;
|
|
||||||
|
|
||||||
// allow for stat adding for powerups.
|
|
||||||
public static Stats operator +(Stats a, Stats b)
|
|
||||||
{
|
|
||||||
return new Stats
|
|
||||||
{
|
|
||||||
Acceleration = a.Acceleration + b.Acceleration,
|
|
||||||
AccelerationCurve = a.AccelerationCurve + b.AccelerationCurve,
|
|
||||||
Braking = a.Braking + b.Braking,
|
|
||||||
CoastingDrag = a.CoastingDrag + b.CoastingDrag,
|
|
||||||
AddedGravity = a.AddedGravity + b.AddedGravity,
|
|
||||||
Grip = a.Grip + b.Grip,
|
|
||||||
floatHeight = a.floatHeight + b.floatHeight,
|
|
||||||
minimumFloatHeight = a.minimumFloatHeight + b.minimumFloatHeight,
|
|
||||||
ReverseAcceleration = a.ReverseAcceleration + b.ReverseAcceleration,
|
|
||||||
ReverseSpeed = a.ReverseSpeed + b.ReverseSpeed,
|
|
||||||
TopSpeed = a.TopSpeed + b.TopSpeed,
|
|
||||||
Steer = a.Steer + b.Steer,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Rigidbody Rigidbody { get; private set; }
|
|
||||||
public InputData Input { get; private set; }
|
public InputData Input { get; private set; }
|
||||||
public float AirPercent { get; private set; }
|
|
||||||
public float GroundPercent { get; private set; }
|
|
||||||
|
|
||||||
public ArcadeKart.Stats baseStats = new ArcadeKart.Stats
|
|
||||||
{
|
|
||||||
TopSpeed = 10f,
|
|
||||||
Acceleration = 5f,
|
|
||||||
AccelerationCurve = 4f,
|
|
||||||
Braking = 10f,
|
|
||||||
ReverseAcceleration = 5f,
|
|
||||||
ReverseSpeed = 5f,
|
|
||||||
Steer = 5f,
|
|
||||||
CoastingDrag = 4f,
|
|
||||||
Grip = .95f,
|
|
||||||
floatHeight = 1f,
|
|
||||||
minimumFloatHeight = .5f,
|
|
||||||
AddedGravity = 1f,
|
|
||||||
};
|
|
||||||
|
|
||||||
[Header("Vehicle Visual")]
|
|
||||||
public List<GameObject> m_VisualWheels;
|
|
||||||
|
|
||||||
[Header("Vehicle Physics")]
|
|
||||||
[Tooltip("The transform that determines the position of the kart's mass.")]
|
|
||||||
public Transform CenterOfMass;
|
|
||||||
|
|
||||||
[Range(0.0f, 20.0f), Tooltip("Coefficient used to reorient the kart in the air. The higher the number, the faster the kart will readjust itself along the horizontal plane.")]
|
|
||||||
public float AirborneReorientationCoefficient = 3.0f;
|
|
||||||
|
|
||||||
[Header("Drifting")]
|
|
||||||
[Range(0.01f, 1.0f), Tooltip("The grip value when drifting.")]
|
|
||||||
public float DriftGrip = 0.4f;
|
|
||||||
[Range(0.0f, 10.0f), Tooltip("Additional steer when the kart is drifting.")]
|
|
||||||
public float DriftAdditionalSteer = 5.0f;
|
|
||||||
[Range(1.0f, 30.0f), Tooltip("The higher the angle, the easier it is to regain full grip.")]
|
|
||||||
public float MinAngleToFinishDrift = 10.0f;
|
|
||||||
[Range(0.01f, 0.99f), Tooltip("Mininum speed percentage to switch back to full grip.")]
|
|
||||||
public float MinSpeedPercentToFinishDrift = 0.5f;
|
|
||||||
[Range(1.0f, 20.0f), Tooltip("The higher the value, the easier it is to control the drift steering.")]
|
|
||||||
public float DriftControl = 10.0f;
|
|
||||||
[Range(0.0f, 20.0f), Tooltip("The lower the value, the longer the drift will last without trying to control it by steering.")]
|
|
||||||
public float DriftDampening = 10.0f;
|
|
||||||
|
|
||||||
[Header("Suspensions")]
|
|
||||||
[Tooltip("The maximum extension possible between the kart's body and the wheels.")]
|
|
||||||
[Range(0.0f, 1.0f)]
|
|
||||||
public float SuspensionHeight = 0.2f;
|
|
||||||
[Range(10.0f, 100000.0f), Tooltip("The higher the value, the stiffer the suspension will be.")]
|
|
||||||
public float SuspensionSpring = 20000.0f;
|
|
||||||
[Range(0.0f, 5000.0f), Tooltip("The higher the value, the faster the kart will stabilize itself.")]
|
|
||||||
public float SuspensionDamp = 500.0f;
|
|
||||||
[Tooltip("Vertical offset to adjust the position of the wheels relative to the kart's body.")]
|
|
||||||
[Range(-1.0f, 1.0f)]
|
|
||||||
public float WheelsPositionVerticalOffset = 0.0f;
|
|
||||||
|
|
||||||
[Tooltip("Which layers the wheels will detect.")]
|
|
||||||
public LayerMask GroundLayers = Physics.DefaultRaycastLayers;
|
|
||||||
|
|
||||||
// the input sources that can control the kart
|
// the input sources that can control the kart
|
||||||
IInput[] m_Inputs;
|
IInput[] m_Inputs;
|
||||||
|
|
||||||
const float k_NullInput = 0.01f;
|
|
||||||
const float k_NullSpeed = 0.01f;
|
|
||||||
Vector3 m_VerticalReference = Vector3.up;
|
|
||||||
|
|
||||||
// Drift params
|
|
||||||
public bool WantsToDrift { get; private set; } = false;
|
|
||||||
public bool IsDrifting { get; private set; } = false;
|
|
||||||
float m_CurrentGrip = 1.0f;
|
|
||||||
float m_DriftTurningPower = 0.0f;
|
|
||||||
float m_PreviousGroundPercent = 1.0f;
|
|
||||||
readonly List<(GameObject trailRoot, WheelCollider wheel, TrailRenderer trail)> m_DriftTrailInstances = new List<(GameObject, WheelCollider, TrailRenderer)>();
|
|
||||||
readonly List<(WheelCollider wheel, float horizontalOffset, float rotation, ParticleSystem sparks)> m_DriftSparkInstances = new List<(WheelCollider, float, float, ParticleSystem)>();
|
|
||||||
|
|
||||||
// can the kart move?
|
|
||||||
bool m_CanMove = true;
|
|
||||||
List<StatPowerup> m_ActivePowerupList = new List<StatPowerup>();
|
|
||||||
ArcadeKart.Stats m_FinalStats;
|
|
||||||
|
|
||||||
Quaternion m_LastValidRotation;
|
|
||||||
Vector3 m_LastValidPosition;
|
|
||||||
Vector3 m_LastCollisionNormal;
|
|
||||||
bool m_HasCollision;
|
|
||||||
bool m_InAir = false;
|
|
||||||
|
|
||||||
public void AddPowerup(StatPowerup statPowerup) => m_ActivePowerupList.Add(statPowerup);
|
|
||||||
public void SetCanMove(bool move) => m_CanMove = move;
|
|
||||||
public float GetMaxSpeed() => Mathf.Max(m_FinalStats.TopSpeed, m_FinalStats.ReverseSpeed);
|
|
||||||
|
|
||||||
void UpdateSuspensionParams(WheelCollider wheel)
|
|
||||||
{
|
|
||||||
wheel.suspensionDistance = SuspensionHeight;
|
|
||||||
wheel.center = new Vector3(0.0f, WheelsPositionVerticalOffset, 0.0f);
|
|
||||||
JointSpring spring = wheel.suspensionSpring;
|
|
||||||
spring.spring = SuspensionSpring;
|
|
||||||
spring.damper = SuspensionDamp;
|
|
||||||
wheel.suspensionSpring = spring;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Awake()
|
|
||||||
{
|
|
||||||
Rigidbody = GetComponent<Rigidbody>();
|
|
||||||
m_Inputs = GetComponents<IInput>();
|
|
||||||
|
|
||||||
m_CurrentGrip = baseStats.Grip;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FixedUpdate()
|
|
||||||
{
|
|
||||||
|
|
||||||
GatherInputs();
|
|
||||||
// apply our powerups to create our finalStats
|
|
||||||
TickPowerups();
|
|
||||||
|
|
||||||
// apply our physics properties
|
|
||||||
Rigidbody.centerOfMass = transform.InverseTransformPoint(CenterOfMass.position);
|
|
||||||
|
|
||||||
int groundedCount = 4;
|
|
||||||
// if (FrontLeftWheel.isGrounded && FrontLeftWheel.GetGroundHit(out WheelHit hit))
|
|
||||||
// groundedCount++;
|
|
||||||
// if (FrontRightWheel.isGrounded && FrontRightWheel.GetGroundHit(out hit))
|
|
||||||
// groundedCount++;
|
|
||||||
// if (RearLeftWheel.isGrounded && RearLeftWheel.GetGroundHit(out hit))
|
|
||||||
// groundedCount++;
|
|
||||||
// if (RearRightWheel.isGrounded && RearRightWheel.GetGroundHit(out hit))
|
|
||||||
// groundedCount++;
|
|
||||||
|
|
||||||
// calculate how grounded and airborne we are
|
|
||||||
GroundPercent = (float) groundedCount / 4.0f;
|
|
||||||
AirPercent = 1 - GroundPercent;
|
|
||||||
|
|
||||||
// apply vehicle physics
|
|
||||||
if (m_CanMove)
|
|
||||||
{
|
|
||||||
MoveVehicle(Input.Accelerate, Input.Brake, Input.TurnInput);
|
|
||||||
}
|
|
||||||
GroundAirbourne();
|
|
||||||
|
|
||||||
m_PreviousGroundPercent = GroundPercent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GatherInputs()
|
void GatherInputs()
|
||||||
{
|
{
|
||||||
// reset input
|
// reset input
|
||||||
Input = new InputData();
|
Input = new InputData();
|
||||||
WantsToDrift = false;
|
|
||||||
|
|
||||||
// gather nonzero input from our sources
|
// gather nonzero input from our sources
|
||||||
for (int i = 0; i < m_Inputs.Length; i++)
|
for (int i = 0; i < m_Inputs.Length; i++)
|
||||||
{
|
{
|
||||||
Input = m_Inputs[i].GenerateInput();
|
Input = m_Inputs[i].GenerateInput();
|
||||||
WantsToDrift = Input.Brake && Vector3.Dot(Rigidbody.linearVelocity, transform.forward) > 0.0f;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TickPowerups()
|
|
||||||
|
|
||||||
|
[Header("Hover Settings")]
|
||||||
|
public float hoverHeight = 2.0f;
|
||||||
|
public float hoverForce = 100f;
|
||||||
|
public LayerMask groundLayer;
|
||||||
|
public float hoverDampening = 5f;
|
||||||
|
|
||||||
|
[Header("Movement Settings")]
|
||||||
|
public float forwardSpeed = 50f;
|
||||||
|
public float turnSpeed = 20f;
|
||||||
|
public float strafeSpeed = 15f;
|
||||||
|
public float drag = 2f;
|
||||||
|
|
||||||
|
|
||||||
|
private Rigidbody rb;
|
||||||
|
|
||||||
|
void Awake()
|
||||||
{
|
{
|
||||||
// remove all elapsed powerups
|
rb = GetComponent<Rigidbody>();
|
||||||
m_ActivePowerupList.RemoveAll((p) => { return p.ElapsedTime > p.MaxTime; });
|
m_Inputs = GetComponents<IInput>();
|
||||||
|
|
||||||
// zero out powerups before we add them all up
|
|
||||||
var powerups = new Stats();
|
|
||||||
|
|
||||||
// add up all our powerups
|
|
||||||
for (int i = 0; i < m_ActivePowerupList.Count; i++)
|
|
||||||
{
|
|
||||||
var p = m_ActivePowerupList[i];
|
|
||||||
|
|
||||||
// add elapsed time
|
|
||||||
p.ElapsedTime += Time.fixedDeltaTime;
|
|
||||||
|
|
||||||
// add up the powerups
|
|
||||||
powerups += p.modifiers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add powerups to our final stats
|
void FixedUpdate()
|
||||||
m_FinalStats = baseStats + powerups;
|
{
|
||||||
|
GatherInputs();
|
||||||
// clamp values in finalstats
|
Hover();
|
||||||
m_FinalStats.Grip = Mathf.Clamp(m_FinalStats.Grip, 0, 1);
|
Move();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroundAirbourne()
|
void Hover()
|
||||||
{
|
{
|
||||||
RaycastHit hit;
|
// Raycast to ground to simulate hover
|
||||||
|
Ray ray = new Ray(transform.position, -transform.up);
|
||||||
// Check if the object is hitting the ground using a raycast
|
if (Physics.Raycast(ray, out RaycastHit hit, hoverHeight * 2, groundLayer))
|
||||||
|
|
||||||
if (Physics.Raycast(transform.position, Vector3.down, out hit, baseStats.floatHeight + 0.1f))
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
float hoverError = hoverHeight - hit.distance;
|
||||||
|
float upwardSpeed = rb.linearVelocity.y;
|
||||||
|
float appliedHoverForce = hoverError * hoverForce - upwardSpeed * hoverDampening;
|
||||||
|
|
||||||
// Calculate the upward force needed to maintain the desired height
|
rb.AddForce(Vector3.up * appliedHoverForce, ForceMode.Acceleration);
|
||||||
|
|
||||||
float upwardForce = (baseStats.floatHeight - (hit.distance - baseStats.minimumFloatHeight)) * 10f;
|
|
||||||
|
|
||||||
Rigidbody.AddForce(Vector3.up * upwardForce, ForceMode.Acceleration);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
void Move()
|
||||||
{
|
{
|
||||||
Vector3 euler = transform.rotation.eulerAngles;
|
// Forward movement
|
||||||
euler.x = euler.z = 0f;
|
float forwardInput = Input.Accelerate ? 1f : 0f;
|
||||||
transform.rotation = Quaternion.Euler(euler);
|
Vector3 forwardForce = transform.forward * forwardInput * forwardSpeed;
|
||||||
}
|
rb.AddForce(forwardForce, ForceMode.Acceleration);
|
||||||
|
|
||||||
public float LocalSpeed()
|
// Turning (rotate around Y-axis)
|
||||||
{
|
float turnInput = Input.TurnInput;
|
||||||
if (m_CanMove)
|
rb.AddTorque(Vector3.up * turnInput * turnSpeed, ForceMode.Acceleration);
|
||||||
{
|
|
||||||
float dot = Vector3.Dot(transform.forward, Rigidbody.linearVelocity);
|
|
||||||
if (Mathf.Abs(dot) > 0.1f)
|
|
||||||
{
|
|
||||||
float speed = Rigidbody.linearVelocity.magnitude;
|
|
||||||
return dot < 0 ? -(speed / m_FinalStats.ReverseSpeed) : (speed / m_FinalStats.TopSpeed);
|
|
||||||
}
|
|
||||||
return 0f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// use this value to play kart sound when it is waiting the race start countdown.
|
|
||||||
return Input.Accelerate ? 1.0f : 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnCollisionEnter(Collision collision) => m_HasCollision = true;
|
// Apply drag to reduce endless acceleration
|
||||||
void OnCollisionExit(Collision collision) => m_HasCollision = false;
|
rb.linearVelocity = Vector3.Lerp(rb.linearVelocity, Vector3.zero, drag * Time.fixedDeltaTime);
|
||||||
|
|
||||||
void OnCollisionStay(Collision collision)
|
|
||||||
{
|
|
||||||
m_HasCollision = true;
|
|
||||||
m_LastCollisionNormal = Vector3.zero;
|
|
||||||
float dot = -1.0f;
|
|
||||||
|
|
||||||
foreach (var contact in collision.contacts)
|
|
||||||
{
|
|
||||||
if (Vector3.Dot(contact.normal, Vector3.up) > dot)
|
|
||||||
m_LastCollisionNormal = contact.normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveVehicle(bool accelerate, bool brake, float turnInput)
|
|
||||||
{
|
|
||||||
float accelInput = (accelerate ? 1.0f : 0.0f) - (brake ? 1.0f : 0.0f);
|
|
||||||
|
|
||||||
// manual acceleration curve coefficient scalar
|
|
||||||
float accelerationCurveCoeff = 5;
|
|
||||||
Vector3 localVel = transform.InverseTransformVector(Rigidbody.linearVelocity);
|
|
||||||
|
|
||||||
bool accelDirectionIsFwd = accelInput >= 0;
|
|
||||||
bool localVelDirectionIsFwd = localVel.z >= 0;
|
|
||||||
|
|
||||||
// use the max speed for the direction we are going--forward or reverse.
|
|
||||||
float maxSpeed = localVelDirectionIsFwd ? m_FinalStats.TopSpeed : m_FinalStats.ReverseSpeed;
|
|
||||||
float accelPower = accelDirectionIsFwd ? m_FinalStats.Acceleration : m_FinalStats.ReverseAcceleration;
|
|
||||||
|
|
||||||
float currentSpeed = Rigidbody.linearVelocity.magnitude;
|
|
||||||
float accelRampT = currentSpeed / maxSpeed;
|
|
||||||
float multipliedAccelerationCurve = m_FinalStats.AccelerationCurve * accelerationCurveCoeff;
|
|
||||||
float accelRamp = Mathf.Lerp(multipliedAccelerationCurve, 1, accelRampT * accelRampT);
|
|
||||||
|
|
||||||
bool isBraking = (localVelDirectionIsFwd && brake) || (!localVelDirectionIsFwd && accelerate);
|
|
||||||
|
|
||||||
// if we are braking (moving reverse to where we are going)
|
|
||||||
// use the braking accleration instead
|
|
||||||
float finalAccelPower = isBraking ? m_FinalStats.Braking : accelPower;
|
|
||||||
|
|
||||||
float finalAcceleration = finalAccelPower * accelRamp;
|
|
||||||
|
|
||||||
// apply inputs to forward/backward
|
|
||||||
float turningPower = IsDrifting ? m_DriftTurningPower : turnInput * m_FinalStats.Steer;
|
|
||||||
|
|
||||||
Quaternion turnAngle = Quaternion.AngleAxis(turningPower, transform.up);
|
|
||||||
Vector3 fwd = turnAngle * transform.forward;
|
|
||||||
Vector3 movement = fwd * accelInput * finalAcceleration * ((m_HasCollision || GroundPercent > 0.0f) ? 1.0f : 0.0f);
|
|
||||||
|
|
||||||
// forward movement
|
|
||||||
bool wasOverMaxSpeed = currentSpeed >= maxSpeed;
|
|
||||||
|
|
||||||
// if over max speed, cannot accelerate faster.
|
|
||||||
if (wasOverMaxSpeed && !isBraking)
|
|
||||||
movement *= 0.0f;
|
|
||||||
|
|
||||||
Vector3 newVelocity = Rigidbody.linearVelocity + movement * Time.fixedDeltaTime;
|
|
||||||
newVelocity.y = Rigidbody.linearVelocity.y;
|
|
||||||
|
|
||||||
// clamp max speed if we are on ground
|
|
||||||
if (GroundPercent > 0.0f && !wasOverMaxSpeed)
|
|
||||||
{
|
|
||||||
newVelocity = Vector3.ClampMagnitude(newVelocity, maxSpeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// coasting is when we aren't touching accelerate
|
|
||||||
if (Mathf.Abs(accelInput) < k_NullInput && GroundPercent > 0.0f)
|
|
||||||
{
|
|
||||||
newVelocity = Vector3.MoveTowards(newVelocity, new Vector3(0, Rigidbody.linearVelocity.y, 0), Time.fixedDeltaTime * m_FinalStats.CoastingDrag);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rigidbody.linearVelocity = newVelocity;
|
|
||||||
|
|
||||||
// Drift
|
|
||||||
if (GroundPercent > 0.0f)
|
|
||||||
{
|
|
||||||
if (m_InAir)
|
|
||||||
{
|
|
||||||
m_InAir = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// manual angular velocity coefficient
|
|
||||||
float angularVelocitySteering = 0.4f;
|
|
||||||
float angularVelocitySmoothSpeed = 20f;
|
|
||||||
|
|
||||||
// turning is reversed if we're going in reverse and pressing reverse
|
|
||||||
if (!localVelDirectionIsFwd && !accelDirectionIsFwd)
|
|
||||||
angularVelocitySteering *= -1.0f;
|
|
||||||
|
|
||||||
var angularVel = Rigidbody.angularVelocity;
|
|
||||||
|
|
||||||
// move the Y angular velocity towards our target
|
|
||||||
angularVel.y = Mathf.MoveTowards(angularVel.y, turningPower * angularVelocitySteering, Time.fixedDeltaTime * angularVelocitySmoothSpeed);
|
|
||||||
|
|
||||||
// apply the angular velocity
|
|
||||||
Rigidbody.angularVelocity = angularVel;
|
|
||||||
|
|
||||||
// rotate rigidbody's velocity as well to generate immediate velocity redirection
|
|
||||||
// manual velocity steering coefficient
|
|
||||||
float velocitySteering = 25f;
|
|
||||||
|
|
||||||
// If the karts lands with a forward not in the velocity direction, we start the drift
|
|
||||||
if (GroundPercent >= 0.0f && m_PreviousGroundPercent < 0.1f)
|
|
||||||
{
|
|
||||||
Vector3 flattenVelocity = Vector3.ProjectOnPlane(Rigidbody.linearVelocity, m_VerticalReference).normalized;
|
|
||||||
if (Vector3.Dot(flattenVelocity, transform.forward * Mathf.Sign(accelInput)) < Mathf.Cos(MinAngleToFinishDrift * Mathf.Deg2Rad))
|
|
||||||
{
|
|
||||||
IsDrifting = true;
|
|
||||||
m_CurrentGrip = DriftGrip;
|
|
||||||
m_DriftTurningPower = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drift Management
|
|
||||||
if (!IsDrifting)
|
|
||||||
{
|
|
||||||
if ((WantsToDrift || isBraking) && currentSpeed > maxSpeed * MinSpeedPercentToFinishDrift)
|
|
||||||
{
|
|
||||||
IsDrifting = true;
|
|
||||||
m_DriftTurningPower = turningPower + (Mathf.Sign(turningPower) * DriftAdditionalSteer);
|
|
||||||
m_CurrentGrip = DriftGrip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsDrifting)
|
|
||||||
{
|
|
||||||
float turnInputAbs = Mathf.Abs(turnInput);
|
|
||||||
if (turnInputAbs < k_NullInput)
|
|
||||||
m_DriftTurningPower = Mathf.MoveTowards(m_DriftTurningPower, 0.0f, Mathf.Clamp01(DriftDampening * Time.fixedDeltaTime));
|
|
||||||
|
|
||||||
// Update the turning power based on input
|
|
||||||
float driftMaxSteerValue = m_FinalStats.Steer + DriftAdditionalSteer;
|
|
||||||
m_DriftTurningPower = Mathf.Clamp(m_DriftTurningPower + (turnInput * Mathf.Clamp01(DriftControl * Time.fixedDeltaTime)), -driftMaxSteerValue, driftMaxSteerValue);
|
|
||||||
|
|
||||||
bool facingVelocity = Vector3.Dot(Rigidbody.linearVelocity.normalized, transform.forward * Mathf.Sign(accelInput)) > Mathf.Cos(MinAngleToFinishDrift * Mathf.Deg2Rad);
|
|
||||||
|
|
||||||
bool canEndDrift = true;
|
|
||||||
if (isBraking)
|
|
||||||
canEndDrift = false;
|
|
||||||
else if (!facingVelocity)
|
|
||||||
canEndDrift = false;
|
|
||||||
else if (turnInputAbs >= k_NullInput && currentSpeed > maxSpeed * MinSpeedPercentToFinishDrift)
|
|
||||||
canEndDrift = false;
|
|
||||||
|
|
||||||
if (canEndDrift || currentSpeed < k_NullSpeed)
|
|
||||||
{
|
|
||||||
// No Input, and car aligned with speed direction => Stop the drift
|
|
||||||
IsDrifting = false;
|
|
||||||
m_CurrentGrip = m_FinalStats.Grip;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// rotate our velocity based on current steer value
|
|
||||||
Rigidbody.linearVelocity = Quaternion.AngleAxis(turningPower * Mathf.Sign(localVel.z) * velocitySteering * m_CurrentGrip * Time.fixedDeltaTime, transform.up) * Rigidbody.linearVelocity;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_InAir = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool validPosition = false;
|
|
||||||
if (Physics.Raycast(transform.position + (transform.up * 0.1f), -transform.up, out RaycastHit hit, 3.0f, 1 << 9 | 1 << 10 | 1 << 11)) // Layer: ground (9) / Environment(10) / Track (11)
|
|
||||||
{
|
|
||||||
Vector3 lerpVector = (m_HasCollision && m_LastCollisionNormal.y > hit.normal.y) ? m_LastCollisionNormal : hit.normal;
|
|
||||||
m_VerticalReference = Vector3.Slerp(m_VerticalReference, lerpVector, Mathf.Clamp01(AirborneReorientationCoefficient * Time.fixedDeltaTime * (GroundPercent > 0.0f ? 10.0f : 1.0f))); // Blend faster if on ground
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Vector3 lerpVector = (m_HasCollision && m_LastCollisionNormal.y > 0.0f) ? m_LastCollisionNormal : Vector3.up;
|
|
||||||
m_VerticalReference = Vector3.Slerp(m_VerticalReference, lerpVector, Mathf.Clamp01(AirborneReorientationCoefficient * Time.fixedDeltaTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
validPosition = GroundPercent > 0.7f && !m_HasCollision && Vector3.Dot(m_VerticalReference, Vector3.up) > 0.9f;
|
|
||||||
|
|
||||||
// Airborne / Half on ground management
|
|
||||||
if (GroundPercent < 0.7f)
|
|
||||||
{
|
|
||||||
Rigidbody.angularVelocity = new Vector3(0.0f, Rigidbody.angularVelocity.y * 0.98f, 0.0f);
|
|
||||||
Vector3 finalOrientationDirection = Vector3.ProjectOnPlane(transform.forward, m_VerticalReference);
|
|
||||||
finalOrientationDirection.Normalize();
|
|
||||||
if (finalOrientationDirection.sqrMagnitude > 0.0f)
|
|
||||||
{
|
|
||||||
Rigidbody.MoveRotation(Quaternion.Lerp(Rigidbody.rotation, Quaternion.LookRotation(finalOrientationDirection, m_VerticalReference), Mathf.Clamp01(AirborneReorientationCoefficient * Time.fixedDeltaTime)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (validPosition)
|
|
||||||
{
|
|
||||||
m_LastValidPosition = transform.position;
|
|
||||||
m_LastValidRotation.eulerAngles = new Vector3(0.0f, transform.rotation.y, 0.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user