update : rewrite car controller, add terrain

This commit is contained in:
Cviat 2026-07-20 09:22:00 +03:00
parent 7533103d11
commit da08bcc9d3
10 changed files with 1057 additions and 571 deletions

74
.gitignore vendored
View File

@ -1,74 +0,0 @@
# This .gitignore file should be placed at the root of your Unity project directory
#
# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
#
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Uu]ser[Ss]ettings/
# MemoryCaptures can get excessive
/[Mm]emoryCaptures/
# Asset meta data should only be ignored when the corresponding asset is also ignored
!/[Aa]ssets/**/*.meta
# Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools*
# Autogenerated Jetbrains Rider plugin
/[Aa]ssets/Plugins/Editor/JetBrains*
# Visual Studio cache directory
.vs/
.gradle/
# Gradle build aux
/Assets/Plugins/Android/mainTemplate.gradle
/Assets/Plugins/Android/launcherTemplate.gradle
# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.opendb
*.VC.db
# Unity3D generated meta files
*.pidb.meta
*.pdb.meta
*.mdb.meta
# Unity3D generated file on crash reports
sysinfo.txt
# Builds
*.apk
*.aab
*.unitypackage
*.app
# Crashlytics generated file
crashlytics-build.properties
# Packed Addressables
/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*
# Temporary auto-generated Android Assets
/[Aa]ssets/[Ss]treaming[Aa]ssets/aa/*
.idea/

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 5eba01364f86498419063e7f96a3ccce
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,432 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 10
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 12
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 12
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 512
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 256
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 1
m_PVRDenoiserTypeDirect: 1
m_PVRDenoiserTypeIndirect: 1
m_PVRDenoiserTypeAO: 1
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 1
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0}
m_LightingSettings: {fileID: 0}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &330585543
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 330585546}
- component: {fileID: 330585545}
- component: {fileID: 330585544}
- component: {fileID: 330585547}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &330585544
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 330585543}
m_Enabled: 1
--- !u!20 &330585545
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 330585543}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &330585546
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 330585543}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10}
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 &330585547
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 330585543}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_RenderShadows: 1
m_RequiresDepthTextureOption: 2
m_RequiresOpaqueTextureOption: 2
m_CameraType: 0
m_Cameras: []
m_RendererIndex: -1
m_VolumeLayerMask:
serializedVersion: 2
m_Bits: 1
m_VolumeTrigger: {fileID: 0}
m_VolumeFrameworkUpdateModeOption: 2
m_RenderPostProcessing: 1
m_Antialiasing: 0
m_AntialiasingQuality: 2
m_StopNaN: 0
m_Dithering: 0
m_ClearDepth: 1
m_AllowXRRendering: 1
m_AllowHDROutput: 1
m_UseScreenCoordOverride: 0
m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
m_RequiresDepthTexture: 0
m_RequiresColorTexture: 0
m_Version: 2
m_TaaSettings:
quality: 3
frameInfluence: 0.1
jitterScale: 1
mipBias: 0
varianceClampScale: 0.9
contrastAdaptiveSharpening: 0
--- !u!1 &410087039
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 410087041}
- component: {fileID: 410087040}
- component: {fileID: 410087042}
m_Layer: 0
m_Name: Directional Light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!108 &410087040
Light:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 410087039}
m_Enabled: 1
serializedVersion: 11
m_Type: 1
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_Intensity: 2
m_Range: 10
m_SpotAngle: 30
m_InnerSpotAngle: 21.80208
m_CookieSize: 10
m_Shadows:
m_Type: 2
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_CullingMatrixOverride:
e00: 1
e01: 0
e02: 0
e03: 0
e10: 0
e11: 1
e12: 0
e13: 0
e20: 0
e21: 0
e22: 1
e23: 0
e30: 0
e31: 0
e32: 0
e33: 1
m_UseCullingMatrixOverride: 0
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingLayerMask: 1
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 5000
m_UseColorTemperature: 1
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
m_UseBoundingSphereOverride: 0
m_UseViewFrustumForShadowCasterCull: 1
m_ForceVisible: 0
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &410087041
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 410087039}
serializedVersion: 2
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!114 &410087042
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 410087039}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Version: 3
m_UsePipelineSettings: 1
m_AdditionalLightsShadowResolutionTier: 2
m_LightLayerMask: 1
m_RenderingLayers: 1
m_CustomShadowLayers: 0
m_ShadowLayerMask: 1
m_ShadowRenderingLayers: 1
m_LightCookieSize: {x: 1, y: 1}
m_LightCookieOffset: {x: 0, y: 0}
m_SoftShadowQuality: 1
--- !u!1 &832575517
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 832575519}
- component: {fileID: 832575518}
m_Layer: 0
m_Name: Global Volume
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &832575518
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 832575517}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IsGlobal: 1
priority: 0
blendDistance: 0
weight: 1
sharedProfile: {fileID: 11400000, guid: 10fc4df2da32a41aaa32d77bc913491c, type: 2}
--- !u!4 &832575519
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 832575517}
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!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- {fileID: 330585546}
- {fileID: 410087041}
- {fileID: 832575519}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 99c9720ab356a0642a771bea13969a05
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -342,6 +342,9 @@ MonoBehaviour:
skyOcclusionIntensityMultiplier:
m_OverrideState: 1
m_Value: 1
worldOffset:
m_OverrideState: 1
m_Value: {x: 0, y: 0, z: 0}
--- !u!114 &-1216621516061285780
MonoBehaviour:
m_ObjectHideFlags: 3
@ -376,6 +379,9 @@ MonoBehaviour:
highQualityFiltering:
m_OverrideState: 1
m_Value: 0
filter:
m_OverrideState: 1
m_Value: 0
downscale:
m_OverrideState: 1
m_Value: 0
@ -462,8 +468,6 @@ MonoBehaviour:
- {fileID: -6288072647309666549}
- {fileID: 7518938298396184218}
- {fileID: -1410297666881709256}
- {fileID: -7750755424749557576}
- {fileID: -5139089513906902183}
--- !u!114 &853819529557874667
MonoBehaviour:
m_ObjectHideFlags: 3

View File

@ -71,6 +71,39 @@ WheelCollider:
m_LayerOverridePriority: 0
m_Enabled: 1
m_ProvidesContacts: 0
--- !u!1 &750113556555537078
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9114007139308049182}
m_Layer: 0
m_Name: Audio
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &9114007139308049182
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 750113556555537078}
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: 5897662229585756618}
- {fileID: 1619493721624094195}
m_Father: {fileID: 4772777578382570152}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1220105584347587854
GameObject:
m_ObjectHideFlags: 0
@ -142,6 +175,299 @@ WheelCollider:
m_LayerOverridePriority: 0
m_Enabled: 1
m_ProvidesContacts: 0
--- !u!1 &2599938933167188421
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7863987729731623420}
m_Layer: 0
m_Name: Effects
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7863987729731623420
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2599938933167188421}
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: 8749525721669873730}
- {fileID: 6943352201908577945}
- {fileID: 4860281492798288263}
- {fileID: 3017463661873623124}
m_Father: {fileID: 4772777578382570152}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &4250428261150226367
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1619493721624094195}
- component: {fileID: 5164767240841886004}
m_Layer: 0
m_Name: TireScreechSound
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1619493721624094195
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4250428261150226367}
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: 9114007139308049182}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!82 &5164767240841886004
AudioSource:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4250428261150226367}
m_Enabled: 1
serializedVersion: 4
OutputAudioMixerGroup: {fileID: 0}
m_audioClip: {fileID: 0}
m_Resource: {fileID: 8300000, guid: f632e2ace80a32e47a2c531f64901a50, type: 3}
m_PlayOnAwake: 0
m_Volume: 0.4
m_Pitch: 1
Loop: 1
Mute: 0
Spatialize: 0
SpatializePostEffects: 0
Priority: 128
DopplerLevel: 0.3
MinDistance: 12
MaxDistance: 70
Pan2D: 0
rolloffMode: 1
BypassEffects: 0
BypassListenerEffects: 0
BypassReverbZones: 0
rolloffCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
panLevelCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
spreadCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
reverbZoneMixCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
--- !u!1 &5725176332190465528
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5897662229585756618}
- component: {fileID: 2872479692476395633}
m_Layer: 0
m_Name: EngineSound
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5897662229585756618
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5725176332190465528}
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: 9114007139308049182}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!82 &2872479692476395633
AudioSource:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5725176332190465528}
m_Enabled: 1
serializedVersion: 4
OutputAudioMixerGroup: {fileID: 0}
m_audioClip: {fileID: 0}
m_Resource: {fileID: 8300000, guid: 771ce407ce807b74885ec23ebd1e6647, type: 3}
m_PlayOnAwake: 0
m_Volume: 0.65
m_Pitch: 1
Loop: 1
Mute: 0
Spatialize: 0
SpatializePostEffects: 0
Priority: 128
DopplerLevel: 0.3
MinDistance: 24
MaxDistance: 90
Pan2D: 0
rolloffMode: 1
BypassEffects: 0
BypassListenerEffects: 0
BypassReverbZones: 0
rolloffCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
panLevelCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
spreadCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
reverbZoneMixCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
--- !u!1 &6741570655071805230
GameObject:
m_ObjectHideFlags: 0
@ -251,6 +577,8 @@ Transform:
- {fileID: 4673438351332549834}
- {fileID: 3534324926145310694}
- {fileID: 279644236469480577}
- {fileID: 7863987729731623420}
- {fileID: 9114007139308049182}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!54 &5167617291018270
@ -321,13 +649,24 @@ MonoBehaviour:
frontRightVisual: {fileID: 0}
rearLeftVisual: {fileID: 0}
rearRightVisual: {fileID: 0}
motorTorque: 950
brakeTorque: 1700
maxSteerAngle: 32
reverseTorqueScale: 0.45
downforce: 35
centerOfMassOffset: {x: 0, y: -0.45, z: 0.15}
maxSpeedKmh: 120
maxReverseSpeedKmh: 45
accelerationMultiplier: 6
maxSteerAngle: 35
steeringSpeed: 0.5
brakeForce: 450
decelerationMultiplier: 2
handbrakeDriftMultiplier: 5
downforce: 35
centerOfMass: {x: 0, y: -0.45, z: 0.15}
useEffects: 1
rearLeftSmoke: {fileID: 8749525721655742662}
rearRightSmoke: {fileID: 6943352201889072669}
rearLeftSkid: {fileID: 4860281492798288262}
rearRightSkid: {fileID: 3017463661873623125}
useSounds: 1
engineSound: {fileID: 2872479692476395633}
tireScreechSound: {fileID: 5164767240841886004}
--- !u!114 &8664118715040108722
MonoBehaviour:
m_ObjectHideFlags: 0
@ -423,6 +762,282 @@ WheelCollider:
m_LayerOverridePriority: 0
m_Enabled: 1
m_ProvidesContacts: 0
--- !u!1001 &2782393766222725750
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 7863987729731623420}
m_Modifications:
- target: {fileID: 7344874181333496816, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_Emitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalPosition.x
value: -0.8716712
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalPosition.y
value: 0.27369422
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalPosition.z
value: -0.42227113
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496819, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_Name
value: LeftTireSkid
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
--- !u!96 &4860281492798288262 stripped
TrailRenderer:
m_CorrespondingSourceObject: {fileID: 7344874181333496816, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
m_PrefabInstance: {fileID: 2782393766222725750}
m_PrefabAsset: {fileID: 0}
--- !u!4 &4860281492798288263 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
m_PrefabInstance: {fileID: 2782393766222725750}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &4638004351678942375
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 7863987729731623420}
m_Modifications:
- target: {fileID: 4121091811543088291, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_Name
value: LeftTireSmoke_PS
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalPosition.x
value: -1.0716712
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalPosition.y
value: 0.023694217
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalPosition.z
value: -0.42227113
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
--- !u!198 &8749525721655742662 stripped
ParticleSystem:
m_CorrespondingSourceObject: {fileID: 4121091811527957601, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
m_PrefabInstance: {fileID: 4638004351678942375}
m_PrefabAsset: {fileID: 0}
--- !u!4 &8749525721669873730 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
m_PrefabInstance: {fileID: 4638004351678942375}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &5480338763159847845
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 7863987729731623420}
m_Modifications:
- target: {fileID: 7344874181333496816, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_Emitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalPosition.x
value: 0.87719953
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalPosition.y
value: 0.2736943
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalPosition.z
value: -0.42227113
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7344874181333496819, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
propertyPath: m_Name
value: RightTireSkid
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
--- !u!4 &3017463661873623124 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 7344874181333496817, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
m_PrefabInstance: {fileID: 5480338763159847845}
m_PrefabAsset: {fileID: 0}
--- !u!96 &3017463661873623125 stripped
TrailRenderer:
m_CorrespondingSourceObject: {fileID: 7344874181333496816, guid: ab4ea67cd9337c341af0bd7182c60f92, type: 3}
m_PrefabInstance: {fileID: 5480338763159847845}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &6443156973287594620
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 7863987729731623420}
m_Modifications:
- target: {fileID: 4121091811543088291, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_Name
value: RightTireSmoke_PS
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalPosition.x
value: 1.0771996
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalPosition.y
value: 0.023694307
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalPosition.z
value: -0.42227113
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
--- !u!198 &6943352201889072669 stripped
ParticleSystem:
m_CorrespondingSourceObject: {fileID: 4121091811527957601, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
m_PrefabInstance: {fileID: 6443156973287594620}
m_PrefabAsset: {fileID: 0}
--- !u!4 &6943352201908577945 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 4121091811543137509, guid: ddf4ea2625767fd4bb4153e7e4009ad5, type: 3}
m_PrefabInstance: {fileID: 6443156973287594620}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &6787725748994149289
PrefabInstance:
m_ObjectHideFlags: 0

View File

@ -247,15 +247,15 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 5333045600610406045, guid: 5be9815168b750e43a3cafd4741a38ec, type: 3}
propertyPath: m_LocalPosition.x
value: 151.49287
value: 125.79
objectReference: {fileID: 0}
- target: {fileID: 5333045600610406045, guid: 5be9815168b750e43a3cafd4741a38ec, type: 3}
propertyPath: m_LocalPosition.y
value: -0.00000177061
value: 18.48
objectReference: {fileID: 0}
- target: {fileID: 5333045600610406045, guid: 5be9815168b750e43a3cafd4741a38ec, type: 3}
propertyPath: m_LocalPosition.z
value: 96.31607
value: 102.32
objectReference: {fileID: 0}
- target: {fileID: 5333045600610406045, guid: 5be9815168b750e43a3cafd4741a38ec, type: 3}
propertyPath: m_LocalRotation.w
@ -626,7 +626,7 @@ Transform:
m_GameObject: {fileID: 1735981100}
serializedVersion: 2
m_LocalRotation: {x: 0.4066569, y: 0, z: 0, w: 0.913581}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalPosition: {x: 0, y: 6.02, z: 6.68}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []

View File

@ -9,6 +9,10 @@ namespace RaceFields.EditorTools
{
private const string BuggyPrefabPath = "Assets/_Project/Prefabs/Vehicles/Player/Buggy_Player.prefab";
private const string CameraPrefabPath = "Assets/_Project/Prefabs/Cameras/Buggy_ThirdPersonCamera.prefab";
private const string TireSmokePrefabPath = "Assets/PROMETEO - Car Controller/Effects/Particle Systems/Prefabs/TireSmoke_PS.prefab";
private const string TireSkidPrefabPath = "Assets/PROMETEO - Car Controller/Effects/Trails/Prefabs/TireSkid.prefab";
private const string EngineSoundPath = "Assets/PROMETEO - Car Controller/Sounds/CarEngine.wav";
private const string TireScreechSoundPath = "Assets/PROMETEO - Car Controller/Sounds/TireScreech.wav";
[MenuItem("Race Fields/Setup/Rebuild Buggy Prefab")]
public static void RebuildBuggyPrefab()
@ -18,13 +22,15 @@ namespace RaceFields.EditorTools
{
EnsureComponent<Rigidbody>(root, ConfigureBody);
EnsureComponent<BoxCollider>(root, ConfigureBodyCollider);
EnsureComponent<ArcadeBuggyController>(root, null);
ArcadeBuggyController controller = EnsureComponent<ArcadeBuggyController>(root, null);
EnsureComponent<BuggyWheelSetup>(root, setup => setup.AlignAllWheels());
SetupWheel(root.transform, "F_L", "WheelCollider_FL");
SetupWheel(root.transform, "F_R", "WheelCollider_FR");
SetupWheel(root.transform, "B_L", "WheelCollider_RL");
SetupWheel(root.transform, "B_R", "WheelCollider_RR");
SetupEffects(root.transform, controller);
SetupSounds(root.transform, controller);
BuggyWheelSetup wheelSetup = root.GetComponent<BuggyWheelSetup>();
wheelSetup.AlignAllWheels();
@ -121,6 +127,117 @@ namespace RaceFields.EditorTools
wheelCollider.suspensionSpring = spring;
}
private static void SetupEffects(Transform root, ArcadeBuggyController controller)
{
GameObject effectsRoot = GetOrCreateChild(root, "Effects");
Transform rearLeftWheel = FindDescendant(root, "WheelCollider_RL");
Transform rearRightWheel = FindDescendant(root, "WheelCollider_RR");
ParticleSystem rearLeftSmoke = SetupEffectPrefab<ParticleSystem>(effectsRoot.transform, rearLeftWheel, "LeftTireSmoke_PS", TireSmokePrefabPath, new Vector3(-0.2f, -0.25f, 0f));
ParticleSystem rearRightSmoke = SetupEffectPrefab<ParticleSystem>(effectsRoot.transform, rearRightWheel, "RightTireSmoke_PS", TireSmokePrefabPath, new Vector3(0.2f, -0.25f, 0f));
TrailRenderer rearLeftSkid = SetupEffectPrefab<TrailRenderer>(effectsRoot.transform, rearLeftWheel, "LeftTireSkid", TireSkidPrefabPath, Vector3.zero);
TrailRenderer rearRightSkid = SetupEffectPrefab<TrailRenderer>(effectsRoot.transform, rearRightWheel, "RightTireSkid", TireSkidPrefabPath, Vector3.zero);
SerializedObject serializedController = new SerializedObject(controller);
serializedController.FindProperty("maxSpeedKmh").floatValue = 120f;
serializedController.FindProperty("maxReverseSpeedKmh").floatValue = 45f;
serializedController.FindProperty("accelerationMultiplier").floatValue = 6f;
serializedController.FindProperty("maxSteerAngle").floatValue = 35f;
serializedController.FindProperty("steeringSpeed").floatValue = 0.5f;
serializedController.FindProperty("brakeForce").floatValue = 450f;
serializedController.FindProperty("decelerationMultiplier").floatValue = 2f;
serializedController.FindProperty("handbrakeDriftMultiplier").floatValue = 5f;
serializedController.FindProperty("useEffects").boolValue = true;
serializedController.FindProperty("rearLeftSmoke").objectReferenceValue = rearLeftSmoke;
serializedController.FindProperty("rearRightSmoke").objectReferenceValue = rearRightSmoke;
serializedController.FindProperty("rearLeftSkid").objectReferenceValue = rearLeftSkid;
serializedController.FindProperty("rearRightSkid").objectReferenceValue = rearRightSkid;
serializedController.ApplyModifiedPropertiesWithoutUndo();
}
private static void SetupSounds(Transform root, ArcadeBuggyController controller)
{
GameObject audioRoot = GetOrCreateChild(root, "Audio");
AudioSource engineSource = SetupAudioSource(audioRoot.transform, "EngineSound", EngineSoundPath, true, 0.65f, 1f, 24f, 90f);
AudioSource tireScreechSource = SetupAudioSource(audioRoot.transform, "TireScreechSound", TireScreechSoundPath, true, 0.4f, 1f, 12f, 70f);
SerializedObject serializedController = new SerializedObject(controller);
serializedController.FindProperty("useSounds").boolValue = true;
serializedController.FindProperty("engineSound").objectReferenceValue = engineSource;
serializedController.FindProperty("tireScreechSound").objectReferenceValue = tireScreechSource;
serializedController.ApplyModifiedPropertiesWithoutUndo();
}
private static AudioSource SetupAudioSource(Transform parent, string sourceName, string clipPath, bool loop, float volume, float pitch, float minDistance, float maxDistance)
{
GameObject sourceObject = GetOrCreateChild(parent, sourceName);
AudioSource source = sourceObject.GetComponent<AudioSource>();
if (source == null)
source = sourceObject.AddComponent<AudioSource>();
source.clip = AssetDatabase.LoadAssetAtPath<AudioClip>(clipPath);
source.playOnAwake = false;
source.loop = loop;
source.volume = volume;
source.pitch = pitch;
source.spatialBlend = 1f;
source.rolloffMode = AudioRolloffMode.Linear;
source.minDistance = minDistance;
source.maxDistance = maxDistance;
source.dopplerLevel = 0.3f;
return source;
}
private static T SetupEffectPrefab<T>(Transform parent, Transform wheel, string effectName, string prefabPath, Vector3 localOffset) where T : Component
{
if (wheel == null)
return null;
Transform existing = FindDescendant(parent, effectName);
GameObject effectObject;
if (existing != null)
{
effectObject = existing.gameObject;
}
else
{
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
effectObject = prefab != null
? (GameObject)PrefabUtility.InstantiatePrefab(prefab)
: new GameObject(effectName);
}
effectObject.name = effectName;
effectObject.transform.SetParent(parent, false);
effectObject.transform.position = wheel.position + TransformDirection(wheel, localOffset);
effectObject.transform.rotation = wheel.rotation;
effectObject.transform.localScale = Vector3.one;
T component = effectObject.GetComponentInChildren<T>(true);
if (component is TrailRenderer trail)
trail.emitting = false;
else if (component is ParticleSystem particles)
particles.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
return component;
}
private static Vector3 TransformDirection(Transform wheel, Vector3 localOffset)
{
return wheel.TransformDirection(localOffset);
}
private static GameObject GetOrCreateChild(Transform root, string childName)
{
Transform existing = FindDescendant(root, childName);
if (existing != null)
return existing.gameObject;
GameObject child = new GameObject(childName);
child.transform.SetParent(root, false);
return child;
}
private static float EstimateRadius(Transform visual)
{
Renderer renderer = visual.GetComponentInChildren<Renderer>();

View File

@ -21,20 +21,60 @@ namespace RaceFields.Vehicles
[SerializeField] private Transform rearRightVisual;
[Header("Driving")]
[SerializeField] private float motorTorque = 950f;
[SerializeField] private float brakeTorque = 1700f;
[SerializeField] private float maxSteerAngle = 32f;
[SerializeField] private float reverseTorqueScale = 0.45f;
[SerializeField, Range(20f, 190f)] private float maxSpeedKmh = 120f;
[SerializeField, Range(10f, 120f)] private float maxReverseSpeedKmh = 45f;
[SerializeField, Range(1f, 10f)] private float accelerationMultiplier = 6f;
[SerializeField, Range(10f, 45f)] private float maxSteerAngle = 35f;
[SerializeField, Range(0.1f, 1f)] private float steeringSpeed = 0.5f;
[SerializeField, Range(100f, 600f)] private float brakeForce = 450f;
[SerializeField, Range(1f, 10f)] private float decelerationMultiplier = 2f;
[SerializeField, Range(1f, 10f)] private float handbrakeDriftMultiplier = 5f;
[SerializeField] private float downforce = 35f;
[Header("Stability")]
[SerializeField] private Vector3 centerOfMassOffset = new Vector3(0f, -0.45f, 0.15f);
[SerializeField] private float maxSpeedKmh = 120f;
[SerializeField] private Vector3 centerOfMass = new Vector3(0f, -0.45f, 0.15f);
[Header("Effects")]
[SerializeField] private bool useEffects = true;
[SerializeField] private ParticleSystem rearLeftSmoke;
[SerializeField] private ParticleSystem rearRightSmoke;
[SerializeField] private TrailRenderer rearLeftSkid;
[SerializeField] private TrailRenderer rearRightSkid;
[Header("Sounds")]
[SerializeField] private bool useSounds;
[SerializeField] private AudioSource engineSound;
[SerializeField] private AudioSource tireScreechSound;
public float SpeedKmh { get; private set; }
public bool IsDrifting { get; private set; }
public bool IsTractionLocked { get; private set; }
private const float TorquePerAccelerationStep = 50f;
private const float DriftVelocityThreshold = 2.5f;
private const float SkidVelocityThreshold = 5f;
private const float EffectsMinSpeedKmh = 12f;
private Rigidbody body;
private float throttle;
private float steering;
private bool brake;
private float throttleInput;
private float steeringInput;
private bool handbrakeInput;
private float steeringAxis;
private float throttleAxis;
private float driftingAxis;
private float localVelocityX;
private float localVelocityZ;
private float initialEnginePitch;
private WheelFrictionCurve frontLeftSidewaysFriction;
private WheelFrictionCurve frontRightSidewaysFriction;
private WheelFrictionCurve rearLeftSidewaysFriction;
private WheelFrictionCurve rearRightSidewaysFriction;
private float frontLeftExtremumSlip;
private float frontRightExtremumSlip;
private float rearLeftExtremumSlip;
private float rearRightExtremumSlip;
private Quaternion frontLeftVisualRotationOffset = Quaternion.identity;
private Quaternion frontRightVisualRotationOffset = Quaternion.identity;
private Quaternion rearLeftVisualRotationOffset = Quaternion.identity;
@ -43,25 +83,30 @@ namespace RaceFields.Vehicles
private void Awake()
{
body = GetComponent<Rigidbody>();
body.centerOfMass += centerOfMassOffset;
AutoFindReferences();
CacheVisualRotationOffsets();
CacheWheelFriction();
body.centerOfMass = centerOfMass;
initialEnginePitch = engineSound != null ? engineSound.pitch : 1f;
SetEffectsActive(false);
}
private void Update()
{
ReadInput();
SyncWheelVisual(frontLeftCollider, frontLeftVisual, frontLeftVisualRotationOffset);
SyncWheelVisual(frontRightCollider, frontRightVisual, frontRightVisualRotationOffset);
SyncWheelVisual(rearLeftCollider, rearLeftVisual, rearLeftVisualRotationOffset);
SyncWheelVisual(rearRightCollider, rearRightVisual, rearRightVisualRotationOffset);
UpdateTelemetry();
UpdateWheelVisuals();
UpdateSounds();
}
private void FixedUpdate()
{
ApplySteering();
ApplyMotorAndBrakes();
body.AddForce(-transform.up * downforce * body.linearVelocity.magnitude, ForceMode.Force);
ApplyDrive();
ApplyHandbrake();
ApplyDownforce();
UpdateEffects();
}
private void ReadInput()
@ -74,57 +119,278 @@ namespace RaceFields.Vehicles
float left = Keyboard.current.aKey.isPressed || Keyboard.current.leftArrowKey.isPressed ? 1f : 0f;
float right = Keyboard.current.dKey.isPressed || Keyboard.current.rightArrowKey.isPressed ? 1f : 0f;
throttle = forward - reverse;
steering = right - left;
brake = Keyboard.current.spaceKey.isPressed;
throttleInput = forward - reverse;
steeringInput = right - left;
handbrakeInput = Keyboard.current.spaceKey.isPressed;
return;
}
#endif
throttle = Input.GetAxisRaw("Vertical");
steering = Input.GetAxisRaw("Horizontal");
brake = Input.GetKey(KeyCode.Space);
throttleInput = Input.GetAxisRaw("Vertical");
steeringInput = Input.GetAxisRaw("Horizontal");
handbrakeInput = Input.GetKey(KeyCode.Space);
}
private void UpdateTelemetry()
{
SpeedKmh = body.linearVelocity.magnitude * 3.6f;
Vector3 localVelocity = transform.InverseTransformDirection(body.linearVelocity);
localVelocityX = localVelocity.x;
localVelocityZ = localVelocity.z;
IsDrifting = Mathf.Abs(localVelocityX) > DriftVelocityThreshold;
}
private void ApplySteering()
{
float angle = steering * maxSteerAngle;
if (frontLeftCollider != null) frontLeftCollider.steerAngle = angle;
if (frontRightCollider != null) frontRightCollider.steerAngle = angle;
if (steeringInput < -0.01f)
steeringAxis -= Time.fixedDeltaTime * 10f * steeringSpeed;
else if (steeringInput > 0.01f)
steeringAxis += Time.fixedDeltaTime * 10f * steeringSpeed;
else
steeringAxis = Mathf.MoveTowards(steeringAxis, 0f, Time.fixedDeltaTime * 10f * steeringSpeed);
steeringAxis = Mathf.Clamp(steeringAxis, -1f, 1f);
float steeringAngle = steeringAxis * maxSteerAngle;
SetSteerAngle(frontLeftCollider, steeringAngle, steeringSpeed);
SetSteerAngle(frontRightCollider, steeringAngle, steeringSpeed);
}
private void ApplyMotorAndBrakes()
private void ApplyDrive()
{
float speedKmh = body.linearVelocity.magnitude * 3.6f;
float torque = speedKmh < maxSpeedKmh ? throttle * motorTorque : 0f;
if (throttle < 0f) torque *= reverseTorqueScale;
if (throttleInput > 0.01f)
{
throttleAxis = Mathf.MoveTowards(throttleAxis, 1f, Time.fixedDeltaTime * 3f);
if (localVelocityZ < -1f)
{
ApplyBrakeTorque(brakeForce);
ApplyMotorTorque(0f);
return;
}
ApplyBrakeTorque(0f);
ApplyMotorTorque(SpeedKmh < maxSpeedKmh ? accelerationMultiplier * TorquePerAccelerationStep * throttleAxis : 0f);
return;
}
if (throttleInput < -0.01f)
{
throttleAxis = Mathf.MoveTowards(throttleAxis, -1f, Time.fixedDeltaTime * 3f);
if (localVelocityZ > 1f)
{
ApplyBrakeTorque(brakeForce);
ApplyMotorTorque(0f);
return;
}
ApplyBrakeTorque(0f);
ApplyMotorTorque(SpeedKmh < maxReverseSpeedKmh ? accelerationMultiplier * TorquePerAccelerationStep * throttleAxis : 0f);
return;
}
throttleAxis = Mathf.MoveTowards(throttleAxis, 0f, Time.fixedDeltaTime * 10f);
ApplyMotorTorque(0f);
if (!handbrakeInput)
{
ApplyBrakeTorque(0f);
body.linearVelocity *= 1f / (1f + 0.025f * decelerationMultiplier);
if (body.linearVelocity.magnitude < 0.25f)
body.linearVelocity = Vector3.zero;
}
}
private void ApplyHandbrake()
{
if (handbrakeInput)
{
driftingAxis = Mathf.Clamp01(driftingAxis + Time.fixedDeltaTime);
float startingPoint = driftingAxis * frontLeftExtremumSlip * handbrakeDriftMultiplier;
if (startingPoint < frontLeftExtremumSlip)
driftingAxis = frontLeftExtremumSlip / (frontLeftExtremumSlip * handbrakeDriftMultiplier);
SetDriftFriction(driftingAxis);
IsTractionLocked = true;
ApplyBrakeTorque(brakeForce);
return;
}
IsTractionLocked = false;
driftingAxis = Mathf.MoveTowards(driftingAxis, 0f, Time.fixedDeltaTime / 1.5f);
SetDriftFriction(driftingAxis);
}
private void ApplyDownforce()
{
body.AddForce(-transform.up * downforce * body.linearVelocity.magnitude, ForceMode.Force);
}
private void UpdateSounds()
{
if (!useSounds)
{
StopAudio(engineSound);
StopAudio(tireScreechSound);
return;
}
if (engineSound != null)
{
if (!engineSound.isPlaying)
engineSound.Play();
engineSound.pitch = initialEnginePitch + body.linearVelocity.magnitude / 25f;
}
bool rearWheelsGrounded = IsWheelGrounded(rearLeftCollider) || IsWheelGrounded(rearRightCollider);
bool shouldScreech = rearWheelsGrounded && (IsDrifting || (IsTractionLocked && SpeedKmh > EffectsMinSpeedKmh));
if (tireScreechSound != null)
{
if (shouldScreech && !tireScreechSound.isPlaying)
tireScreechSound.Play();
else if (!shouldScreech && tireScreechSound.isPlaying)
tireScreechSound.Stop();
}
}
private void UpdateEffects()
{
if (!useEffects)
{
SetEffectsActive(false);
return;
}
bool rearLeftGrounded = IsWheelGrounded(rearLeftCollider);
bool rearRightGrounded = IsWheelGrounded(rearRightCollider);
bool emitSmoke = IsDrifting && SpeedKmh > EffectsMinSpeedKmh;
bool emitSkids = (IsTractionLocked || Mathf.Abs(localVelocityX) > SkidVelocityThreshold) && SpeedKmh > EffectsMinSpeedKmh;
SetParticlePlaying(rearLeftSmoke, emitSmoke && rearLeftGrounded);
SetParticlePlaying(rearRightSmoke, emitSmoke && rearRightGrounded);
SetTrailEmitting(rearLeftSkid, emitSkids && rearLeftGrounded);
SetTrailEmitting(rearRightSkid, emitSkids && rearRightGrounded);
}
private void UpdateWheelVisuals()
{
SyncWheelVisual(frontLeftCollider, frontLeftVisual, frontLeftVisualRotationOffset);
SyncWheelVisual(frontRightCollider, frontRightVisual, frontRightVisualRotationOffset);
SyncWheelVisual(rearLeftCollider, rearLeftVisual, rearLeftVisualRotationOffset);
SyncWheelVisual(rearRightCollider, rearRightVisual, rearRightVisualRotationOffset);
}
private void CacheWheelFriction()
{
frontLeftSidewaysFriction = frontLeftCollider != null ? frontLeftCollider.sidewaysFriction : default;
frontRightSidewaysFriction = frontRightCollider != null ? frontRightCollider.sidewaysFriction : default;
rearLeftSidewaysFriction = rearLeftCollider != null ? rearLeftCollider.sidewaysFriction : default;
rearRightSidewaysFriction = rearRightCollider != null ? rearRightCollider.sidewaysFriction : default;
frontLeftExtremumSlip = frontLeftSidewaysFriction.extremumSlip;
frontRightExtremumSlip = frontRightSidewaysFriction.extremumSlip;
rearLeftExtremumSlip = rearLeftSidewaysFriction.extremumSlip;
rearRightExtremumSlip = rearRightSidewaysFriction.extremumSlip;
}
private void SetDriftFriction(float drift)
{
ApplySidewaysFriction(frontLeftCollider, ref frontLeftSidewaysFriction, frontLeftExtremumSlip, drift);
ApplySidewaysFriction(frontRightCollider, ref frontRightSidewaysFriction, frontRightExtremumSlip, drift);
ApplySidewaysFriction(rearLeftCollider, ref rearLeftSidewaysFriction, rearLeftExtremumSlip, drift);
ApplySidewaysFriction(rearRightCollider, ref rearRightSidewaysFriction, rearRightExtremumSlip, drift);
}
private void ApplySidewaysFriction(WheelCollider wheel, ref WheelFrictionCurve friction, float defaultExtremumSlip, float drift)
{
if (wheel == null)
return;
float driftExtremumSlip = defaultExtremumSlip * handbrakeDriftMultiplier;
friction.extremumSlip = Mathf.Lerp(defaultExtremumSlip, driftExtremumSlip, drift);
wheel.sidewaysFriction = friction;
}
private void ApplyMotorTorque(float torque)
{
SetDriveTorque(frontLeftCollider, torque);
SetDriveTorque(frontRightCollider, torque);
SetDriveTorque(rearLeftCollider, torque);
SetDriveTorque(rearRightCollider, torque);
}
float currentBrakeTorque = brake ? brakeTorque : 0f;
SetBrakeTorque(frontLeftCollider, currentBrakeTorque);
SetBrakeTorque(frontRightCollider, currentBrakeTorque);
SetBrakeTorque(rearLeftCollider, currentBrakeTorque);
SetBrakeTorque(rearRightCollider, currentBrakeTorque);
private void ApplyBrakeTorque(float torque)
{
SetBrakeTorque(frontLeftCollider, torque);
SetBrakeTorque(frontRightCollider, torque);
SetBrakeTorque(rearLeftCollider, torque);
SetBrakeTorque(rearRightCollider, torque);
}
private static void SetSteerAngle(WheelCollider wheel, float angle, float lerp)
{
if (wheel != null)
wheel.steerAngle = Mathf.Lerp(wheel.steerAngle, angle, lerp);
}
private static void SetDriveTorque(WheelCollider wheel, float torque)
{
if (wheel != null) wheel.motorTorque = torque;
if (wheel != null)
wheel.motorTorque = torque;
}
private static void SetBrakeTorque(WheelCollider wheel, float torque)
{
if (wheel != null) wheel.brakeTorque = torque;
if (wheel != null)
wheel.brakeTorque = torque;
}
private static void SyncWheelVisual(WheelCollider collider, Transform visual, Quaternion visualRotationOffset)
{
if (collider == null || visual == null) return;
if (collider == null || visual == null)
return;
collider.GetWorldPose(out Vector3 position, out Quaternion rotation);
visual.SetPositionAndRotation(position, rotation * visualRotationOffset);
}
private void SetEffectsActive(bool active)
{
SetParticlePlaying(rearLeftSmoke, active);
SetParticlePlaying(rearRightSmoke, active);
SetTrailEmitting(rearLeftSkid, active);
SetTrailEmitting(rearRightSkid, active);
}
private static void SetParticlePlaying(ParticleSystem particles, bool playing)
{
if (particles == null)
return;
if (playing && !particles.isPlaying)
particles.Play();
else if (!playing && particles.isPlaying)
particles.Stop();
}
private static void SetTrailEmitting(TrailRenderer trail, bool emitting)
{
if (trail != null)
trail.emitting = emitting;
}
private static bool IsWheelGrounded(WheelCollider wheel)
{
return wheel != null && wheel.isGrounded;
}
private static void StopAudio(AudioSource source)
{
if (source != null && source.isPlaying)
source.Stop();
}
private void AutoFindReferences()
{
frontLeftCollider ??= FindChildComponent<WheelCollider>("WheelCollider_FL");
@ -136,6 +402,11 @@ namespace RaceFields.Vehicles
frontRightVisual ??= FindFirstChildTransform("F_R", "WheelVisual_FR");
rearLeftVisual ??= FindFirstChildTransform("B_L", "WheelVisual_RL");
rearRightVisual ??= FindFirstChildTransform("B_R", "WheelVisual_RR");
rearLeftSmoke ??= FindChildComponent<ParticleSystem>("LeftTireSmoke_PS");
rearRightSmoke ??= FindChildComponent<ParticleSystem>("RightTireSmoke_PS");
rearLeftSkid ??= FindChildComponent<TrailRenderer>("LeftTireSkid");
rearRightSkid ??= FindChildComponent<TrailRenderer>("RightTireSkid");
}
private void CacheVisualRotationOffsets()