Merge pull request #11 from JohnSWigner/ai_racer
add AI racer, race manager, checkpoint, finish line, respawn mechanis…
This commit is contained in:
commit
a7afd1792e
246
Assets/Prefabs/AIRacer.prefab
Normal file
246
Assets/Prefabs/AIRacer.prefab
Normal file
@ -0,0 +1,246 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &5373302305645060479
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 403226101183159382}
|
||||
- component: {fileID: 7605148307958671168}
|
||||
- component: {fileID: 7040049591731627265}
|
||||
m_Layer: 0
|
||||
m_Name: Racer
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &403226101183159382
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5373302305645060479}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071068}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -1.101}
|
||||
m_LocalScale: {x: 50, y: 50, z: 50}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 713388573115023667}
|
||||
m_LocalEulerAnglesHint: {x: -90, y: 90, z: -90}
|
||||
--- !u!23 &7605148307958671168
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5373302305645060479}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: a8c192d1f2299e9429da6a6bbe7015b8, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!33 &7040049591731627265
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5373302305645060479}
|
||||
m_Mesh: {fileID: -1971573099692935037, guid: 9b10eb187f9523b48b3484ebce59fa25, type: 3}
|
||||
--- !u!1 &6468720760632047264
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 713388573115023667}
|
||||
m_Layer: 0
|
||||
m_Name: BankingObject
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &713388573115023667
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6468720760632047264}
|
||||
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:
|
||||
- {fileID: 403226101183159382}
|
||||
m_Father: {fileID: 2739604471974086380}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &9007727309090789879
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2739604471974086380}
|
||||
- component: {fileID: 7162886650759621711}
|
||||
- component: {fileID: 6800183193855919764}
|
||||
- component: {fileID: 4631925233965777590}
|
||||
- component: {fileID: 8696968540172343143}
|
||||
m_Layer: 0
|
||||
m_Name: AIRacer
|
||||
m_TagString: Racer
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &2739604471974086380
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9007727309090789879}
|
||||
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:
|
||||
- {fileID: 713388573115023667}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!54 &7162886650759621711
|
||||
Rigidbody:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9007727309090789879}
|
||||
serializedVersion: 4
|
||||
m_Mass: 1
|
||||
m_Drag: 0
|
||||
m_AngularDrag: 0.5
|
||||
m_CenterOfMass: {x: 0, y: 0, z: 0}
|
||||
m_InertiaTensor: {x: 1, y: 1, z: 1}
|
||||
m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ImplicitCom: 1
|
||||
m_ImplicitTensor: 1
|
||||
m_UseGravity: 1
|
||||
m_IsKinematic: 0
|
||||
m_Interpolate: 0
|
||||
m_Constraints: 0
|
||||
m_CollisionDetection: 0
|
||||
--- !u!65 &6800183193855919764
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9007727309090789879}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 2, y: 0.75, z: 2.4}
|
||||
m_Center: {x: 0, y: -0.1, z: -0.9}
|
||||
--- !u!114 &4631925233965777590
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9007727309090789879}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c250747ddb036f14faf25789ceb28a34, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
hoverHeight: 3
|
||||
positionAdjustmentSpeed: 5
|
||||
raycastDistance: 10
|
||||
terrainLayer:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
movementSpeed: 50
|
||||
acceleration: 5
|
||||
deceleration: 7
|
||||
rotationSpeed: 100
|
||||
waypoints: []
|
||||
waypointThreshold: 5
|
||||
enableRubberBanding: 1
|
||||
rubberBandingCoefficient: 0.1
|
||||
maxSpeedMultiplier: 1.5
|
||||
minSpeedMultiplier: 0.8
|
||||
--- !u!114 &8696968540172343143
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9007727309090789879}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 80f1410edd2d20447b553914aa3c9c7f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
currentCheckpointIndex: 0
|
||||
lapCount: 0
|
7
Assets/Prefabs/AIRacer.prefab.meta
Normal file
7
Assets/Prefabs/AIRacer.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6651bdcbc08f8ed4384fe9587db0f16f
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -26,12 +26,12 @@ Transform:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5373302305645060479}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: -0.70710677, y: 0, z: 0, w: 0.70710677}
|
||||
m_LocalPosition: {x: -0, y: 0, z: -1.101}
|
||||
m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071068}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -1.101}
|
||||
m_LocalScale: {x: 50, y: 50, z: 50}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 2739604471974086380}
|
||||
m_Father: {fileID: 713388573115023667}
|
||||
m_LocalEulerAnglesHint: {x: -90, y: 90, z: -90}
|
||||
--- !u!23 &7605148307958671168
|
||||
MeshRenderer:
|
||||
@ -86,6 +86,53 @@ MeshFilter:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5373302305645060479}
|
||||
m_Mesh: {fileID: -1971573099692935037, guid: 9b10eb187f9523b48b3484ebce59fa25, type: 3}
|
||||
--- !u!1 &6468720760632047264
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 713388573115023667}
|
||||
- component: {fileID: 6552287091957501518}
|
||||
m_Layer: 0
|
||||
m_Name: BankingObject
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &713388573115023667
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6468720760632047264}
|
||||
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:
|
||||
- {fileID: 403226101183159382}
|
||||
m_Father: {fileID: 2739604471974086380}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &6552287091957501518
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6468720760632047264}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f060abec37829be48a8165282e7c3aeb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
bankingSpeed: 5
|
||||
maxBankingAngle: 30
|
||||
--- !u!1 &9007727309090789879
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -97,11 +144,11 @@ GameObject:
|
||||
- component: {fileID: 2739604471974086380}
|
||||
- component: {fileID: 7162886650759621711}
|
||||
- component: {fileID: 6800183193855919764}
|
||||
- component: {fileID: 2566772842932132389}
|
||||
- component: {fileID: 341120459158792421}
|
||||
- component: {fileID: 7105996084223619230}
|
||||
m_Layer: 0
|
||||
m_Name: Player
|
||||
m_TagString: Untagged
|
||||
m_TagString: Racer
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
@ -119,7 +166,7 @@ Transform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 403226101183159382}
|
||||
- {fileID: 713388573115023667}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!54 &7162886650759621711
|
||||
@ -170,21 +217,6 @@ BoxCollider:
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 2, y: 0.75, z: 2.4}
|
||||
m_Center: {x: 0, y: -0.1, z: -0.9}
|
||||
--- !u!114 &2566772842932132389
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9007727309090789879}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: de1851cd35e729f4aa33011a49cd59fb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
TurnInputName: Horizontal
|
||||
AccelerateButtonName: Accelerate
|
||||
BrakeButtonName: Brake
|
||||
--- !u!114 &341120459158792421
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -207,3 +239,17 @@ MonoBehaviour:
|
||||
acceleration: 3
|
||||
deceleration: 2
|
||||
rotationSpeed: 125
|
||||
--- !u!114 &7105996084223619230
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9007727309090789879}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 80f1410edd2d20447b553914aa3c9c7f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
currentCheckpointIndex: 0
|
||||
lapCount: 0
|
||||
|
8
Assets/Prefabs/RaceObjects.meta
Normal file
8
Assets/Prefabs/RaceObjects.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e2afd01cab1aec41b5867293731f0b8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
69
Assets/Prefabs/RaceObjects/Checkpoint.prefab
Normal file
69
Assets/Prefabs/RaceObjects/Checkpoint.prefab
Normal file
@ -0,0 +1,69 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &4611779275587207245
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 170758284542595608}
|
||||
- component: {fileID: 312733210285042010}
|
||||
- component: {fileID: 6172101860559313244}
|
||||
m_Layer: 0
|
||||
m_Name: Checkpoint
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &170758284542595608
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4611779275587207245}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -0.0013773441, y: -0.0979718, z: -0.8798604}
|
||||
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!65 &312733210285042010
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4611779275587207245}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 1
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 50, y: 40, z: 1}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &6172101860559313244
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4611779275587207245}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 7c3aaa50cd9e11d49801b7daff0a21bf, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
checkpointIndex: 0
|
7
Assets/Prefabs/RaceObjects/Checkpoint.prefab.meta
Normal file
7
Assets/Prefabs/RaceObjects/Checkpoint.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42174ef287c46c342845e8be9f640353
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
68
Assets/Prefabs/RaceObjects/Finish Line.prefab
Normal file
68
Assets/Prefabs/RaceObjects/Finish Line.prefab
Normal file
@ -0,0 +1,68 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &4611779275587207245
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 170758284542595608}
|
||||
- component: {fileID: 312733210285042010}
|
||||
- component: {fileID: 5198925182810260566}
|
||||
m_Layer: 0
|
||||
m_Name: Finish Line
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &170758284542595608
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4611779275587207245}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -0.0013773441, y: -0.0979718, z: -0.8798604}
|
||||
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!65 &312733210285042010
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4611779275587207245}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 1
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 50, y: 20, z: 1}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &5198925182810260566
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4611779275587207245}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9a4bc101ca357064ca138761e1319354, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
7
Assets/Prefabs/RaceObjects/Finish Line.prefab.meta
Normal file
7
Assets/Prefabs/RaceObjects/Finish Line.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b44d494d42ce6164dbaa9b9c298b9e1d
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
51
Assets/Prefabs/RaceObjects/RaceManager.prefab
Normal file
51
Assets/Prefabs/RaceObjects/RaceManager.prefab
Normal file
@ -0,0 +1,51 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &2884735936553393805
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6446736146779979254}
|
||||
- component: {fileID: 8956791611276861029}
|
||||
m_Layer: 0
|
||||
m_Name: RaceManager
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &6446736146779979254
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2884735936553393805}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -0.0013773441, y: -0.0979718, z: -0.8798604}
|
||||
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!114 &8956791611276861029
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2884735936553393805}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 18ac36268412d1946a31d8945cc6ac33, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
totalLaps: 3
|
||||
numberOfCheckpoints: 0
|
||||
finishLine: {fileID: 0}
|
||||
raceFinished: 0
|
||||
winnerName:
|
7
Assets/Prefabs/RaceObjects/RaceManager.prefab.meta
Normal file
7
Assets/Prefabs/RaceObjects/RaceManager.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d3c243c1b15b8d47b49111dee600ae6
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Resources.meta
Normal file
8
Assets/Resources.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2203474888d52347830cc8c8f51e421
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
6866
Assets/Scenes/AITrack.unity
Normal file
6866
Assets/Scenes/AITrack.unity
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/Scenes/AITrack.unity.meta
Normal file
7
Assets/Scenes/AITrack.unity.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79f34c11850512b418ac4060394f87ce
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1232,7 +1232,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 39e00ff0228389448a3e4fa61b925b10, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
scene_to_load: TestTrack
|
||||
scene_to_load: AITrack
|
||||
controlsPanel: {fileID: 1583355326}
|
||||
--- !u!1 &1397774624
|
||||
GameObject:
|
||||
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 933d22bf6aedba544849d3821a5d3a91
|
||||
guid: 856adccddca4ccf42ae7e35ef8ad938e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
322
Assets/Scripts/Kart/AIHovercarController.cs
Normal file
322
Assets/Scripts/Kart/AIHovercarController.cs
Normal file
@ -0,0 +1,322 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class AIHovercarController : MonoBehaviour
|
||||
{
|
||||
[Header("Hover Settings")]
|
||||
public float hoverHeight = 3.0f;
|
||||
public float positionAdjustmentSpeed = 10.0f;
|
||||
public float raycastDistance = 10.0f;
|
||||
public LayerMask terrainLayer;
|
||||
|
||||
[Header("Movement Settings")]
|
||||
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;
|
||||
|
||||
[Header("Checkpoint Navigation")]
|
||||
[Tooltip("Ordered list of checkpoints for the AI to follow.")]
|
||||
public Transform[] checkpoints;
|
||||
[Tooltip("Distance from a checkpoint at which the AI switches to the next one.")]
|
||||
public float checkpointThreshold = 5.0f;
|
||||
private int currentCheckpointIndex = 0;
|
||||
|
||||
[Header("Random Steering Settings")]
|
||||
[Tooltip("Probability per second that a random steering offset is applied (0 = never, 1 = every second on average).")]
|
||||
public float randomSteeringProbability = 0.2f;
|
||||
[Tooltip("Maximum random steering offset added (in normalized input units; e.g., 0.2 means up to ±20% extra steering).")]
|
||||
public float randomSteeringMaxOffset = 0.2f;
|
||||
|
||||
[Header("Slowdown Settings")]
|
||||
[Tooltip("Distance before a checkpoint at which the AI begins to slow down.")]
|
||||
public float slowdownDistance = 10f;
|
||||
[Tooltip("Strength of the slowdown (0 = no slowdown, 1 = full slowdown to minimum throttle at the checkpoint).")]
|
||||
public float slowdownStrength = 0.5f;
|
||||
|
||||
[Header("Reset Settings")]
|
||||
[Tooltip("Time (in seconds) without track contact before resetting the vehicle.")]
|
||||
public float timeBeforeReset = 3.0f;
|
||||
|
||||
[Header("Track Orientation Settings")]
|
||||
[Tooltip("Distance to search downward for track (used to align the vehicle’s bottom).")]
|
||||
public float trackRaycastDistance = 10.0f;
|
||||
[Tooltip("Tag used on the track geometry.")]
|
||||
public string trackTag = "Track";
|
||||
|
||||
[Header("Avoidance Settings")]
|
||||
[Tooltip("Radius within which the AI will try to avoid other racers.")]
|
||||
public float avoidanceRadius = 5.0f;
|
||||
[Tooltip("Strength of the steering adjustment to avoid collisions.")]
|
||||
public float avoidanceSteeringStrength = 0.5f;
|
||||
[Tooltip("Throttle multiplier applied when avoiding other racers (0 to 1, where lower means more slowdown).")]
|
||||
public float avoidanceSlowdownMultiplier = 0.5f;
|
||||
[Tooltip("Tag used to identify other racers for avoidance.")]
|
||||
public string racerTag = "Racer";
|
||||
|
||||
private float currentSpeed = 0.0f;
|
||||
private Rigidbody rb;
|
||||
|
||||
// Timer for lost ground/track contact
|
||||
private float noContactTimer = 0.0f;
|
||||
// Flag indicating if the hover raycast hit the terrain/track this physics frame
|
||||
private bool groundContact = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
rb = GetComponent<Rigidbody>();
|
||||
rb.useGravity = false;
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
HandleHovering();
|
||||
HandleMovement();
|
||||
|
||||
// If no ground/track contact is detected, count up the timer.
|
||||
if (!groundContact)
|
||||
{
|
||||
noContactTimer += Time.fixedDeltaTime;
|
||||
if (noContactTimer >= timeBeforeReset)
|
||||
{
|
||||
ResetToCheckpoint();
|
||||
noContactTimer = 0.0f; // Reset timer after repositioning.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the timer when ground/track contact is re-established.
|
||||
noContactTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hover logic: cast a ray downward, interpolate the hit point and normal on the terrain,
|
||||
/// and adjust the vehicle's position and rotation so it hovers along the track.
|
||||
/// Also sets the groundContact flag for reset timing.
|
||||
/// </summary>
|
||||
void HandleHovering()
|
||||
{
|
||||
RaycastHit hit;
|
||||
Vector3 rayOrigin = transform.position;
|
||||
|
||||
if (Physics.Raycast(rayOrigin, -transform.up, out hit, raycastDistance, terrainLayer))
|
||||
{
|
||||
groundContact = true;
|
||||
|
||||
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];
|
||||
|
||||
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]);
|
||||
|
||||
Vector3 interpolatedPoint = worldVertex1 * hit.barycentricCoordinate.x +
|
||||
worldVertex2 * hit.barycentricCoordinate.y +
|
||||
worldVertex3 * hit.barycentricCoordinate.z;
|
||||
|
||||
Vector3 localNormal1 = mesh.normals[vertex1Index];
|
||||
Vector3 localNormal2 = mesh.normals[vertex2Index];
|
||||
Vector3 localNormal3 = mesh.normals[vertex3Index];
|
||||
Vector3 worldNormal1 = hit.collider.transform.TransformDirection(localNormal1);
|
||||
Vector3 worldNormal2 = hit.collider.transform.TransformDirection(localNormal2);
|
||||
Vector3 worldNormal3 = hit.collider.transform.TransformDirection(localNormal3);
|
||||
Vector3 interpolatedNormal = worldNormal1 * hit.barycentricCoordinate.x +
|
||||
worldNormal2 * hit.barycentricCoordinate.y +
|
||||
worldNormal3 * hit.barycentricCoordinate.z;
|
||||
interpolatedNormal.Normalize();
|
||||
|
||||
Vector3 targetPosition = interpolatedPoint + interpolatedNormal * hoverHeight;
|
||||
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.fixedDeltaTime * positionAdjustmentSpeed);
|
||||
|
||||
Quaternion targetRotation = Quaternion.FromToRotation(transform.up, interpolatedNormal) * transform.rotation;
|
||||
rb.rotation = Quaternion.Slerp(rb.rotation, targetRotation, Time.fixedDeltaTime * 5.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
groundContact = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates input by computing throttle and steering based on the AI's orientation relative to the next checkpoint.
|
||||
/// New additions:
|
||||
/// - Random steering offset.
|
||||
/// - Throttle reduction when turning sharply and when approaching a checkpoint.
|
||||
/// - Avoidance: steer away from and slow down for nearby racers.
|
||||
/// </summary>
|
||||
void HandleMovement()
|
||||
{
|
||||
// Default simulated inputs.
|
||||
float verticalInput = 1f; // full throttle by default
|
||||
float horizontalInput = 0f;
|
||||
|
||||
if (checkpoints != null && checkpoints.Length > 0)
|
||||
{
|
||||
Transform targetCheckpoint = checkpoints[currentCheckpointIndex];
|
||||
Vector3 toCheckpoint = targetCheckpoint.position - transform.position;
|
||||
float distanceToCheckpoint = toCheckpoint.magnitude;
|
||||
Vector3 toCheckpointNormalized = toCheckpoint.normalized;
|
||||
|
||||
// If the target checkpoint is behind the vehicle, switch to the next one immediately.
|
||||
if (Vector3.Dot(transform.forward, toCheckpointNormalized) < 0)
|
||||
{
|
||||
currentCheckpointIndex = (currentCheckpointIndex + 1) % checkpoints.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute steering input based on the angle between the vehicle's forward and the direction to the checkpoint.
|
||||
Vector3 projectedForward = Vector3.ProjectOnPlane(transform.forward, transform.up).normalized;
|
||||
Vector3 projectedTarget = Vector3.ProjectOnPlane(toCheckpointNormalized, transform.up).normalized;
|
||||
float angle = Vector3.SignedAngle(projectedForward, projectedTarget, transform.up);
|
||||
horizontalInput = Mathf.Clamp(angle / 45f, -1f, 1f);
|
||||
|
||||
// Add a random steering offset occasionally.
|
||||
if (Random.value < randomSteeringProbability * Time.fixedDeltaTime)
|
||||
{
|
||||
float randomOffset = Random.Range(-randomSteeringMaxOffset, randomSteeringMaxOffset);
|
||||
horizontalInput += randomOffset;
|
||||
horizontalInput = Mathf.Clamp(horizontalInput, -1f, 1f);
|
||||
}
|
||||
|
||||
// Reduce throttle when turning sharply.
|
||||
verticalInput = Mathf.Clamp(1f - (Mathf.Abs(horizontalInput) * 0.5f), 0f, 1f);
|
||||
|
||||
// Additional slowdown when approaching a checkpoint.
|
||||
if (distanceToCheckpoint < slowdownDistance)
|
||||
{
|
||||
float slowdownFactor = Mathf.Lerp(1 - slowdownStrength, 1f, distanceToCheckpoint / slowdownDistance);
|
||||
verticalInput *= slowdownFactor;
|
||||
}
|
||||
|
||||
// Switch to the next checkpoint when close enough.
|
||||
if (distanceToCheckpoint < checkpointThreshold)
|
||||
{
|
||||
currentCheckpointIndex = (currentCheckpointIndex + 1) % checkpoints.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Avoidance Logic ---
|
||||
// Look for nearby racers and, if any are detected, adjust steering and throttle.
|
||||
Collider[] nearbyColliders = Physics.OverlapSphere(transform.position, avoidanceRadius);
|
||||
Vector3 avoidanceVector = Vector3.zero;
|
||||
int avoidanceCount = 0;
|
||||
foreach (Collider col in nearbyColliders)
|
||||
{
|
||||
if (col.gameObject != gameObject && col.CompareTag(racerTag))
|
||||
{
|
||||
Vector3 diff = transform.position - col.transform.position;
|
||||
if (diff.magnitude > 0)
|
||||
{
|
||||
// Closer objects contribute more.
|
||||
avoidanceVector += diff.normalized / diff.magnitude;
|
||||
avoidanceCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (avoidanceCount > 0)
|
||||
{
|
||||
avoidanceVector /= avoidanceCount;
|
||||
// Project onto the horizontal plane.
|
||||
avoidanceVector = Vector3.ProjectOnPlane(avoidanceVector, transform.up).normalized;
|
||||
// Determine steering adjustment from avoidance.
|
||||
float avoidanceAngle = Vector3.SignedAngle(transform.forward, avoidanceVector, transform.up);
|
||||
float avoidanceInput = Mathf.Clamp(avoidanceAngle / 45f, -1f, 1f) * avoidanceSteeringStrength;
|
||||
horizontalInput += avoidanceInput;
|
||||
horizontalInput = Mathf.Clamp(horizontalInput, -1f, 1f);
|
||||
// Slow down throttle when avoiding.
|
||||
verticalInput *= avoidanceSlowdownMultiplier;
|
||||
}
|
||||
// --- End Avoidance Logic ---
|
||||
|
||||
// Apply movement: accelerate/decelerate toward the target speed, then update velocity and angular velocity.
|
||||
float targetSpeed = verticalInput * movementSpeed;
|
||||
if (verticalInput != 0)
|
||||
{
|
||||
currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, Time.fixedDeltaTime * acceleration);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSpeed = Mathf.Lerp(currentSpeed, 0, Time.fixedDeltaTime * deceleration);
|
||||
}
|
||||
|
||||
rb.linearVelocity = transform.forward * currentSpeed;
|
||||
float turn = horizontalInput * rotationSpeed;
|
||||
rb.angularVelocity = transform.up * turn * Mathf.Deg2Rad;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the AI's position to the last checkpoint it passed and reorients it so that:
|
||||
/// - Its front faces toward the nearest (other) checkpoint.
|
||||
/// - Its bottom is aligned with the nearby track surface (determined via a raycast and track tag).
|
||||
/// </summary>
|
||||
void ResetToCheckpoint()
|
||||
{
|
||||
if (checkpoints == null || checkpoints.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("No checkpoints assigned in the Inspector.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the last checkpoint passed.
|
||||
int lastCheckpointIndex = currentCheckpointIndex - 1;
|
||||
if (lastCheckpointIndex < 0)
|
||||
{
|
||||
lastCheckpointIndex = checkpoints.Length - 1;
|
||||
}
|
||||
Transform lastCheckpoint = checkpoints[lastCheckpointIndex];
|
||||
|
||||
// Find the nearest other checkpoint (to set the forward direction).
|
||||
Transform nearestOther = null;
|
||||
float nearestDistance = Mathf.Infinity;
|
||||
foreach (Transform cp in checkpoints)
|
||||
{
|
||||
if (cp == lastCheckpoint)
|
||||
continue;
|
||||
float d = Vector3.Distance(lastCheckpoint.position, cp.position);
|
||||
if (d < nearestDistance)
|
||||
{
|
||||
nearestDistance = d;
|
||||
nearestOther = cp;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine desired forward direction.
|
||||
Vector3 desiredForward = (nearestOther != null)
|
||||
? (nearestOther.position - lastCheckpoint.position).normalized
|
||||
: transform.forward;
|
||||
|
||||
// Determine the track’s surface normal to align the vehicle’s bottom.
|
||||
// Raycast downward from a point just above the checkpoint.
|
||||
Vector3 desiredUp = Vector3.up; // Fallback
|
||||
RaycastHit hit;
|
||||
Vector3 rayOrigin = lastCheckpoint.position + Vector3.up * 1.0f;
|
||||
if (Physics.Raycast(rayOrigin, -Vector3.up, out hit, trackRaycastDistance))
|
||||
{
|
||||
if (hit.collider.CompareTag(trackTag))
|
||||
{
|
||||
// Use the inverted hit normal so the vehicle’s bottom (–transform.up) is flush with the track.
|
||||
desiredUp = -hit.normal;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust desired forward so that it is perpendicular to desired up.
|
||||
desiredForward = Vector3.ProjectOnPlane(desiredForward, desiredUp).normalized;
|
||||
|
||||
Quaternion desiredRotation = Quaternion.LookRotation(desiredForward, desiredUp);
|
||||
|
||||
// Reset position and orientation.
|
||||
transform.position = lastCheckpoint.position;
|
||||
transform.rotation = desiredRotation;
|
||||
|
||||
// Clear any existing motion.
|
||||
rb.linearVelocity = Vector3.zero;
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
|
||||
Debug.Log("AI reset to checkpoint: " + lastCheckpoint.name +
|
||||
(nearestOther != null ? " with front facing: " + nearestOther.name : ""));
|
||||
}
|
||||
}
|
2
Assets/Scripts/Kart/AIHovercarController.cs.meta
Normal file
2
Assets/Scripts/Kart/AIHovercarController.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c250747ddb036f14faf25789ceb28a34
|
@ -1,86 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.VFX;
|
||||
|
||||
namespace SRL
|
||||
{
|
||||
public class ArcadeKart : MonoBehaviour
|
||||
{
|
||||
|
||||
public InputData Input { get; private set; }
|
||||
// the input sources that can control the kart
|
||||
IInput[] m_Inputs;
|
||||
|
||||
void GatherInputs()
|
||||
{
|
||||
// reset input
|
||||
Input = new InputData();
|
||||
|
||||
// gather nonzero input from our sources
|
||||
for (int i = 0; i < m_Inputs.Length; i++)
|
||||
{
|
||||
Input = m_Inputs[i].GenerateInput();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[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()
|
||||
{
|
||||
rb = GetComponent<Rigidbody>();
|
||||
m_Inputs = GetComponents<IInput>();
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
GatherInputs();
|
||||
Hover();
|
||||
Move();
|
||||
}
|
||||
|
||||
void Hover()
|
||||
{
|
||||
// Raycast to ground to simulate hover
|
||||
Ray ray = new Ray(transform.position, -transform.up);
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, hoverHeight * 2, groundLayer))
|
||||
{
|
||||
float hoverError = hoverHeight - hit.distance;
|
||||
float upwardSpeed = rb.linearVelocity.y;
|
||||
float appliedHoverForce = hoverError * hoverForce - upwardSpeed * hoverDampening;
|
||||
|
||||
rb.AddForce(Vector3.up * appliedHoverForce, ForceMode.Acceleration);
|
||||
}
|
||||
}
|
||||
|
||||
void Move()
|
||||
{
|
||||
// Forward movement
|
||||
float forwardInput = Input.Accelerate ? 1f : 0f;
|
||||
Vector3 forwardForce = transform.forward * forwardInput * forwardSpeed;
|
||||
rb.AddForce(forwardForce, ForceMode.Acceleration);
|
||||
|
||||
// Turning (rotate around Y-axis)
|
||||
float turnInput = Input.TurnInput;
|
||||
rb.AddTorque(Vector3.up * turnInput * turnSpeed, ForceMode.Acceleration);
|
||||
|
||||
// Apply drag to reduce endless acceleration
|
||||
rb.linearVelocity = Vector3.Lerp(rb.linearVelocity, Vector3.zero, drag * Time.fixedDeltaTime);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 438e8be3307824743b12d4e4f02825ea
|
@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 592688461ab994244b969670c11efe3f
|
@ -1,24 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace SRL
|
||||
{
|
||||
public struct InputData
|
||||
{
|
||||
public bool Accelerate;
|
||||
public bool Brake;
|
||||
public float TurnInput;
|
||||
}
|
||||
|
||||
public interface IInput
|
||||
{
|
||||
InputData GenerateInput();
|
||||
}
|
||||
|
||||
public abstract class BaseInput : MonoBehaviour, IInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Override this function to generate an XY input that can be used to steer and control the car.
|
||||
/// </summary>
|
||||
public abstract InputData GenerateInput();
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4dbe12014e130b54daf317a2e6be5b65
|
@ -2,29 +2,71 @@ using UnityEngine;
|
||||
|
||||
public class StableHovercarController : MonoBehaviour
|
||||
{
|
||||
public float hoverHeight = 3.0f;
|
||||
public float positionAdjustmentSpeed = 10.0f;
|
||||
public float raycastDistance = 10.0f;
|
||||
[Header("Hover Settings")]
|
||||
public float hoverHeight = 3.0f;
|
||||
public float positionAdjustmentSpeed = 10.0f;
|
||||
public float raycastDistance = 10.0f;
|
||||
public LayerMask terrainLayer;
|
||||
|
||||
[Header("Movement Settings")]
|
||||
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;
|
||||
|
||||
private float currentSpeed = 0.0f; // Speed that interpolates over time
|
||||
[Header("Reset Settings")]
|
||||
[Tooltip("Time (in seconds) without track contact before resetting the vehicle.")]
|
||||
public float timeBeforeReset = 3.0f;
|
||||
// Checkpoints are used to reposition the vehicle.
|
||||
public Transform[] checkpoints;
|
||||
|
||||
[Header("Track Orientation Settings")]
|
||||
[Tooltip("Distance to search downward for track (used to align the vehicle’s bottom).")]
|
||||
public float trackRaycastDistance = 10.0f;
|
||||
[Tooltip("Tag used on the track geometry.")]
|
||||
public string trackTag = "Track";
|
||||
|
||||
private float currentSpeed = 0.0f;
|
||||
private Rigidbody rb;
|
||||
private RacerProgress racerProgress;
|
||||
|
||||
// Timer for how long the raycast has failed to hit ground/track
|
||||
private float noContactTimer = 0.0f;
|
||||
// Flag that indicates whether a raycast hit was detected in this physics update.
|
||||
private bool groundContact = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
rb = GetComponent<Rigidbody>();
|
||||
rb.useGravity = false; // Disable gravity for stability
|
||||
rb.useGravity = false; // Disable gravity for hover stability
|
||||
|
||||
racerProgress = GetComponent<RacerProgress>();
|
||||
if (racerProgress == null)
|
||||
{
|
||||
Debug.LogWarning("No RacerProgress component found on this vehicle!");
|
||||
}
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
HandleHovering();
|
||||
HandleMovement();
|
||||
|
||||
// If we aren’t detecting ground/track contact, count up.
|
||||
if (!groundContact)
|
||||
{
|
||||
noContactTimer += Time.fixedDeltaTime;
|
||||
if (noContactTimer >= timeBeforeReset)
|
||||
{
|
||||
ResetToCheckpoint();
|
||||
noContactTimer = 0.0f; // Reset timer after repositioning
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the timer when ground/track is detected.
|
||||
noContactTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleHovering()
|
||||
@ -32,23 +74,30 @@ public class StableHovercarController : MonoBehaviour
|
||||
RaycastHit hit;
|
||||
Vector3 rayOrigin = transform.position;
|
||||
|
||||
// Cast a ray downward to detect the terrain
|
||||
// Cast a ray downward to detect the terrain (or track geometry).
|
||||
if (Physics.Raycast(rayOrigin, -transform.up, out hit, raycastDistance, terrainLayer))
|
||||
{
|
||||
// We have ground contact.
|
||||
groundContact = true;
|
||||
|
||||
// Determine the triangle on the mesh that was hit.
|
||||
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];
|
||||
|
||||
// Convert the triangle vertices to world space.
|
||||
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 to find the hit point on the triangle.
|
||||
Vector3 interpolatedPoint = worldVertex1 * hit.barycentricCoordinate.x +
|
||||
worldVertex2 * hit.barycentricCoordinate.y +
|
||||
worldVertex3 * hit.barycentricCoordinate.z;
|
||||
|
||||
// Similarly, interpolate the normals.
|
||||
Vector3 localNormal1 = mesh.normals[vertex1Index];
|
||||
Vector3 localNormal2 = mesh.normals[vertex2Index];
|
||||
Vector3 localNormal3 = mesh.normals[vertex3Index];
|
||||
@ -58,39 +107,130 @@ public class StableHovercarController : MonoBehaviour
|
||||
Vector3 interpolatedNormal = worldNormal1 * hit.barycentricCoordinate.x +
|
||||
worldNormal2 * hit.barycentricCoordinate.y +
|
||||
worldNormal3 * hit.barycentricCoordinate.z;
|
||||
interpolatedNormal.Normalize();
|
||||
interpolatedNormal.Normalize();
|
||||
|
||||
// Compute the target hover position.
|
||||
Vector3 targetPosition = interpolatedPoint + interpolatedNormal * hoverHeight;
|
||||
|
||||
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.fixedDeltaTime * positionAdjustmentSpeed);
|
||||
|
||||
// Smoothly rotate the vehicle to align with the terrain.
|
||||
Quaternion targetRotation = Quaternion.FromToRotation(transform.up, interpolatedNormal) * transform.rotation;
|
||||
rb.rotation = Quaternion.Slerp(rb.rotation, targetRotation, Time.fixedDeltaTime * 5.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No ground detected.
|
||||
groundContact = false;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleMovement()
|
||||
{
|
||||
// Get player input
|
||||
// Get player input.
|
||||
float input = Input.GetAxis("Vertical");
|
||||
|
||||
// Determine target speed based on input
|
||||
// Calculate target speed.
|
||||
float targetSpeed = input * movementSpeed;
|
||||
|
||||
// Smooth acceleration/deceleration.
|
||||
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
|
||||
// Apply forward movement.
|
||||
rb.linearVelocity = transform.forward * currentSpeed;
|
||||
|
||||
// Apply rotation.
|
||||
float turn = Input.GetAxis("Horizontal") * rotationSpeed;
|
||||
rb.angularVelocity = transform.up * turn * Mathf.Deg2Rad;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the vehicle’s position to the last checkpoint reached (from RacerProgress) and orients it so that:
|
||||
/// - Its front faces the nearest (other) checkpoint.
|
||||
/// - Its bottom is aligned to the track (using a raycast and the specified track tag).
|
||||
/// </summary>
|
||||
void ResetToCheckpoint()
|
||||
{
|
||||
// Make sure we have checkpoints.
|
||||
if (checkpoints == null || checkpoints.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("No checkpoints have been assigned in the Inspector.");
|
||||
return;
|
||||
}
|
||||
if (racerProgress == null)
|
||||
{
|
||||
Debug.LogWarning("RacerProgress component is missing. Cannot reset to checkpoint.");
|
||||
return;
|
||||
}
|
||||
int cpIndex = racerProgress.currentCheckpointIndex;
|
||||
if (cpIndex < 0 || cpIndex >= checkpoints.Length)
|
||||
{
|
||||
Debug.LogWarning("Invalid checkpoint index in RacerProgress!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Position: use the checkpoint that the racer last reached.
|
||||
Transform lastCheckpoint = checkpoints[cpIndex];
|
||||
|
||||
// Find the "other" checkpoint nearest to the last checkpoint.
|
||||
// (This will be used to determine the forward direction.)
|
||||
Transform nearestOther = null;
|
||||
float nearestDistance = Mathf.Infinity;
|
||||
foreach (Transform cp in checkpoints)
|
||||
{
|
||||
if (cp == lastCheckpoint)
|
||||
continue;
|
||||
float d = Vector3.Distance(lastCheckpoint.position, cp.position);
|
||||
if (d < nearestDistance)
|
||||
{
|
||||
nearestDistance = d;
|
||||
nearestOther = cp;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine desired forward:
|
||||
// If we found another checkpoint, aim toward it.
|
||||
// (Project the vector onto the plane defined by the desired up.)
|
||||
Vector3 desiredForward = (nearestOther != null)
|
||||
? (nearestOther.position - lastCheckpoint.position).normalized
|
||||
: transform.forward;
|
||||
|
||||
// Determine the track’s surface normal so we can align the vehicle’s bottom.
|
||||
// We cast a ray downward from a point just above the checkpoint.
|
||||
Vector3 desiredUp = Vector3.up; // Fallback if no track is detected.
|
||||
RaycastHit hit;
|
||||
Vector3 rayOrigin = lastCheckpoint.position + Vector3.up * 1.0f;
|
||||
if (Physics.Raycast(rayOrigin, -Vector3.up, out hit, trackRaycastDistance))
|
||||
{
|
||||
if (hit.collider.CompareTag(trackTag))
|
||||
{
|
||||
// To have the vehicle’s bottom (–transform.up) flush with the track,
|
||||
// we set our desired up vector to be the inverse of the track’s normal.
|
||||
desiredUp = -hit.normal;
|
||||
}
|
||||
}
|
||||
|
||||
// Now adjust the desired forward so that it is perpendicular to the desired up.
|
||||
desiredForward = Vector3.ProjectOnPlane(desiredForward, desiredUp).normalized;
|
||||
|
||||
// Build the final rotation.
|
||||
Quaternion desiredRotation = Quaternion.LookRotation(desiredForward, desiredUp);
|
||||
|
||||
// Reset position and orientation.
|
||||
transform.position = lastCheckpoint.position;
|
||||
transform.rotation = desiredRotation;
|
||||
|
||||
// Clear any existing motion.
|
||||
rb.linearVelocity = Vector3.zero;
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
|
||||
Debug.Log("Vehicle reset to checkpoint: " + lastCheckpoint.name +
|
||||
(nearestOther != null ? " with front facing: " + nearestOther.name : ""));
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace SRL {
|
||||
|
||||
public class KeyboardInput : BaseInput
|
||||
{
|
||||
public string TurnInputName = "Horizontal";
|
||||
public string AccelerateButtonName = "Accelerate";
|
||||
public string BrakeButtonName = "Brake";
|
||||
|
||||
public override InputData GenerateInput() {
|
||||
return new InputData
|
||||
{
|
||||
Accelerate = Input.GetButton(AccelerateButtonName),
|
||||
Brake = Input.GetButton(BrakeButtonName),
|
||||
TurnInput = Input.GetAxis("Horizontal")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de1851cd35e729f4aa33011a49cd59fb
|
2
Assets/Scripts/Kart/ObjectBanking.cs.meta
Normal file
2
Assets/Scripts/Kart/ObjectBanking.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f060abec37829be48a8165282e7c3aeb
|
8
Assets/Scripts/RaceGameManager.meta
Normal file
8
Assets/Scripts/RaceGameManager.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33bad5ae96b211b4ba79fa289a4eb6b9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
24
Assets/Scripts/RaceGameManager/Checkpoint.cs
Normal file
24
Assets/Scripts/RaceGameManager/Checkpoint.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class Checkpoint : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The order index of this checkpoint along the track.")]
|
||||
public int checkpointIndex = 0;
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
RacerProgress progress = other.GetComponent<RacerProgress>();
|
||||
if (progress != null && RaceManager.Instance != null)
|
||||
{
|
||||
// Only update if the racer is expecting this checkpoint next.
|
||||
if (progress.currentCheckpointIndex == checkpointIndex)
|
||||
{
|
||||
int totalCheckpoints = RaceManager.Instance.numberOfCheckpoints;
|
||||
progress.currentCheckpointIndex = (checkpointIndex + 1) % totalCheckpoints;
|
||||
// If the racer just passed the final checkpoint, increment the lap count.
|
||||
if (checkpointIndex == totalCheckpoints - 1)
|
||||
progress.lapCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
2
Assets/Scripts/RaceGameManager/Checkpoint.cs.meta
Normal file
2
Assets/Scripts/RaceGameManager/Checkpoint.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c3aaa50cd9e11d49801b7daff0a21bf
|
13
Assets/Scripts/RaceGameManager/FinishLine.cs
Normal file
13
Assets/Scripts/RaceGameManager/FinishLine.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class FinishLine : MonoBehaviour
|
||||
{
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
RacerProgress progress = other.GetComponent<RacerProgress>();
|
||||
if (progress != null && RaceManager.Instance != null)
|
||||
{
|
||||
RaceManager.Instance.CheckFinish(progress);
|
||||
}
|
||||
}
|
||||
}
|
2
Assets/Scripts/RaceGameManager/FinishLine.cs.meta
Normal file
2
Assets/Scripts/RaceGameManager/FinishLine.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a4bc101ca357064ca138761e1319354
|
72
Assets/Scripts/RaceGameManager/RaceManager.cs
Normal file
72
Assets/Scripts/RaceGameManager/RaceManager.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class RaceManager : MonoBehaviour
|
||||
{
|
||||
public static RaceManager Instance;
|
||||
|
||||
[Header("Race Settings")]
|
||||
[Tooltip("Total number of laps needed to finish the race.")]
|
||||
public int totalLaps = 3;
|
||||
[Tooltip("Total number of checkpoints in the race.")]
|
||||
public int numberOfCheckpoints = 0; // Set this in the Inspector to match your track setup
|
||||
|
||||
[Header("Finish Line Settings")]
|
||||
[Tooltip("Assign the finish line object (with a trigger collider) here.")]
|
||||
public Transform finishLine;
|
||||
|
||||
private List<RacerProgress> racers = new List<RacerProgress>();
|
||||
public bool raceFinished = false;
|
||||
public string winnerName = "";
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Basic singleton setup.
|
||||
if (Instance == null)
|
||||
Instance = this;
|
||||
else
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Optionally, automatically find all racers by tag.
|
||||
GameObject[] racerObjects = GameObject.FindGameObjectsWithTag("Racer");
|
||||
foreach (GameObject racer in racerObjects)
|
||||
{
|
||||
RacerProgress progress = racer.GetComponent<RacerProgress>();
|
||||
if (progress != null)
|
||||
racers.Add(progress);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the highest “progress value” among all racers.
|
||||
/// (Calculated as: lap count * numberOfCheckpoints + current checkpoint index.)
|
||||
/// </summary>
|
||||
public float GetLeaderProgress()
|
||||
{
|
||||
float leaderProgress = 0f;
|
||||
foreach (RacerProgress rp in racers)
|
||||
{
|
||||
float progressValue = rp.lapCount * numberOfCheckpoints + rp.currentCheckpointIndex;
|
||||
if (progressValue > leaderProgress)
|
||||
leaderProgress = progressValue;
|
||||
}
|
||||
return leaderProgress;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this when a racer crosses the finish line.
|
||||
/// </summary>
|
||||
public void CheckFinish(RacerProgress rp)
|
||||
{
|
||||
if (rp.lapCount >= totalLaps && !raceFinished)
|
||||
{
|
||||
raceFinished = true;
|
||||
winnerName = rp.gameObject.name;
|
||||
Debug.Log("Race Finished! Winner: " + winnerName);
|
||||
// Here you might trigger UI updates, stop all racers, etc.
|
||||
}
|
||||
}
|
||||
}
|
2
Assets/Scripts/RaceGameManager/RaceManager.cs.meta
Normal file
2
Assets/Scripts/RaceGameManager/RaceManager.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18ac36268412d1946a31d8945cc6ac33
|
9
Assets/Scripts/RaceGameManager/RacerProgress.cs
Normal file
9
Assets/Scripts/RaceGameManager/RacerProgress.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class RacerProgress : MonoBehaviour
|
||||
{
|
||||
// The checkpoint index the racer is currently aiming for.
|
||||
public int currentCheckpointIndex = 0;
|
||||
// The current lap count.
|
||||
public int lapCount = 0;
|
||||
}
|
2
Assets/Scripts/RaceGameManager/RacerProgress.cs.meta
Normal file
2
Assets/Scripts/RaceGameManager/RacerProgress.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80f1410edd2d20447b553914aa3c9c7f
|
@ -11,9 +11,12 @@ EditorBuildSettings:
|
||||
- enabled: 0
|
||||
path: Assets/Scenes/SampleScene.unity
|
||||
guid: 99c9720ab356a0642a771bea13969a05
|
||||
- enabled: 1
|
||||
path: Assets/Scenes/TestTrack.unity
|
||||
- enabled: 0
|
||||
path: Assets/Scenes/TestTrackWithAI.unity
|
||||
guid: 933d22bf6aedba544849d3821a5d3a91
|
||||
- enabled: 1
|
||||
path: Assets/Scenes/AITrack.unity
|
||||
guid: 79f34c11850512b418ac4060394f87ce
|
||||
m_configObjects:
|
||||
com.unity.input.settings.actions: {fileID: -944628639613478452, guid: 052faaac586de48259a63d0c4782560b, type: 3}
|
||||
m_UseUCBPForAssetBundles: 0
|
||||
|
@ -3,7 +3,9 @@
|
||||
--- !u!78 &1
|
||||
TagManager:
|
||||
serializedVersion: 3
|
||||
tags: []
|
||||
tags:
|
||||
- Racer
|
||||
- Track
|
||||
layers:
|
||||
- Default
|
||||
- TransparentFX
|
||||
|
Loading…
x
Reference in New Issue
Block a user