From 429fcf0b6e4d8d66892c1985f4d7c92e5e5933d9 Mon Sep 17 00:00:00 2001
From: John Wigner <johnswigner@gmail.com>
Date: Fri, 31 Jan 2025 09:18:52 -0500
Subject: [PATCH] add speedometer, banking and smoothing on kart

---
 Assets/Art/Sprites/UI.meta                    |   8 +
 .../Buttons => UI}/EmptySpedometer.aseprite   | Bin
 .../EmptySpedometer.aseprite.meta             |   0
 Assets/Art/Sprites/UI/EmptySpedometer.png     |   3 +
 .../Art/Sprites/UI/EmptySpedometer.png.meta   | 143 +++++
 .../Buttons => UI}/FullSpedometer.aseprite    | Bin
 .../FullSpedometer.aseprite.meta              |   0
 Assets/Art/Sprites/UI/FullSpedometer.png      |   3 +
 Assets/Art/Sprites/UI/FullSpedometer.png.meta | 143 +++++
 Assets/Scenes/TestTrack.unity                 | 497 +++++++++++++++++-
 Assets/Scripts/Kart/BankingObject.cs          |  29 +
 Assets/Scripts/Kart/BankingObject.cs.meta     |   2 +
 Assets/Scripts/Kart/HovercarController.cs     |  69 ++-
 Assets/Scripts/Kart/SpeedometerController.cs  |  45 ++
 .../Kart/SpeedometerController.cs.meta        |   2 +
 15 files changed, 910 insertions(+), 34 deletions(-)
 create mode 100644 Assets/Art/Sprites/UI.meta
 rename Assets/Art/Sprites/{Menu/Buttons => UI}/EmptySpedometer.aseprite (100%)
 rename Assets/Art/Sprites/{Menu/Buttons => UI}/EmptySpedometer.aseprite.meta (100%)
 create mode 100644 Assets/Art/Sprites/UI/EmptySpedometer.png
 create mode 100644 Assets/Art/Sprites/UI/EmptySpedometer.png.meta
 rename Assets/Art/Sprites/{Menu/Buttons => UI}/FullSpedometer.aseprite (100%)
 rename Assets/Art/Sprites/{Menu/Buttons => UI}/FullSpedometer.aseprite.meta (100%)
 create mode 100644 Assets/Art/Sprites/UI/FullSpedometer.png
 create mode 100644 Assets/Art/Sprites/UI/FullSpedometer.png.meta
 create mode 100644 Assets/Scripts/Kart/BankingObject.cs
 create mode 100644 Assets/Scripts/Kart/BankingObject.cs.meta
 create mode 100644 Assets/Scripts/Kart/SpeedometerController.cs
 create mode 100644 Assets/Scripts/Kart/SpeedometerController.cs.meta

diff --git a/Assets/Art/Sprites/UI.meta b/Assets/Art/Sprites/UI.meta
new file mode 100644
index 0000000..c9fff56
--- /dev/null
+++ b/Assets/Art/Sprites/UI.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 32d6c93d1c666b245aa7c72ddcc63416
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Art/Sprites/Menu/Buttons/EmptySpedometer.aseprite b/Assets/Art/Sprites/UI/EmptySpedometer.aseprite
similarity index 100%
rename from Assets/Art/Sprites/Menu/Buttons/EmptySpedometer.aseprite
rename to Assets/Art/Sprites/UI/EmptySpedometer.aseprite
diff --git a/Assets/Art/Sprites/Menu/Buttons/EmptySpedometer.aseprite.meta b/Assets/Art/Sprites/UI/EmptySpedometer.aseprite.meta
similarity index 100%
rename from Assets/Art/Sprites/Menu/Buttons/EmptySpedometer.aseprite.meta
rename to Assets/Art/Sprites/UI/EmptySpedometer.aseprite.meta
diff --git a/Assets/Art/Sprites/UI/EmptySpedometer.png b/Assets/Art/Sprites/UI/EmptySpedometer.png
new file mode 100644
index 0000000..e24a74f
--- /dev/null
+++ b/Assets/Art/Sprites/UI/EmptySpedometer.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2913ed4ea9980da6d4ec4919879c9468604a191dc3d721cda8c362b2e90977cd
+size 50297
diff --git a/Assets/Art/Sprites/UI/EmptySpedometer.png.meta b/Assets/Art/Sprites/UI/EmptySpedometer.png.meta
new file mode 100644
index 0000000..fc4a394
--- /dev/null
+++ b/Assets/Art/Sprites/UI/EmptySpedometer.png.meta
@@ -0,0 +1,143 @@
+fileFormatVersion: 2
+guid: fd17be6cd9f6a3e44840be970946f208
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 13
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+    flipGreenChannel: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  ignoreMipmapLimit: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 1
+    wrapV: 1
+    wrapW: 0
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  swizzle: 50462976
+  cookieLightType: 0
+  platformSettings:
+  - serializedVersion: 4
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    ignorePlatformSupport: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 4
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    ignorePlatformSupport: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 4
+    buildTarget: WebGL
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    ignorePlatformSupport: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 4
+    buildTarget: WindowsStoreApps
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    ignorePlatformSupport: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    customData: 
+    physicsShape: []
+    bones: []
+    spriteID: 5e97eb03825dee720800000000000000
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+    spriteCustomMetadata:
+      entries: []
+    nameFileIdTable: {}
+  mipmapLimitGroupName: 
+  pSDRemoveMatte: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Art/Sprites/Menu/Buttons/FullSpedometer.aseprite b/Assets/Art/Sprites/UI/FullSpedometer.aseprite
similarity index 100%
rename from Assets/Art/Sprites/Menu/Buttons/FullSpedometer.aseprite
rename to Assets/Art/Sprites/UI/FullSpedometer.aseprite
diff --git a/Assets/Art/Sprites/Menu/Buttons/FullSpedometer.aseprite.meta b/Assets/Art/Sprites/UI/FullSpedometer.aseprite.meta
similarity index 100%
rename from Assets/Art/Sprites/Menu/Buttons/FullSpedometer.aseprite.meta
rename to Assets/Art/Sprites/UI/FullSpedometer.aseprite.meta
diff --git a/Assets/Art/Sprites/UI/FullSpedometer.png b/Assets/Art/Sprites/UI/FullSpedometer.png
new file mode 100644
index 0000000..2d1fbef
--- /dev/null
+++ b/Assets/Art/Sprites/UI/FullSpedometer.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:813c51f71617bdd158ab2c4edd314361cfbdef55ec240a8327ad2e08e3851d4b
+size 54256
diff --git a/Assets/Art/Sprites/UI/FullSpedometer.png.meta b/Assets/Art/Sprites/UI/FullSpedometer.png.meta
new file mode 100644
index 0000000..1986105
--- /dev/null
+++ b/Assets/Art/Sprites/UI/FullSpedometer.png.meta
@@ -0,0 +1,143 @@
+fileFormatVersion: 2
+guid: c518c8b8a7532054a8828a794a4ce385
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 13
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+    flipGreenChannel: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  ignoreMipmapLimit: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 1
+    wrapV: 1
+    wrapW: 0
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  swizzle: 50462976
+  cookieLightType: 0
+  platformSettings:
+  - serializedVersion: 4
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    ignorePlatformSupport: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 4
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    ignorePlatformSupport: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 4
+    buildTarget: WebGL
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    ignorePlatformSupport: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 4
+    buildTarget: WindowsStoreApps
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    ignorePlatformSupport: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    customData: 
+    physicsShape: []
+    bones: []
+    spriteID: 5e97eb03825dee720800000000000000
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+    spriteCustomMetadata:
+      entries: []
+    nameFileIdTable: {}
+  mipmapLimitGroupName: 
+  pSDRemoveMatte: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scenes/TestTrack.unity b/Assets/Scenes/TestTrack.unity
index 7f86e95..9649367 100644
--- a/Assets/Scenes/TestTrack.unity
+++ b/Assets/Scenes/TestTrack.unity
@@ -119,6 +119,292 @@ NavMeshSettings:
     debug:
       m_Flags: 0
   m_NavMeshData: {fileID: 0}
+--- !u!1 &39858505
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 39858506}
+  - component: {fileID: 39858508}
+  - component: {fileID: 39858507}
+  m_Layer: 5
+  m_Name: EmptySpeedometer
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &39858506
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 39858505}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 996843409}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 430, y: -150}
+  m_SizeDelta: {x: 200, y: 200}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &39858507
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 39858505}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 21300000, guid: fd17be6cd9f6a3e44840be970946f208, type: 3}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &39858508
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 39858505}
+  m_CullTransparentMesh: 1
+--- !u!1 &76618634
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 76618635}
+  - component: {fileID: 76618637}
+  - component: {fileID: 76618636}
+  m_Layer: 5
+  m_Name: Speed
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &76618635
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 76618634}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 996843409}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 421, y: -144.9}
+  m_SizeDelta: {x: 200, y: 50}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &76618636
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 76618634}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_text: 120V
+  m_isRightToLeft: 0
+  m_fontAsset: {fileID: 11400000, guid: dc36b3fdc14f47ebb36fd484a67e268a, type: 2}
+  m_sharedMaterial: {fileID: 2140032, guid: dc36b3fdc14f47ebb36fd484a67e268a, type: 2}
+  m_fontSharedMaterials: []
+  m_fontMaterial: {fileID: 0}
+  m_fontMaterials: []
+  m_fontColor32:
+    serializedVersion: 2
+    rgba: 4282449151
+  m_fontColor: {r: 1, g: 0.9882353, b: 0.2509804, a: 1}
+  m_enableVertexGradient: 0
+  m_colorMode: 3
+  m_fontColorGradient:
+    topLeft: {r: 1, g: 1, b: 1, a: 1}
+    topRight: {r: 1, g: 1, b: 1, a: 1}
+    bottomLeft: {r: 1, g: 1, b: 1, a: 1}
+    bottomRight: {r: 1, g: 1, b: 1, a: 1}
+  m_fontColorGradientPreset: {fileID: 0}
+  m_spriteAsset: {fileID: 0}
+  m_tintAllSprites: 0
+  m_StyleSheet: {fileID: 0}
+  m_TextStyleHashCode: -1183493901
+  m_overrideHtmlColors: 0
+  m_faceColor:
+    serializedVersion: 2
+    rgba: 4294967295
+  m_fontSize: 64
+  m_fontSizeBase: 64
+  m_fontWeight: 400
+  m_enableAutoSizing: 0
+  m_fontSizeMin: 18
+  m_fontSizeMax: 72
+  m_fontStyle: 0
+  m_HorizontalAlignment: 2
+  m_VerticalAlignment: 256
+  m_textAlignment: 65535
+  m_characterSpacing: 0
+  m_wordSpacing: 0
+  m_lineSpacing: 0
+  m_lineSpacingMax: 0
+  m_paragraphSpacing: 0
+  m_charWidthMaxAdj: 0
+  m_TextWrappingMode: 1
+  m_wordWrappingRatios: 0.4
+  m_overflowMode: 0
+  m_linkedTextComponent: {fileID: 0}
+  parentLinkedComponent: {fileID: 0}
+  m_enableKerning: 0
+  m_ActiveFontFeatures: 6e72656b
+  m_enableExtraPadding: 0
+  checkPaddingRequired: 0
+  m_isRichText: 1
+  m_EmojiFallbackSupport: 1
+  m_parseCtrlCharacters: 1
+  m_isOrthographic: 1
+  m_isCullingEnabled: 0
+  m_horizontalMapping: 0
+  m_verticalMapping: 0
+  m_uvLineOffset: 0
+  m_geometrySortingOrder: 0
+  m_IsTextObjectScaleStatic: 0
+  m_VertexBufferAutoSizeReduction: 0
+  m_useMaxVisibleDescender: 1
+  m_pageToDisplay: 1
+  m_margin: {x: 0, y: 0, z: 0, w: 0}
+  m_isUsingLegacyAnimationComponent: 0
+  m_isVolumetricText: 0
+  m_hasFontAssetChanged: 0
+  m_baseMaterial: {fileID: 0}
+  m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
+--- !u!222 &76618637
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 76618634}
+  m_CullTransparentMesh: 1
+--- !u!1 &477184587
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 477184590}
+  - component: {fileID: 477184589}
+  - component: {fileID: 477184588}
+  m_Layer: 5
+  m_Name: FullSpeedometer
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &477184588
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 477184587}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 21300000, guid: c518c8b8a7532054a8828a794a4ce385, type: 3}
+  m_Type: 3
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 0
+  m_FillClockwise: 0
+  m_FillOrigin: 3
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &477184589
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 477184587}
+  m_CullTransparentMesh: 1
+--- !u!224 &477184590
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 477184587}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 996843409}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 430, y: -150}
+  m_SizeDelta: {x: 200, y: 200}
+  m_Pivot: {x: 0.5, y: 0.5}
 --- !u!1 &575325051
 GameObject:
   m_ObjectHideFlags: 0
@@ -375,6 +661,127 @@ MeshRenderer:
   m_SortingLayer: 0
   m_SortingOrder: 0
   m_AdditionalVertexStreams: {fileID: 0}
+--- !u!1 &996843404
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 996843409}
+  - component: {fileID: 996843408}
+  - component: {fileID: 996843407}
+  - component: {fileID: 996843406}
+  - component: {fileID: 996843405}
+  m_Layer: 5
+  m_Name: PlayerUI
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &996843405
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 996843404}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 92f3d3903bb620a45936872ab28bb90f, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  fullSpeedometerImage: {fileID: 477184588}
+  speedText: {fileID: 76618636}
+  playerVehicle: {fileID: 1703462595}
+  maxSpeed: 120
+--- !u!114 &996843406
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 996843404}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_IgnoreReversedGraphics: 1
+  m_BlockingObjects: 0
+  m_BlockingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+--- !u!114 &996843407
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 996843404}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_UiScaleMode: 0
+  m_ReferencePixelsPerUnit: 100
+  m_ScaleFactor: 1
+  m_ReferenceResolution: {x: 800, y: 600}
+  m_ScreenMatchMode: 0
+  m_MatchWidthOrHeight: 0
+  m_PhysicalUnit: 3
+  m_FallbackScreenDPI: 96
+  m_DefaultSpriteDPI: 96
+  m_DynamicPixelsPerUnit: 1
+  m_PresetInfoIsWorld: 0
+--- !u!223 &996843408
+Canvas:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 996843404}
+  m_Enabled: 1
+  serializedVersion: 3
+  m_RenderMode: 0
+  m_Camera: {fileID: 0}
+  m_PlaneDistance: 100
+  m_PixelPerfect: 0
+  m_ReceivesEvents: 1
+  m_OverrideSorting: 0
+  m_OverridePixelPerfect: 0
+  m_SortingBucketNormalizedSize: 0
+  m_VertexColorAlwaysGammaSpace: 0
+  m_AdditionalShaderChannelsFlag: 25
+  m_UpdateRectTransformForStandalone: 0
+  m_SortingLayerID: 0
+  m_SortingOrder: 0
+  m_TargetDisplay: 0
+--- !u!224 &996843409
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 996843404}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 0, y: 0, z: 0}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 477184590}
+  - {fileID: 39858506}
+  - {fileID: 76618635}
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 0, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0, y: 0}
 --- !u!1 &1703462595
 GameObject:
   m_ObjectHideFlags: 0
@@ -487,16 +894,15 @@ MonoBehaviour:
   m_Name: 
   m_EditorClassIdentifier: 
   hoverHeight: 3
-  positionAdjustmentSpeed: 10
+  positionAdjustmentSpeed: 5
   raycastDistance: 10
   terrainLayer:
     serializedVersion: 2
     m_Bits: 4294967295
-  movementSpeed: 150
+  movementSpeed: 120
+  acceleration: 3
+  deceleration: 2
   rotationSpeed: 35
-  leanLimit: 10
-  leanTime: 100
-  playerModel: {fileID: 0}
 --- !u!1 &1746292606
 GameObject:
   m_ObjectHideFlags: 0
@@ -743,6 +1149,85 @@ MonoBehaviour:
   m_LightCookieSize: {x: 1, y: 1}
   m_LightCookieOffset: {x: 0, y: 0}
   m_SoftShadowQuality: 0
+--- !u!1 &2141142284
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2141142287}
+  - component: {fileID: 2141142286}
+  - component: {fileID: 2141142285}
+  m_Layer: 0
+  m_Name: EventSystem
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &2141142285
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2141142284}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_SendPointerHoverToParent: 1
+  m_MoveRepeatDelay: 0.5
+  m_MoveRepeatRate: 0.1
+  m_XRTrackingOrigin: {fileID: 0}
+  m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
+  m_DeselectOnBackgroundClick: 1
+  m_PointerBehavior: 0
+  m_CursorLockBehavior: 0
+  m_ScrollDeltaPerTick: 6
+--- !u!114 &2141142286
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2141142284}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_FirstSelected: {fileID: 0}
+  m_sendNavigationEvents: 1
+  m_DragThreshold: 10
+--- !u!4 &2141142287
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2141142284}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  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!1 &2141521686
 GameObject:
   m_ObjectHideFlags: 0
@@ -861,3 +1346,5 @@ SceneRoots:
   - {fileID: 1746292610}
   - {fileID: 1703462600}
   - {fileID: 575325056}
+  - {fileID: 996843409}
+  - {fileID: 2141142287}
diff --git a/Assets/Scripts/Kart/BankingObject.cs b/Assets/Scripts/Kart/BankingObject.cs
new file mode 100644
index 0000000..58a2abe
--- /dev/null
+++ b/Assets/Scripts/Kart/BankingObject.cs
@@ -0,0 +1,29 @@
+using UnityEngine;
+
+public class ObjectBanking : MonoBehaviour
+{
+    [Header("Banking Configuration")]
+    [Tooltip("The speed at which the object banks left or right.")]
+    public float bankingSpeed = 5f;
+
+    [Tooltip("The maximum angle the object can bank to either side.")]
+    public float maxBankingAngle = 30f;
+
+    // Internal variable to keep track of current bank angle
+    private float currentBankAngle = 0f;
+
+    void Update()
+    {
+        // Get input from Horizontal axis (e.g., keyboard or controller)
+        float horizontalInput = Input.GetAxis("Horizontal");
+
+        // Target angle is proportional to input and max banking angle
+        float targetBankAngle = horizontalInput * maxBankingAngle;
+
+        // Smoothly interpolate current angle towards the target
+        currentBankAngle = Mathf.Lerp(currentBankAngle, targetBankAngle, Time.deltaTime * bankingSpeed);
+
+        // Apply the rotation (banking along the Z-axis)
+        transform.localRotation = Quaternion.Euler(0f, 0f, -currentBankAngle);
+    }
+}
diff --git a/Assets/Scripts/Kart/BankingObject.cs.meta b/Assets/Scripts/Kart/BankingObject.cs.meta
new file mode 100644
index 0000000..21672ba
--- /dev/null
+++ b/Assets/Scripts/Kart/BankingObject.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 592688461ab994244b969670c11efe3f
\ No newline at end of file
diff --git a/Assets/Scripts/Kart/HovercarController.cs b/Assets/Scripts/Kart/HovercarController.cs
index e6745d0..156fa5f 100644
--- a/Assets/Scripts/Kart/HovercarController.cs
+++ b/Assets/Scripts/Kart/HovercarController.cs
@@ -2,18 +2,17 @@ using UnityEngine;
 
 public class StableHovercarController : MonoBehaviour
 {
-    public float hoverHeight = 3.0f;  // Fixed height above terrain
-    public float positionAdjustmentSpeed = 10.0f;  // How quickly the vehicle adjusts its position
-    public float raycastDistance = 10.0f;  // How far the raycast searches for terrain
+    public float hoverHeight = 3.0f;  
+    public float positionAdjustmentSpeed = 10.0f;  
+    public float raycastDistance = 10.0f;  
     public LayerMask terrainLayer;
-    public float movementSpeed = 10.0f;
+
+    public float movementSpeed = 10.0f;  // Max speed
+    public float acceleration = 5.0f;    // How quickly to accelerate
+    public float deceleration = 7.0f;    // How quickly to decelerate
     public float rotationSpeed = 100.0f;
 
-    public float leanLimit = 10.0f;
-    public float leanTime = 100.0f;
-
-    public GameObject playerModel = null;
-
+    private float currentSpeed = 0.0f;   // Speed that interpolates over time
     private Rigidbody rb;
 
     void Start()
@@ -23,6 +22,12 @@ public class StableHovercarController : MonoBehaviour
     }
 
     void FixedUpdate()
+    {
+        HandleHovering();
+        HandleMovement();
+    }
+
+    void HandleHovering()
     {
         RaycastHit hit;
         Vector3 rayOrigin = transform.position;
@@ -30,27 +35,20 @@ public class StableHovercarController : MonoBehaviour
         // Cast a ray downward to detect the terrain
         if (Physics.Raycast(rayOrigin, -transform.up, out hit, raycastDistance, terrainLayer))
         {
-            // Get the mesh and triangle vertices from the hit object
             Mesh mesh = hit.collider.GetComponent<MeshFilter>().mesh;
             int triangleIndex = hit.triangleIndex;
             int vertex1Index = mesh.triangles[triangleIndex * 3 + 0];
             int vertex2Index = mesh.triangles[triangleIndex * 3 + 1];
             int vertex3Index = mesh.triangles[triangleIndex * 3 + 2];
 
-            // Get the vertices of the triangle in world space
-            Vector3 localVertex1 = mesh.vertices[vertex1Index];
-            Vector3 localVertex2 = mesh.vertices[vertex2Index];
-            Vector3 localVertex3 = mesh.vertices[vertex3Index];
-            Vector3 worldVertex1 = hit.collider.transform.TransformPoint(localVertex1);
-            Vector3 worldVertex2 = hit.collider.transform.TransformPoint(localVertex2);
-            Vector3 worldVertex3 = hit.collider.transform.TransformPoint(localVertex3);
+            Vector3 worldVertex1 = hit.collider.transform.TransformPoint(mesh.vertices[vertex1Index]);
+            Vector3 worldVertex2 = hit.collider.transform.TransformPoint(mesh.vertices[vertex2Index]);
+            Vector3 worldVertex3 = hit.collider.transform.TransformPoint(mesh.vertices[vertex3Index]);
 
-            // Interpolate the exact hover point using barycentric coordinates
             Vector3 interpolatedPoint = worldVertex1 * hit.barycentricCoordinate.x +
                                         worldVertex2 * hit.barycentricCoordinate.y +
                                         worldVertex3 * hit.barycentricCoordinate.z;
 
-            // Interpolate the surface normal using barycentric coordinates
             Vector3 localNormal1 = mesh.normals[vertex1Index];
             Vector3 localNormal2 = mesh.normals[vertex2Index];
             Vector3 localNormal3 = mesh.normals[vertex3Index];
@@ -60,26 +58,39 @@ public class StableHovercarController : MonoBehaviour
             Vector3 interpolatedNormal = worldNormal1 * hit.barycentricCoordinate.x +
                                          worldNormal2 * hit.barycentricCoordinate.y +
                                          worldNormal3 * hit.barycentricCoordinate.z;
-            interpolatedNormal.Normalize();  // Ensure the normal is properly normalized
+            interpolatedNormal.Normalize();  
 
-            // Calculate the target hover position above the terrain
             Vector3 targetPosition = interpolatedPoint + interpolatedNormal * hoverHeight;
 
-            // Smoothly move the vehicle to the target hover position
             transform.position = Vector3.Lerp(transform.position, targetPosition, Time.fixedDeltaTime * positionAdjustmentSpeed);
 
-            // Align the vehicle's up direction with the interpolated surface normal
             Quaternion targetRotation = Quaternion.FromToRotation(transform.up, interpolatedNormal) * transform.rotation;
-
-            // Smoothly rotate the vehicle to align with the surface
             rb.rotation = Quaternion.Slerp(rb.rotation, targetRotation, Time.fixedDeltaTime * 5.0f);
         }
+    }
 
-        // Basic movement controls (WSAD / arrow keys)
-        float move = Input.GetAxis("Vertical") * movementSpeed;
+    void HandleMovement()
+    {
+        // Get player input
+        float input = Input.GetAxis("Vertical");
+
+        // Determine target speed based on input
+        float targetSpeed = input * movementSpeed;
+
+        if (input != 0)
+        {
+            // Smooth acceleration
+            currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, Time.fixedDeltaTime * acceleration);
+        }
+        else
+        {
+            // Smooth deceleration when no input is present
+            currentSpeed = Mathf.Lerp(currentSpeed, 0, Time.fixedDeltaTime * deceleration);
+        }
+
+        // Apply movement and rotation
+        rb.linearVelocity = transform.forward * currentSpeed;
         float turn = Input.GetAxis("Horizontal") * rotationSpeed;
-
-        rb.linearVelocity = transform.forward * move;
         rb.angularVelocity = transform.up * turn * Mathf.Deg2Rad;
     }
 }
diff --git a/Assets/Scripts/Kart/SpeedometerController.cs b/Assets/Scripts/Kart/SpeedometerController.cs
new file mode 100644
index 0000000..54a0956
--- /dev/null
+++ b/Assets/Scripts/Kart/SpeedometerController.cs
@@ -0,0 +1,45 @@
+using UnityEngine;
+using UnityEngine.UI;
+using TMPro;  // Import TextMeshPro namespace
+
+public class SpeedometerController : MonoBehaviour
+{
+    public Image fullSpeedometerImage;      // Reference to the full speedometer UI
+    public TextMeshProUGUI speedText;       // Reference to the speed display (TextMeshPro)
+    public GameObject playerVehicle;        // Reference to the player's vehicle
+
+    private Rigidbody vehicleRigidbody;     // Reference to the vehicle's Rigidbody
+    public float maxSpeed = 10f;          // Maximum speed (adjust as needed)
+
+    void Start()
+    {
+        // Get the Rigidbody from the assigned player GameObject
+        if (playerVehicle != null)
+        {
+            vehicleRigidbody = playerVehicle.GetComponent<Rigidbody>();
+            if (vehicleRigidbody == null)
+            {
+                Debug.LogError("No Rigidbody found on the player GameObject! Please make sure it has one.");
+            }
+        }
+        else
+        {
+            Debug.LogError("Player GameObject is not assigned in the Inspector!");
+        }
+    }
+
+    void Update()
+    {
+        // Get the vehicle's speed in units per second (you can customize if needed)
+        float speed = vehicleRigidbody.linearVelocity.magnitude;  // Convert to km/h if needed
+
+        // Clamp speed to maxSpeed
+        float clampedSpeed = Mathf.Clamp(speed, 0, maxSpeed);
+
+        // Update the fill amount (0 to 1)
+        fullSpeedometerImage.fillAmount = clampedSpeed / maxSpeed;
+
+        // Update the speed text (e.g., "0V" to "120V")
+        speedText.text = Mathf.RoundToInt(clampedSpeed) + "V";
+    }
+}
diff --git a/Assets/Scripts/Kart/SpeedometerController.cs.meta b/Assets/Scripts/Kart/SpeedometerController.cs.meta
new file mode 100644
index 0000000..48ae543
--- /dev/null
+++ b/Assets/Scripts/Kart/SpeedometerController.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 92f3d3903bb620a45936872ab28bb90f
\ No newline at end of file