H_SafeExperienceDrivingSystem/U3D_DrivingSystem/Assets/EVP5/Scripts/VehicleTireEffects.cs

204 lines
5.3 KiB
C#

//------------------------------------------------------------------------------------------------
// Edy's Vehicle Physics
// (c) Angel Garcia "Edy" - Oviedo, Spain
// http://www.edy.es
//------------------------------------------------------------------------------------------------
using UnityEngine;
namespace EVP
{
// Data stored per wheel for tire effects
public class TireFxData
{
// Tire marks
public TireMarksRenderer lastRenderer;
public int lastMarksIndex = -1;
public float marksDelta = 0.0f;
// Tire particles
public TireParticleEmitter lastEmitter;
public float lastParticleTime = -1.0f;
public float slipTime = 0.0f;
}
[RequireComponent(typeof(VehicleController))]
public class VehicleTireEffects : MonoBehaviour
{
public float tireWidth = 0.2f;
public float minSlip = 1.0f;
public float maxSlip = 5.0f;
[Header("Tire marks")]
[Range(0,2)]
public float intensity = 1.0f;
public float updateInterval = 0.02f;
[Header("Smoke")]
public float minIntensityTime = 0.5f;
public float maxIntensityTime = 6.0f;
public float limitIntensityTime = 10.0f;
VehicleController m_vehicle;
TireFxData[] m_fxData = new TireFxData[0];
void OnEnable ()
{
m_vehicle = GetComponent<VehicleController>();
m_vehicle.computeExtendedTireData = true;
}
void Update ()
{
if (m_vehicle.paused) return;
if (m_vehicle.wheelData.Length != m_fxData.Length)
InitializeTireFxData();
for (int i=0, c=m_fxData.Length; i<c; i++)
{
WheelData wd = m_vehicle.wheelData[i];
TireFxData md = m_fxData[i];
UpdateTireMarks(wd, md);
UpdateTireParticles(wd, md);
}
}
//--------------------------------------------------------------------------------------------
void InitializeTireFxData ()
{
m_fxData = new TireFxData[m_vehicle.wheelData.Length];
for (int i=0; i<m_fxData.Length; i++)
m_fxData[i] = new TireFxData();
}
void UpdateTireMarks (WheelData wheelData, TireFxData fxData)
{
// If we are already drawing marks to this wheel, wait before updating.
if (fxData.lastMarksIndex != -1 && wheelData.grounded && fxData.marksDelta < updateInterval)
{
fxData.marksDelta += Time.deltaTime;
return;
}
// deltaT = time since last mark for this wheel
float deltaT = fxData.marksDelta;
if (deltaT == 0.0f)
deltaT = Time.deltaTime;
fxData.marksDelta = 0.0f;
// Verify: Should we put marks?
// - Grounded
// - Contacted object has not a rigidbody (assumed to be static)
if (!wheelData.grounded || wheelData.hit.collider.attachedRigidbody != null)
{
fxData.lastMarksIndex = -1;
return;
}
// Have we changed renderer? If so, start a new tread
TireMarksRenderer marksRenderer =
wheelData.groundMaterial != null? wheelData.groundMaterial.marksRenderer : null;
if (marksRenderer != fxData.lastRenderer)
{
fxData.lastRenderer = marksRenderer;
fxData.lastMarksIndex = -1;
}
if (marksRenderer != null)
{
float pressureRatio = Mathf.Clamp01(intensity * wheelData.downforceRatio * 0.5f);
float skidRatio = Mathf.InverseLerp(minSlip, maxSlip, wheelData.combinedTireSlip);
fxData.lastMarksIndex = marksRenderer.AddMark(
wheelData.rayHit.point - wheelData.transform.right * wheelData.collider.center.x + wheelData.velocity * deltaT,
wheelData.rayHit.normal,
pressureRatio,
skidRatio,
tireWidth,
fxData.lastMarksIndex
);
}
}
void UpdateTireParticles (WheelData wheelData, TireFxData fxData)
{
if (!wheelData.grounded)
{
// Not grounded: clear particle state and decrement the particle slip time
fxData.lastParticleTime = -1.0f;
fxData.slipTime -= Time.deltaTime;
if (fxData.slipTime < 0.0f) fxData.slipTime = 0.0f;
return;
}
TireParticleEmitter particleEmitter =
wheelData.groundMaterial != null? wheelData.groundMaterial.particleEmitter : null;
if (particleEmitter != fxData.lastEmitter)
{
fxData.lastEmitter = particleEmitter;
fxData.lastParticleTime = -1.0f;
}
if (particleEmitter != null)
{
Vector3 position = wheelData.rayHit.point + wheelData.transform.up * tireWidth * 0.5f;
Vector3 positionRandom = Random.insideUnitSphere * tireWidth;
float pressureRatio = Mathf.Clamp01(wheelData.downforceRatio);
float skidRatio = Mathf.InverseLerp(minSlip, maxSlip, wheelData.combinedTireSlip);
// Emulate tire "heating" as for the time it has been skidding over the minSlip value.
// Tire will "heat" at full rate when completely skidding at full pressure.
if (skidRatio > 0.0f && particleEmitter.mode == TireParticleEmitter.Mode.PressureAndSkid)
fxData.slipTime += Time.deltaTime * skidRatio * pressureRatio;
else
fxData.slipTime -= Time.deltaTime;
fxData.slipTime = Mathf.Clamp(fxData.slipTime, 0.0f, limitIntensityTime);
float slipTimeRatio = Mathf.InverseLerp(minIntensityTime, maxIntensityTime, fxData.slipTime);
fxData.lastParticleTime = particleEmitter.EmitParticle(
position + positionRandom,
wheelData.velocity,
wheelData.tireSlip.y * wheelData.transform.forward,
pressureRatio,
skidRatio * slipTimeRatio,
fxData.lastParticleTime
);
}
else
{
// No particles set up for this material. Assume is not a "heating material"
// and "cold down" the tire surface.
fxData.slipTime -= Time.deltaTime;
if (fxData.slipTime < 0.0f) fxData.slipTime = 0.0f;
}
}
}
}