public VehicleWheel( WheelCollider vehicleWheel, WheelComponent wheelComponent, WheelPosition frontRear, WheelPosition leftRight ) { wheelFrontRear = frontRear; wheelLeftRight = leftRight; checkCurrentWheelState = WheelsOnGround.WHEEL_ON_GROUND; mainWheelCollider = vehicleWheel; wheelPhysicsComponent = wheelComponent; visualWheel = vehicleWheel.GetComponentInChildren<MeshRenderer>( ).transform; wheelRadius = ( visualWheel.GetComponent<Renderer>().bounds.size.y / 2 ); mainWheelCollider.radius = wheelRadius; mainWheelCollider.GetGroundHit( out wheelGroundContactPoint ); }
public bool Initialize(WheelComponent wheelComponent, GameObject skidmarkContainer, float minDistance, int surfaceMapCount, int maxMarks, bool persistent, float persistentDistance, float groundOffset, float smoothing, float lowerIntensityThreshold, bool fadeOverDistance, Material fallbackMaterial) { _targetWheelComponent = wheelComponent; _minSqrDistance = minDistance * minDistance; _maxMarks = maxMarks; _surfaceMapCount = surfaceMapCount; _persistent = persistent; _persistentDistance = persistentDistance; _fadeOverDistance = !persistent && fadeOverDistance; _groundOffset = groundOffset; _smoothing = smoothing; _lowerIntensityThreshold = lowerIntensityThreshold; _skidmarkContainer = skidmarkContainer; _fallbackMaterial = fallbackMaterial; _maxTris = maxMarks * 6; _outTriArray = new int[_maxTris]; _markWidth = wheelComponent.Width; _isInitial = true; _prevSurfaceMapIndex = _surfaceMapIndex; GenerateNewSection(); return(true); }
public void CalculateCamber() { if (isSolid && Wheels.Count == 2) // Calculate and set solid axle camber { WheelComponent leftWheel = Wheels[0]; WheelComponent rightWheel = Wheels[1]; // Center point of imaginary axle _position = (leftWheel.wheelController.springTravelPoint + rightWheel.wheelController.springTravelPoint) / 2f; _direction = _position - leftWheel.wheelController.springTravelPoint; // Calculate camber from the mid point float camberAngle = Vector3.SignedAngle(_vc.transform.right, _direction, _vc.transform.forward); camberAngle = Mathf.Clamp(camberAngle, -25f, 25f); // Set camber leftWheel.wheelController.SetCamber(camberAngle); rightWheel.wheelController.SetCamber(-camberAngle); camberAtBottom = camberAtTop = camberAngle; } else // Set normal camber { foreach (WheelComponent wheel in Wheels) { wheel.wheelController.SetCamber(camberAtTop, camberAtBottom); } } }
private WheelComponent SetWheelComponent(Transform wheel, Transform axle, bool drive, float maxSteer, float pos_y) { WheelComponent result = new WheelComponent(); GameObject wheelCol = new GameObject(wheel.name + "WheelCollider"); wheelCol.transform.parent = transform; wheelCol.transform.position = wheel.position; wheelCol.transform.eulerAngles = transform.eulerAngles; pos_y = wheelCol.transform.localPosition.y; wheelCol.AddComponent(typeof(WheelCollider)); result.drive = drive; result.wheel = wheel; result.axle = axle; result.collider = wheelCol.GetComponent <WheelCollider>(); result.pos_y = pos_y; result.maxSteer = maxSteer; result.startPos = axle.transform.localPosition; return(result); }
public override bool OnNUI(Rect rect, SerializedProperty property, GUIContent label) { List <string> options = new List <string> { "[no axle]" }; // Try to get vehicle controller from parent property vc = property.serializedObject.targetObject as VehicleController; if (vc == null) { selectedIndex = EditorGUI.Popup(rect, "Belongs to", 0, options.ToArray()); return(false); } // Find the name and index of currently selected output groupIndexProperty = property.FindPropertyRelative("index"); if (groupIndexProperty == null) { Debug.LogWarning("Property axleIndex not found."); return(false); } int axleIndex = groupIndexProperty.intValue; int selectorIndex = axleIndex + 1; string name = axleIndex >= vc.powertrain.wheelGroups.Count || axleIndex < 0 ? "" : vc.powertrain.wheelGroups[axleIndex].name; // Add the names of other powertrain components for (int i = 0; i < vc.powertrain.wheelGroups.Count; i++) { options.Add($"{vc.powertrain.wheelGroups[i].name} [Group {i.ToString()}]"); } // Display dropdown menu selectedIndex = EditorGUI.Popup(new Rect(rect.x, rect.y, rect.width, NUISettings.FIELD_HEIGHT), "Belongs to", selectorIndex, options.ToArray()); // Display currently selected output groupIndexProperty.intValue = selectedIndex - 1; if (selectedIndex > 0 && selectedIndex <= vc.powertrain.wheelGroups.Count) { WheelComponent wheelComponent = SerializedPropertyHelper.GetTargetObjectWithProperty(property) as WheelComponent; if (wheelComponent != null) { wheelComponent.wheelGroup = vc.powertrain.wheelGroups[selectedIndex - 1]; } else { Debug.LogWarning("WheelComponent property not found. Wheel group will not be set."); } } return(true); }
public void CalculateARB() { if (Wheels.Count != 2) { return; } WheelComponent leftWheel = Wheels[0]; WheelComponent rightWheel = Wheels[1]; // Apply anti roll bar if (antiRollBarForce > 0) { float leftTravel = leftWheel.SpringTravel; float rightTravel = rightWheel.SpringTravel; // Cylindrical steel shaft of which ARBs are usually made have ~linear torque vs. angle of twist characteristic // for the low twist angle values. float springLengthDiff = leftWheel.wheelController.spring.length - rightWheel.wheelController.spring.length; _arbForce = springLengthDiff * antiRollBarForce; if (leftWheel.IsGrounded || rightWheel.IsGrounded) { // Apply the ARB force at the shock anchor point. _vc.vehicleRigidbody.AddForceAtPosition(leftWheel.ControllerTransform.up * -_arbForce, leftWheel.ControllerTransform.position); _vc.vehicleRigidbody.AddForceAtPosition(rightWheel.ControllerTransform.up * _arbForce, rightWheel.ControllerTransform.position); } } }
public void Initialize(VehicleController vc, WheelComponent wheelComponent) { _vc = vc; _wheelComponent = wheelComponent; if (!vc.groundDetection.IsEnabled || vc.groundDetection.groundDetectionPreset == null) { return; } // Initialize particles if (vc.groundDetection.groundDetectionPreset.particlePrefab != null) { particlePrefab = Object.Instantiate( vc.groundDetection.groundDetectionPreset.particlePrefab, wheelComponent.ControllerTransform, true); particlePrefab.transform.position = wheelComponent.wheelController.wheel.worldPosition - wheelComponent.wheelController.cachedTransform.up * (wheelComponent.wheelController.radius * 0.5f); particlePS = particlePrefab.GetComponent <ParticleSystem>(); particlePS.name = "SurfaceParticles"; ParticleSystem.ShapeModule shape = particlePS.shape; shape.radius = wheelComponent.Width * 1.5f; _shapeModule = particlePS.shape; _shapeModule.radius = wheelComponent.Width; } else { Debug.LogWarning("Smoke Prefab is null, wheel slip will not produce particles."); } // Initialize chunks if (vc.groundDetection.groundDetectionPreset.chunkPrefab != null) { chunkPrefab = Object.Instantiate( vc.groundDetection.groundDetectionPreset.chunkPrefab, wheelComponent.ControllerTransform, true); chunkPrefab.transform.position = wheelComponent.wheelController.wheel.worldPosition - wheelComponent.wheelController.cachedTransform.up * wheelComponent.wheelController.radius - wheelComponent.wheelController.cachedTransform.forward * (wheelComponent.wheelController.radius * 0.7f); chunkPS = chunkPrefab.GetComponent <ParticleSystem>(); chunkPS.name = "SurfaceChunks"; _shapeModule = chunkPS.shape; _shapeModule.radius = wheelComponent.Width; } else { Debug.LogWarning("Dust Prefab is null, there will be no surface dust."); } _initialized = true; }
private void Start ( ) { vehicleWheels = new WheelCollider[ ]{ frontRightWheel, frontLeftWheel, rearRightWheel, rearLeftWheel }; gearsComponent = new GearsComponent( 6, 180 ); wheelComponent = new WheelComponent( gameObject ); engineComponent = gameObject.AddComponent<EngineComponent>( ); engineComponent.Start( ); UnityWheelBugFix( ); }
public override void Initialize() { _wheelCount = vc.Wheels.Count; for (int index = 0; index < _wheelCount; index++) { WheelComponent wheel = vc.Wheels[index]; AudioSource a = wheel.ControllerGO.AddComponent <AudioSource>(); vc.soundManager.SetAudioSourceDefaults(a, true, true); Sources.Add(a); } AddSourcesToMixer(); _prevVolume = new float[_wheelCount]; _prevPitch = new float[_wheelCount]; initialized = true; }
public override bool OnNUI(Rect position, SerializedProperty property, GUIContent label) { if (!base.OnNUI(position, property, label)) { return(false); } drawer.Field("groundDetectionPreset"); GroundDetectionPreset gdPreset = ((GroundDetection)(SerializedPropertyHelper.GetTargetObjectOfProperty(property) as VehicleComponent))?.groundDetectionPreset; if (gdPreset != null) { drawer.EmbeddedObjectEditor(gdPreset, drawer.positionRect); } drawer.BeginSubsection("Debug Info"); GroundDetection groundDetection = SerializedPropertyHelper.GetTargetObjectOfProperty(drawer.serializedProperty) as GroundDetection; if (groundDetection != null && groundDetection.VehicleController != null) { for (int i = 0; i < groundDetection.VehicleController.powertrain.wheels.Count; i++) { WheelComponent wheelComponent = groundDetection.VehicleController.powertrain.wheels[i]; if (wheelComponent != null) { drawer.Label($"{wheelComponent.name}: {wheelComponent.surfacePreset?.name} SurfacePreset"); } } } else { drawer.Info("Debug info is available only in play mode."); } drawer.EndSubsection(); drawer.EndProperty(); return(true); }
private WheelComponent SetWheelComponent(Transform wheel, Transform axle, bool drive, float maxSteer, float pos_y) { WheelComponent result = new WheelComponent(); GameObject wheelCol = new GameObject(wheel.name + "WheelCollider"); wheelCol.transform.parent = transform; wheelCol.transform.position = wheel.position; wheelCol.transform.eulerAngles = transform.eulerAngles; pos_y = wheelCol.transform.localPosition.y; wheelCol.AddComponent(typeof(WheelCollider)); result.drive = drive; result.wheel = wheel; result.axle = axle; result.collider = wheelCol.GetComponent <WheelCollider>(); result.collider.radius = bikeWheels.setting.Radius; result.collider.center = bikeWheels.setting.WheelCenter; result.pos_y = pos_y; result.maxSteer = maxSteer; result.startPos = axle.transform.localPosition; if (!drive) { // var spring = new JointSpring(); // spring.spring = 35000; // spring.damper = 3500; // spring.targetPosition = 0.7f; // result.collider.suspensionSpring = spring; } // Physics.IgnoreCollision(result.collider, body); // Physics.IgnoreCollision(result.collider, body); return(result); }
private WheelComponent SetWheelComponent(Transform wheel, Transform axle, bool drive, float maxSteer, float pos_y) { WheelComponent result = new WheelComponent(); GameObject wheelCol = new GameObject(wheel.name + "WheelCollider"); wheelCol.transform.parent = transform; wheelCol.transform.position = wheel.position; wheelCol.transform.eulerAngles = transform.eulerAngles; pos_y = wheelCol.transform.localPosition.y; wheel.gameObject.AddComponent <WheelCollider>(); WheelCollider col = (WheelCollider)wheelCol.AddComponent(typeof(WheelCollider)); //TODO: rewrite if we got some problem with wheels size //col.transform.localScale = wheel.localScale; float cof; if (wheel.parent.localScale.x == 1f) { cof = wheel.localScale.x; } else { cof = wheel.parent.localScale.x; } col.radius = wheel.GetComponent <WheelCollider>().radius *cof; Destroy(wheel.transform.GetComponent <WheelCollider>()); result.drive = drive; result.wheel = wheel; result.axle = axle; result.collider = wheelCol.GetComponent <WheelCollider>(); result.pos_y = pos_y; result.maxSteer = maxSteer; result.startPos = wheelCol.transform.localPosition; return(result); }
public float BrakeTorqueModifier() { if (!Active) { return(1f); } active = false; slipThreshold = slipThreshold < 0 ? 0 : slipThreshold > 1 ? 1 : slipThreshold; // Prevent ABS from working in reverse and at low speeds if (vc.ForwardVelocity < lowerSpeedThreshold) { return(1f); } if (vc.brakes.Active && !vc.powertrain.engine.revLimiterActive && vc.input.Handbrake < 0.1f) { for (int index = 0; index < vc.Wheels.Count; index++) { WheelComponent wheel = vc.Wheels[index]; if (!wheel.IsGrounded) { continue; } float longSlip = wheel.LongitudinalSlip; if (longSlip > 0 && longSlip > slipThreshold) { active = true; ABSActive.Invoke(); return(0.01f); } } } return(1f); }
void Start() { wheelComponent = SetWheelComponent(wheel, axle, true, 0, axle.localPosition.y); }
private WheelComponent SetWheelComponent(Transform wheel, Transform axle, bool drive, float maxSteer, float pos_y) { WheelComponent result = new WheelComponent(); GameObject wheelCol = new GameObject(wheel.name + "WheelCollider"); wheelCol.transform.parent = transform; wheelCol.transform.position = wheel.position; wheelCol.transform.eulerAngles = transform.eulerAngles; pos_y = wheelCol.transform.localPosition.y; wheel.gameObject.AddComponent<WheelCollider>(); WheelCollider col = (WheelCollider)wheelCol.AddComponent(typeof(WheelCollider)); //TODO: rewrite if we got some problem with wheels size //col.transform.localScale = wheel.localScale; float cof; if(wheel.parent.localScale.x == 1f) cof = wheel.localScale.x; else cof = wheel.parent.localScale.x; col.radius = wheel.GetComponent<WheelCollider>().radius * cof; Destroy(wheel.transform.GetComponent<WheelCollider>()); result.drive = drive; result.wheel = wheel; result.axle = axle; result.collider = wheelCol.GetComponent<WheelCollider>(); result.pos_y = pos_y; result.maxSteer = maxSteer; result.startPos = wheelCol.transform.localPosition; return result; }
public override void Update() { if (!Active) { return; } for (int i = 0; i < _wheelCount; i++) { WheelComponent wheelComponent = vc.Wheels[i]; SurfacePreset surfacePreset = wheelComponent.surfacePreset; float newVolume = 0; float newPitch = basePitch; if (wheelComponent.IsGrounded && surfacePreset != null && surfacePreset.playSurfaceSounds) { if (surfacePreset.surfaceSoundClip != null) { AudioSource source = Sources[i]; if (!source.isPlaying) { source.Play(); } if (source.clip != surfacePreset.surfaceSoundClip) { // Change skid clip source.clip = surfacePreset.surfaceSoundClip; source.time = Random.Range(0f, surfacePreset.surfaceSoundClip.length); source.time = Random.Range(0f, source.clip.length); } float surfaceModifier = 1f; if (surfacePreset.slipSensitiveSurfaceSound) { surfaceModifier = wheelComponent.NormalizedLateralSlip / vc.longitudinalSlipThreshold; surfaceModifier = surfaceModifier < 0 ? 0 : surfaceModifier > 1 ? 1 : surfaceModifier; } float speedCoeff = vc.Speed / 20f; speedCoeff = speedCoeff < 0 ? 0 : speedCoeff > 1 ? 1 : speedCoeff; // Change surface volume and pitch newVolume = surfacePreset.surfaceSoundVolume * surfaceModifier * speedCoeff; newVolume = newVolume < 0 ? 0 : newVolume > 1 ? 1 : newVolume; newVolume = Mathf.Lerp(_prevVolume[i], newVolume, vc.deltaTime * 12f); newPitch = surfacePreset.surfaceSoundPitch * 0.5f + speedCoeff; } } else { newVolume = Mathf.Lerp(_prevVolume[i], 0, vc.deltaTime * 12f); newPitch = Mathf.Lerp(_prevPitch[i], basePitch, vc.deltaTime * 12f); } SetVolume(newVolume, i); SetPitch(newPitch, i); _prevVolume[i] = newVolume; _prevPitch[i] = newPitch; } }
public void Start ( ) { vehiclePhysics = GetComponent<VehiclePhysics>( ); wheelComponent = vehiclePhysics.wheelComponent; }
public override void Update() { if (!Active) { return; } // Check if can be updated if (vc.groundDetection == null || !vc.groundDetection.IsEnabled) { return; } // Check for added/removed wheels and re-init if needed int wheelCount = vc.powertrain.wheels.Count; if (prevWheelCount != wheelCount) { initialized = false; Initialize(); } prevWheelCount = wheelCount; // Update skidmarks Debug.Assert(skidmarkGenerators.Count == vc.powertrain.wheels.Count, "Skidmark generator count must equal wheel count"); int n = skidmarkGenerators.Count; for (int i = 0; i < n; i++) { WheelComponent wheelComponent = vc.powertrain.wheels[i]; SurfacePreset surfacePreset = wheelComponent.surfacePreset; if (surfacePreset == null || !surfacePreset.drawSkidmarks) { continue; } bool surfaceMapIsNull = surfacePreset == null; int surfaceMapIndex = -1; if (!surfaceMapIsNull) { surfaceMapIndex = wheelComponent.surfaceMapIndex; } float intensity = 1f; if (surfaceMapIndex >= 0) { float latFactor = wheelComponent.NormalizedLateralSlip; latFactor = latFactor < vc.lateralSlipThreshold ? 0 : latFactor - vc.lateralSlipThreshold; float lonFactor = wheelComponent.NormalizedLongitudinalSlip; lonFactor = lonFactor < vc.lateralSlipThreshold ? 0 : lonFactor - vc.lateralSlipThreshold; float slipIntensity = latFactor + lonFactor; float weightCoeff = wheelComponent.wheelController.wheel.load * 2f / wheelComponent.wheelController.maximumTireLoad; weightCoeff = weightCoeff <0 ? 0f : weightCoeff> 1f ? 1f : weightCoeff; slipIntensity *= wheelComponent.surfacePreset.slipFactor * weightCoeff; intensity = wheelComponent.surfacePreset.skidmarkBaseIntensity + slipIntensity; intensity = intensity > 1f ? 1f : intensity < 0f ? 0f : intensity; } intensity *= globalSkidmarkIntensity; intensity = intensity <0f ? 0f : intensity> maxSkidmarkAlpha ? maxSkidmarkAlpha : intensity; float albedoIntensity = 0f; float normalIntensity = 0f; // TODO - check that fallback surface preset is not null skidmarkGenerators[i].Update(surfaceMapIndex, intensity, albedoIntensity, normalIntensity, wheelComponent.wheelController.pointVelocity, vc.fixedDeltaTime); } }
public void AddWheel(WheelComponent wheel) { Wheels.Add(wheel); wheel.wheelGroup = this; }
public override void Update() { if (!Active) { return; } float newVolume = 0; float newPitch = basePitch; if (vc.groundDetection != null) { for (int i = 0; i < _wheelCount; i++) { WheelComponent wheelComponent = vc.Wheels[i]; SurfacePreset surfacePreset = wheelComponent.surfacePreset; bool hasSlip = wheelComponent.HasLateralSlip || wheelComponent.HasLongitudinalSlip; if (wheelComponent.IsGrounded && surfacePreset != null && surfacePreset.playSkidSounds && hasSlip) { float slipPercent = wheelComponent.NormalizedLateralSlip + wheelComponent.NormalizedLongitudinalSlip; slipPercent = slipPercent < 0 ? 0 : slipPercent > 1 ? 1 : slipPercent; if (surfacePreset.skidSoundClip != null) { AudioSource source = Sources[i]; if (!source.isPlaying) { source.Play(); } if (source.clip != surfacePreset.skidSoundClip) { // Change skid clip source.clip = surfacePreset.skidSoundClip; source.time = Random.Range(0f, surfacePreset.skidSoundClip.length); source.time = Random.Range(0f, source.clip.length); } float absAngVel = wheelComponent.angularVelocity < 0 ? -wheelComponent.angularVelocity : wheelComponent.angularVelocity; float speedCoeff = vc.Speed / 3f + absAngVel / 20f; speedCoeff = speedCoeff > 1f ? 1f : speedCoeff; newVolume = slipPercent * surfacePreset.skidSoundVolume * speedCoeff; newVolume = Mathf.Lerp(_prevVolume[i], newVolume, vc.deltaTime * 12f); float loadCoeff = wheelComponent.wheelController.wheel.load / wheelComponent.wheelController.maximumTireLoad; loadCoeff = loadCoeff > 1f ? 1f : loadCoeff; newPitch = surfacePreset.skidSoundPitch + loadCoeff * 0.3f; newPitch = Mathf.Lerp(_prevPitch[i], newPitch, vc.deltaTime * 18f); } } else { newVolume = 0; newPitch = basePitch; } SetVolume(newVolume, i); SetPitch(newPitch, i); _prevVolume[i] = newVolume; _prevPitch[i] = newPitch; } } }
public void RemoveWheel(WheelComponent wheel) { Wheels.Remove(wheel); }