mirror of
https://github.com/GTA-ASM/SanAndreasUnity
synced 2024-11-23 20:43:04 +00:00
193 lines
No EOL
6.7 KiB
C#
193 lines
No EOL
6.7 KiB
C#
using SanAndreasUnity.Importing.Vehicles;
|
|
using SanAndreasUnity.Utilities;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using VConsts = SanAndreasUnity.Behaviours.Vehicles.VehiclePhysicsConstants;
|
|
|
|
namespace SanAndreasUnity.Behaviours.Vehicles
|
|
{
|
|
[RequireComponent(typeof(Rigidbody))]
|
|
public partial class Vehicle
|
|
{
|
|
private Rigidbody _rigidBody;
|
|
public Rigidbody RigidBody => _rigidBody;
|
|
|
|
[Range(-1, 1)]
|
|
public float Accelerator;
|
|
|
|
[Range(-1, 1)]
|
|
public float Steering;
|
|
|
|
[Range(0, 1)]
|
|
public float Braking = 1f;
|
|
|
|
public Vector3 Velocity { get { return _rigidBody.velocity; } }
|
|
|
|
public float AverageWheelHeight { get { return _wheels.Count == 0 ? transform.position.y : _wheels.Average(x => x.Child.position.y); } }
|
|
|
|
public Handling.Car HandlingData { get; private set; }
|
|
|
|
private void InitializePhysics()
|
|
{
|
|
_geometryParts.AttachCollisionModel(transform, true);
|
|
|
|
_rigidBody = gameObject.GetComponent<Rigidbody>();
|
|
|
|
_rigidBody.interpolation = Net.NetStatus.IsServer ? VehicleManager.Instance.rigidbodyInterpolationOnServer : VehicleManager.Instance.rigidbodyInterpolationOnClient;
|
|
_rigidBody.collisionDetectionMode = VehicleManager.Instance.rigidBodyCollisionDetectionMode;
|
|
|
|
if (Net.NetStatus.IsClientOnly)
|
|
{
|
|
_rigidBody.useGravity = false;
|
|
_rigidBody.detectCollisions = false;
|
|
}
|
|
|
|
HandlingData = Handling.Get<Handling.Car>(Definition.HandlingName);
|
|
|
|
VConsts.Changed += UpdateValues;
|
|
|
|
var vals = VConsts.Instance;
|
|
|
|
foreach (var wheel in _wheels)
|
|
{
|
|
var front = (wheel.Alignment & WheelAlignment.Front) == WheelAlignment.Front;
|
|
|
|
wheel.Parent.position -= Vector3.up * HandlingData.SuspensionLowerLimit;
|
|
|
|
var scale = front ? Definition.WheelScaleFront : Definition.WheelScaleRear;
|
|
|
|
var mf = wheel.Child.GetComponent<MeshFilter>();
|
|
if (mf != null)
|
|
{
|
|
var size = mf.sharedMesh.bounds.size.y;
|
|
wheel.Child.localScale = Vector3.one * scale / size;
|
|
}
|
|
|
|
wheel.Collider = wheel.Parent.gameObject.AddComponent<WheelCollider>();
|
|
wheel.Collider.radius = scale * .5f;
|
|
wheel.Collider.suspensionDistance = HandlingData.SuspensionUpperLimit - HandlingData.SuspensionLowerLimit;
|
|
}
|
|
|
|
UpdateValues(vals);
|
|
}
|
|
|
|
private void UpdateValues(VConsts vals)
|
|
{
|
|
_rigidBody.drag = HandlingData.Drag * vals.DragScale;
|
|
_rigidBody.mass = HandlingData.Mass * vals.MassScale;
|
|
_rigidBody.centerOfMass = HandlingData.CentreOfMass;
|
|
|
|
foreach (var wheel in _wheels)
|
|
{
|
|
var spring = wheel.Collider.suspensionSpring;
|
|
|
|
spring.damper = HandlingData.SuspensionDampingLevel * vals.SuspensionDampingScale;
|
|
spring.spring = HandlingData.SuspensionForceLevel * vals.SuspensionForceScale;
|
|
spring.targetPosition = 0.5f;
|
|
|
|
wheel.Collider.suspensionSpring = spring;
|
|
|
|
var friction = wheel.Collider.sidewaysFriction;
|
|
friction.extremumSlip = vals.SideFrictionExtremumSlip;
|
|
friction.extremumValue = vals.SideFrictionExtremumValue;
|
|
friction.asymptoteSlip = vals.SideFrictionAsymptoteSlip;
|
|
friction.asymptoteValue = vals.SideFrictionAsymptoteValue;
|
|
friction.stiffness = 1f;
|
|
wheel.Collider.sidewaysFriction = friction;
|
|
|
|
friction = wheel.Collider.forwardFriction;
|
|
friction.extremumSlip = vals.ForwardFrictionExtremumSlip;
|
|
friction.extremumValue = vals.ForwardFrictionExtremumValue;
|
|
friction.asymptoteSlip = vals.ForwardFrictionAsymptoteSlip;
|
|
friction.asymptoteValue = vals.ForwardFrictionAsymptoteValue;
|
|
friction.stiffness = 1f;
|
|
wheel.Collider.forwardFriction = friction;
|
|
}
|
|
}
|
|
|
|
private float DriveBias(Wheel wheel)
|
|
{
|
|
switch (HandlingData.TransmissionDriveType)
|
|
{
|
|
case DriveType.Forward:
|
|
return wheel.IsFront ? 1f : 0f;
|
|
|
|
case DriveType.Rear:
|
|
return wheel.IsRear ? 1f : 0f;
|
|
|
|
default:
|
|
return 1f;
|
|
}
|
|
}
|
|
|
|
private bool ShouldSteer(Wheel wheel)
|
|
{
|
|
// TODO: look at flags
|
|
return wheel.IsFront;
|
|
}
|
|
|
|
private float BrakeBias(Wheel wheel)
|
|
{
|
|
return wheel.IsFront
|
|
? 1f - HandlingData.BrakeBias : wheel.IsRear
|
|
? HandlingData.BrakeBias : .5f;
|
|
}
|
|
|
|
private void PhysicsFixedUpdate()
|
|
{
|
|
if (m_isServer || (this.IsControlledByLocalPlayer && VehicleManager.Instance.controlWheelsOnLocalPlayer))
|
|
{
|
|
this.UpdateWheelsPhysics();
|
|
}
|
|
|
|
if (m_isServer)
|
|
{
|
|
this.AddAntiRollForceToRigidBody();
|
|
}
|
|
|
|
}
|
|
|
|
void UpdateWheelsPhysics()
|
|
{
|
|
var vals = VConsts.Instance;
|
|
|
|
foreach (var wheel in _wheels)
|
|
{
|
|
// apply steering
|
|
if (ShouldSteer(wheel))
|
|
{
|
|
wheel.Collider.steerAngle = HandlingData.SteeringLock * Steering;
|
|
}
|
|
|
|
// apply motor torque
|
|
wheel.Collider.motorTorque =
|
|
Accelerator * HandlingData.TransmissionEngineAccel
|
|
* vals.AccelerationScale * DriveBias(wheel);
|
|
|
|
// apply brake torque
|
|
wheel.Collider.brakeTorque =
|
|
Braking * HandlingData.BrakeDecel
|
|
* vals.BreakingScale * BrakeBias(wheel);
|
|
|
|
// update travel
|
|
if (wheel.Complement != null) wheel.UpdateTravel();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds upward force to rigid body based on difference of travel between complemented wheels.
|
|
/// </summary>
|
|
void AddAntiRollForceToRigidBody()
|
|
{
|
|
foreach (var wheel in _wheels.Where(x => x.Complement != null))
|
|
{
|
|
if (wheel.Travel == wheel.Complement.Travel) continue;
|
|
if (!wheel.Collider.isGrounded) continue;
|
|
|
|
var force = (wheel.Complement.Travel - wheel.Travel) * VConsts.Instance.AntiRollScale;
|
|
_rigidBody.AddForceAtPosition(wheel.Parent.transform.up * force, wheel.Parent.position);
|
|
}
|
|
}
|
|
|
|
}
|
|
} |