931 lines
26 KiB
C#
931 lines
26 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[Serializable]
|
|
public class Buggy : MonoBehaviour
|
|
{
|
|
//Object Linkages
|
|
public MeshFilter wing0;
|
|
public MeshFilter wing1;
|
|
public Transform floatPoints;
|
|
public GameObject wheel;
|
|
public GameObject axel;
|
|
public Transform leftTrail;
|
|
public Transform rightTrail;
|
|
public GameObject WheelmarksPrefab;
|
|
public Collider buggyCollider;
|
|
public WhirldLOD lod;
|
|
public Transform[] wheels;
|
|
public Transform[] wheelGraphics;
|
|
public Transform[] axels;
|
|
public Vector3 wheelPos;
|
|
public Vector3 axelPos;
|
|
|
|
//Internal Registers
|
|
private Vector3[] baseVertices;
|
|
// /*unused*/ private Vector3[] baseNormals;
|
|
private Mesh wingMesh;
|
|
private float wingState;
|
|
// /*unused*/ private int wingFlaps;
|
|
private bool wingOpen;
|
|
private bool isInverted;
|
|
private Vehicle vehicle;
|
|
private Transform[] bouyancyPoints;
|
|
private float suspensionRange;
|
|
private float friction;
|
|
// /*UNUSED*/ private float[] realComp;
|
|
private float[] hitDistance;
|
|
private float[] hitCompress;
|
|
private float[] hitFriction;
|
|
private Vector3[] hitVelocity;
|
|
private Vector3[] wheelPositn;
|
|
private Vector3[] hitForce;
|
|
private Skidmarks wheelMarks;
|
|
private int[] wheelMarkIndex;
|
|
private bool isDynamic;
|
|
private float frictionTotal;
|
|
private float brakePower;
|
|
|
|
//Drivetrain Data
|
|
private float motorTorque;
|
|
private float motorSpeed;
|
|
// /*UNUSED*/ private float motorSpd;
|
|
private float motorInputSmoothed;
|
|
private float wheelRadius;
|
|
private float wheelCircumference;
|
|
private int motorMass;
|
|
private int motorDrag;
|
|
private int maxAcceleration;
|
|
private int motorAccel;
|
|
// /*unused*/ private float motorSpeedNew;
|
|
|
|
public Buggy()
|
|
{
|
|
wingState = 0f;
|
|
//wingFlaps = 0;
|
|
isInverted = false;
|
|
//realComp = new float[4];
|
|
hitDistance = new float[4];
|
|
hitCompress = new float[4];
|
|
hitFriction = new float[4];
|
|
hitVelocity = new Vector3[4];
|
|
wheelPositn = new Vector3[4];
|
|
hitForce = new Vector3[4];
|
|
wheelMarkIndex = new int[4];
|
|
isDynamic = false;
|
|
motorSpeed = 0f;
|
|
//motorSpd = 0f;
|
|
motorInputSmoothed = 0f;
|
|
wheelRadius = 0.3f;
|
|
wheelCircumference = wheelRadius * (float)Math.PI * 2f;
|
|
motorMass = 1;
|
|
motorDrag = 1;
|
|
maxAcceleration = 60;
|
|
motorAccel = 60;
|
|
//motorSpeedNew = 0f;
|
|
}
|
|
|
|
public void InitVehicle(Vehicle veh)
|
|
{
|
|
vehicle = veh;
|
|
|
|
List<Material> materialAccents = new List<Material>();
|
|
|
|
//Init Wing Tinting
|
|
materialAccents.Add(wing0.renderer.material);
|
|
materialAccents.Add(wing1.renderer.material);
|
|
|
|
//Instantiate Wheels
|
|
int i;
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
wheelPositn[i] = new Vector3(
|
|
wheelPos.x * (float)((i % 2 != 0) ? 1 : (-1)),
|
|
wheelPos.y,
|
|
wheelPos.z * (float)((i < 2) ? 1 : (-1))
|
|
);
|
|
GameObject go = (GameObject)UnityEngine.Object.Instantiate(
|
|
wheel,
|
|
this.transform.TransformPoint(wheelPositn[i]),
|
|
this.transform.rotation
|
|
);
|
|
wheels[i] = go.transform;
|
|
wheelGraphics[i] = wheels[i].Find("Graphic").transform;
|
|
if (i == 1 || i == 3)
|
|
{
|
|
Vector3 localEulerAngles = wheels[i].Find("Graphic/Simple").transform.localEulerAngles;
|
|
localEulerAngles.y = 0;
|
|
wheels[i].Find("Graphic/Simple").transform.localEulerAngles = localEulerAngles;
|
|
}
|
|
MeshRenderer mR = (MeshRenderer)wheelGraphics[i].Find("Detailed/Beadlock").GetComponent(typeof(MeshRenderer));
|
|
materialAccents.Add(mR.material);
|
|
wheels[i].parent = this.transform;
|
|
go = (GameObject)UnityEngine.Object.Instantiate(
|
|
axel,
|
|
this.transform.TransformPoint(new Vector3(
|
|
axelPos.x * (float)((i % 2 != 0) ? 1 : (-1)),
|
|
axelPos.y,
|
|
axelPos.z * (float)((i < 2) ? 1 : (-1))
|
|
)),
|
|
this.transform.rotation
|
|
);
|
|
axels[i] = go.transform;
|
|
axels[i].parent = this.transform;
|
|
}
|
|
|
|
//Instantiate Skidmarks
|
|
if (vehicle.isPlayer)
|
|
{
|
|
GameObject go = (GameObject)UnityEngine.Object.Instantiate(
|
|
WheelmarksPrefab,
|
|
Vector3.zero,
|
|
Quaternion.identity
|
|
);
|
|
go.layer = 11;
|
|
wheelMarks = (Skidmarks)go.GetComponentInChildren(typeof(Skidmarks));
|
|
}
|
|
else
|
|
{
|
|
leftTrail.gameObject.active = false;
|
|
rightTrail.gameObject.active = false;
|
|
}
|
|
|
|
//Initialize Bouyancy Points
|
|
i = 0;
|
|
bouyancyPoints = new Transform[floatPoints.childCount];
|
|
foreach (Transform pt in floatPoints)
|
|
{
|
|
bouyancyPoints[i] = pt;
|
|
i++;
|
|
}
|
|
|
|
vehicle.materialAccent = (Material[])materialAccents.ToArray();
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
//Wings
|
|
if (wingState != 0f)
|
|
{
|
|
wingState += Time.deltaTime * 2f;
|
|
if (wingState >= 1f)
|
|
{
|
|
wingOpen = true;
|
|
if (wingState > 2f)
|
|
{
|
|
wingState = 0f;
|
|
}
|
|
}
|
|
//Closing Wings
|
|
else if (wingState > 0f)
|
|
{
|
|
wingOpen = false;
|
|
|
|
Vector3 localPosition = leftTrail.localPosition;
|
|
localPosition.x = 0;
|
|
leftTrail.localPosition = localPosition;
|
|
|
|
localPosition = rightTrail.localPosition;
|
|
localPosition.x = 0;
|
|
rightTrail.localPosition = localPosition;
|
|
|
|
wingState = 0f;
|
|
}
|
|
}
|
|
wingMesh = ((lod.level != 0) ? wing1 : wing0).mesh;
|
|
((lod.level != 0) ? wing1 : wing0).gameObject.active = wingOpen;
|
|
if (wingOpen)
|
|
{
|
|
if (baseVertices == null)
|
|
{
|
|
baseVertices = wingMesh.vertices;
|
|
}
|
|
Vector3[] vertices = new Vector3[baseVertices.Length];
|
|
for (int i = 0; i < vertices.Length; i++)
|
|
{
|
|
Vector3 pos = baseVertices[i];
|
|
if (wingState >= -1 && wingState < 0 || wingState >= 1 && wingState < 2)
|
|
{
|
|
if (wingState > 0f)
|
|
{
|
|
pos.y *= wingState - 1f;
|
|
pos.x *= wingState - 1f;
|
|
|
|
Vector3 localPosition = leftTrail.localPosition;
|
|
localPosition.x = (wingState - 1f) * (3.5f * -1f);
|
|
leftTrail.localPosition = localPosition;
|
|
|
|
localPosition = rightTrail.localPosition;
|
|
localPosition.x = (wingState - 1f) * 3.5f;
|
|
rightTrail.localPosition = localPosition;
|
|
}
|
|
else
|
|
{
|
|
pos.y *= wingState;
|
|
pos.x *= wingState;
|
|
|
|
Vector3 localPosition = leftTrail.localPosition;
|
|
localPosition.x = wingState * 3.5f;
|
|
leftTrail.localPosition = localPosition;
|
|
|
|
localPosition = rightTrail.localPosition;
|
|
localPosition.x = wingState * (3.5f * -1f);
|
|
rightTrail.localPosition = localPosition;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float t = pos.z * (vehicle.input.x * 0.14f);
|
|
if (pos.z > 0.2) t = 0;
|
|
else t *= (Mathf.Abs(pos.x) / 10);
|
|
t += pos.x * (motorInputSmoothed * 0.04f);
|
|
float st = Mathf.Sin(t);
|
|
float ct = Mathf.Cos(t);
|
|
pos.x = pos.y * st + pos.x * ct;
|
|
pos.y = pos.y * ct - pos.x * st;
|
|
}
|
|
vertices[i] = pos;
|
|
}
|
|
if (!(wingState >= -1 && wingState < 0 || wingState >= 1 && wingState < 2))
|
|
{
|
|
Vector3 localPosition = leftTrail.localPosition;
|
|
localPosition.x = -3.5f;
|
|
leftTrail.localPosition = localPosition;
|
|
|
|
localPosition = rightTrail.localPosition;
|
|
localPosition.x = 3.5f;
|
|
rightTrail.localPosition = localPosition;
|
|
}
|
|
wingMesh.vertices = vertices;
|
|
}
|
|
else
|
|
{
|
|
Vector3 localPosition = rightTrail.localPosition;
|
|
localPosition.x = 0;
|
|
rightTrail.localPosition = localPosition;
|
|
|
|
localPosition = leftTrail.localPosition;
|
|
localPosition.x = 0;
|
|
leftTrail.localPosition = localPosition;
|
|
}
|
|
|
|
//Wheels
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
Vector3 pos = new Vector3(
|
|
wheelPos.x * ((i % 2 != 0) ? 1 : -1),
|
|
wheelPos.y - (hitDistance[i] == -1 ? suspensionRange : (hitDistance[i] - wheelRadius)),
|
|
wheelPos.z * (i < 2 ? 1 : -1)
|
|
);
|
|
wheels[i].transform.position = this.transform.TransformPoint(pos);
|
|
wheelGraphics[i].transform.Rotate(
|
|
360f * (motorSpeed / wheelCircumference) * Time.deltaTime * 0.5f,
|
|
0,
|
|
0
|
|
);
|
|
if (axels[i].gameObject.active)
|
|
{
|
|
axels[i].LookAt(wheels[i].position);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void FixedUpdate()
|
|
{
|
|
bool wheelsAreTouchingGround = false;
|
|
if (Game.Settings.buggySmartSuspension)
|
|
{
|
|
//Auto Gear Retract
|
|
if (
|
|
(Game.Settings.buggyNewPhysics || wingOpen) &&
|
|
!Physics.Raycast(
|
|
this.transform.position,
|
|
Vector3.up * -1f, 5f,
|
|
vehicle.terrainMask
|
|
)
|
|
)
|
|
{
|
|
if (suspensionRange > 0.01f)
|
|
{
|
|
suspensionRange -= Time.deltaTime * 0.5f;
|
|
}
|
|
else
|
|
{
|
|
suspensionRange = 0f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
suspensionRange = Mathf.Lerp(
|
|
suspensionRange,
|
|
(wingOpen ? 0.5f : Mathf.Lerp(
|
|
0.4f,
|
|
0.2f,
|
|
Mathf.Min(
|
|
1f,
|
|
((Game.Settings.buggyNewPhysics ?
|
|
vehicle.myRigidbody.velocity.magnitude :
|
|
Mathf.Abs(motorSpeed)) / Game.Settings.buggySpeed
|
|
)
|
|
)
|
|
)),
|
|
Time.deltaTime * 3f
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
suspensionRange = 0.4f;
|
|
}
|
|
Vector3 centerOfMass = vehicle.myRigidbody.centerOfMass;
|
|
centerOfMass.z = 0.2f;
|
|
vehicle.myRigidbody.centerOfMass = centerOfMass;
|
|
|
|
centerOfMass = vehicle.myRigidbody.centerOfMass;
|
|
centerOfMass.y = Game.Settings.buggyCG * suspensionRange * 0.5f;
|
|
vehicle.myRigidbody.centerOfMass = centerOfMass;
|
|
|
|
vehicle.myRigidbody.mass = 30f;
|
|
|
|
RaycastHit hit = default(RaycastHit);
|
|
checked
|
|
{
|
|
if (vehicle.myRigidbody.isKinematic)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (
|
|
Physics.Raycast(
|
|
transform.TransformPoint(wheelPositn[i]),
|
|
transform.up * -1,
|
|
out hit,
|
|
suspensionRange + wheelRadius, vehicle.terrainMask
|
|
)
|
|
)
|
|
{
|
|
motorSpeed = hitVelocity[i].z;
|
|
hitDistance[i] = hit.distance;
|
|
}
|
|
else hitDistance[i] = -1;
|
|
}
|
|
return;
|
|
}
|
|
if (wingOpen)
|
|
{
|
|
motorInputSmoothed = Mathf.Lerp(
|
|
vehicle.input.y,
|
|
motorInputSmoothed + (vehicle.brakes ? -1 : 0),
|
|
0.8f
|
|
);
|
|
int stallSpeed = 16;
|
|
Vector3 locVel = transform.InverseTransformDirection(vehicle.myRigidbody.velocity);
|
|
float roll = ((!(transform.eulerAngles.z > 180f)) ?
|
|
transform.eulerAngles.z :
|
|
(transform.eulerAngles.z - 360f)
|
|
);
|
|
float pitch = ((!(transform.eulerAngles.x > 180f)) ?
|
|
transform.eulerAngles.x :
|
|
(transform.eulerAngles.x - 360f)
|
|
);
|
|
if (locVel.sqrMagnitude > (float)stallSpeed)
|
|
{
|
|
vehicle.myRigidbody.drag = vehicle.myRigidbody.velocity.magnitude / Game.Settings.buggyFlightDrag * 0.3f;
|
|
|
|
//Airbrakes
|
|
if (vehicle.brakes)
|
|
{
|
|
if (brakePower < 1f)
|
|
{
|
|
brakePower += Time.deltaTime * 0.15f;
|
|
}
|
|
float multiplier = -brakePower * 2f;
|
|
vehicle.myRigidbody.AddRelativeForce(
|
|
locVel.x * multiplier * 5f,
|
|
locVel.y * multiplier * 100f,
|
|
locVel.z * 150f * multiplier
|
|
);
|
|
vehicle.myRigidbody.AddRelativeTorque(new Vector3(
|
|
(pitch + (vehicle.input.y * -100f)) * -2f,
|
|
vehicle.input.x * 280f,
|
|
roll * -1f
|
|
));
|
|
}
|
|
|
|
//Standard Flight
|
|
else
|
|
{
|
|
brakePower = 0f;
|
|
float angDelta = Vector3.Angle(
|
|
vehicle.myRigidbody.velocity,
|
|
transform.TransformDirection(Vector3.forward)
|
|
);
|
|
if (angDelta > 10f && Game.Settings.buggyFlightSlip)
|
|
{
|
|
vehicle.myRigidbody.velocity = vehicle.myRigidbody.transform.TransformDirection(
|
|
locVel.x * 0.95f,
|
|
locVel.y * 0.95f,
|
|
locVel.z + ((Mathf.Abs(locVel.x) + Mathf.Abs(locVel.y)) * 0.1f * (angDelta / 360))
|
|
);
|
|
}
|
|
else
|
|
{
|
|
vehicle.myRigidbody.velocity = vehicle.myRigidbody.transform.TransformDirection(
|
|
0,
|
|
0,
|
|
locVel.magnitude + (Time.deltaTime * 50 * (Game.Settings.buggyFlightLooPower ?
|
|
Mathf.Abs(motorInputSmoothed) / 10 :
|
|
(motorInputSmoothed < 0.999f && motorInputSmoothed > -0.999f ?
|
|
Mathf.Abs(motorInputSmoothed) / 10 :
|
|
0
|
|
)
|
|
))
|
|
);
|
|
}
|
|
vehicle.myRigidbody.AddRelativeTorque(new Vector3(
|
|
motorInputSmoothed * 100 * Game.Settings.buggyFlightAgility,
|
|
0,
|
|
vehicle.input.x * -100 * Game.Settings.buggyFlightAgility
|
|
));
|
|
}
|
|
|
|
//Slideslip - "Dihedral"
|
|
if (
|
|
vehicle.input.x == 0 &&
|
|
(transform.eulerAngles.z < 90 ||
|
|
transform.eulerAngles.z > 270
|
|
)
|
|
)
|
|
{
|
|
vehicle.myRigidbody.AddRelativeTorque(
|
|
((transform.eulerAngles.x < 10 || transform.eulerAngles.x > 350) ?
|
|
pitch - 0.95f :
|
|
0
|
|
) * -0,
|
|
roll * -0.6f,
|
|
((transform.eulerAngles.z < 20 || transform.eulerAngles.z > 340) ?
|
|
roll * -0.5f :
|
|
0
|
|
)
|
|
);
|
|
}
|
|
else if (vehicle.input.x == 0){
|
|
vehicle.myRigidbody.AddRelativeTorque(
|
|
0,
|
|
(transform.eulerAngles.z - 180) * 0.4f, 0
|
|
);
|
|
}
|
|
|
|
//Lava "Thermals"
|
|
if (
|
|
transform.position.y < Game.Settings.lavaAlt + 10 ||
|
|
Physics.Raycast(transform.position, Vector3.down, out hit, 10, 1 << 4)
|
|
)
|
|
{
|
|
vehicle.myRigidbody.AddForce(Vector3.up * (10 - hit.distance) * 40);
|
|
}
|
|
vehicle.myRigidbody.angularDrag = 5f;
|
|
}
|
|
else
|
|
{
|
|
//Stalling
|
|
vehicle.myRigidbody.angularDrag = 1f;
|
|
vehicle.myRigidbody.drag = vehicle.myRigidbody.velocity.magnitude / Game.Settings.buggyFlightDrag * 9f;
|
|
vehicle.myRigidbody.AddRelativeTorque(new Vector3(
|
|
vehicle.input.y + 0.5f * 100f,
|
|
0f,
|
|
vehicle.input.x * -30f
|
|
));
|
|
}
|
|
}
|
|
else if (vehicle.brakes && vehicle.myRigidbody.velocity.magnitude < 1.5f)
|
|
{
|
|
if (vehicle.input.y != 0f)
|
|
{
|
|
vehicle.myRigidbody.drag = 2f;
|
|
}
|
|
else
|
|
{
|
|
vehicle.myRigidbody.drag = 50f;
|
|
}
|
|
vehicle.myRigidbody.angularDrag = 1f;
|
|
}
|
|
else if (vehicle.brakes && vehicle.myRigidbody.velocity.magnitude < 10f)
|
|
{
|
|
if (vehicle.input.y != 0f)
|
|
{
|
|
vehicle.myRigidbody.drag = 2f;
|
|
}
|
|
else
|
|
{
|
|
vehicle.myRigidbody.drag = 10f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vehicle.myRigidbody.angularDrag = 0.2f;
|
|
vehicle.myRigidbody.drag = 0.01f;
|
|
}
|
|
|
|
//Steering
|
|
float steeringAngle = Mathf.Lerp(
|
|
40f,
|
|
30f,
|
|
vehicle.myRigidbody.velocity.magnitude / Game.Settings.buggySpeed
|
|
);
|
|
wheels[0].localRotation = (wheels[1].localRotation = Quaternion.LookRotation(new Vector3(
|
|
vehicle.input.x * (steeringAngle / 90f),
|
|
0f,
|
|
1f + -1f * Mathf.Abs(vehicle.input.x * (steeringAngle / 90f))
|
|
)));
|
|
steeringAngle = Mathf.Lerp(
|
|
20f,
|
|
0f,
|
|
vehicle.myRigidbody.velocity.magnitude / Game.Settings.buggySpeed
|
|
);
|
|
wheels[2].localRotation = (wheels[3].localRotation = Quaternion.LookRotation(new Vector3(
|
|
vehicle.input.x * -1f * (steeringAngle / 90f),
|
|
0f,
|
|
1f + -1f * Mathf.Abs(vehicle.input.x * (steeringAngle / 90f))
|
|
)));
|
|
|
|
//Experimental Motor Physics
|
|
if (Game.Settings.buggyNewPhysics)
|
|
{
|
|
motorTorque = -vehicle.input.y * Mathf.Lerp(
|
|
Game.Settings.buggyPower * 3f,
|
|
0f,
|
|
hitVelocity[0].z / Game.Settings.buggySpeed
|
|
);
|
|
|
|
//Apply Wheel Force
|
|
frictionTotal = 0f;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (
|
|
Physics.Raycast(
|
|
transform.TransformPoint(wheelPositn[i]),
|
|
transform.up * -1,
|
|
out hit,
|
|
suspensionRange + wheelRadius,
|
|
vehicle.terrainMask
|
|
)
|
|
)
|
|
{
|
|
//Static Friction
|
|
if (motorTorque == 0 || motorTorque < (hitFriction[i] * hitForce[i].z))
|
|
{
|
|
motorSpeed = hitVelocity[i].z;
|
|
}
|
|
//Dynamic Friction
|
|
else
|
|
{
|
|
motorSpeed = Mathf.Lerp(
|
|
Game.Settings.buggySpeed,
|
|
0,
|
|
(motorTorque - (hitFriction[i] * hitForce[i].z)) / motorTorque
|
|
);
|
|
//motorSpeed += -motorSpeed * motorDrag / motorTorque * Time.fixedDeltaTime;
|
|
}
|
|
//motorSpd = (frictionTotal - Game.Settings.buggyPower * 3) / (Game.Settings.buggyPower * 3 / Game.Settings.buggySpeed);
|
|
|
|
wheelsAreTouchingGround = true;
|
|
isDynamic = (
|
|
(motorTorque > hitFriction[i]) ||
|
|
(Mathf.Abs(hitVelocity[i].x) > Mathf.Abs(hitVelocity[i].z) * 0.3f)
|
|
);
|
|
hitDistance[i] = hit.distance;
|
|
hitCompress[i] = -((hit.distance) / (suspensionRange + wheelRadius)) + 1;
|
|
hitVelocity[i] = wheels[i].InverseTransformDirection(vehicle.myRigidbody.GetPointVelocity(transform.TransformPoint(wheelPositn[i])));
|
|
if (isDynamic)
|
|
{
|
|
hitFriction[i] = Game.Settings.buggyTr * 60;
|
|
//Debug.DrawRay(transform.TransformPoint(wheelPositn[i]),transform.up * 5, Color.red);
|
|
//getSpringForce(comp, vel.y) * //Spring Compression position, normalized (0-1)
|
|
//Mathf.Lerp(1, 1, Mathf.Min(comp * 4, 1)) //Static tire friction coeffecient, as function of downforce*/
|
|
}
|
|
else
|
|
{
|
|
hitFriction[i] = Game.Settings.buggyTr * 150 * Mathf.Lerp(
|
|
1.5f,
|
|
0.5f,
|
|
Mathf.Min(hitCompress[i] * 3, 1)
|
|
);
|
|
}
|
|
|
|
Vector3 dir = new Vector3(
|
|
hitVelocity[i].x,
|
|
0,
|
|
(
|
|
Game.Settings.buggyAWD == true ||
|
|
i > 1 ? (hitVelocity[i].z - motorSpeed) : 0
|
|
)
|
|
);
|
|
if (dir.magnitude > 1) dir = dir.normalized;
|
|
hitForce[i] = dir;
|
|
//Debug.DrawRay(transform.TransformPoint(wheelPositn[i]),transform.right * dir.x, Color.blue);
|
|
//Debug.DrawRay(transform.TransformPoint(wheelPositn[i]),transform.forward * dir.z, Color.blue);
|
|
Vector3 force = wheels[i].TransformDirection(dir * -hitFriction[i]);
|
|
//Debug.DrawRay(hit.point,force / 50);
|
|
vehicle.myRigidbody.AddForceAtPosition(force, hit.point);
|
|
if (wheelMarks)
|
|
{
|
|
//Do Tire Tracks
|
|
wheelMarkIndex[i] = wheelMarks.AddSkidMark(
|
|
hit.point,
|
|
hit.normal,
|
|
(isDynamic ? 1 : Mathf.Min(
|
|
0.5f,
|
|
force.magnitude * 0.0025f
|
|
)),
|
|
wheelMarkIndex[i]
|
|
);
|
|
}
|
|
frictionTotal += hitFriction[i];
|
|
}
|
|
else
|
|
{
|
|
hitDistance[i] = -1;
|
|
wheelMarkIndex[i] = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Modified Yoggy physics
|
|
else
|
|
{
|
|
//Motor
|
|
motorTorque = Mathf.Max(
|
|
1f,
|
|
Mathf.Lerp(
|
|
Game.Settings.buggyPower * 5f,
|
|
0f,
|
|
motorSpeed / (Game.Settings.buggySpeed * 10f)
|
|
) * Mathf.Abs((wingOpen ? 0 : vehicle.input.y))
|
|
);
|
|
motorAccel = (int)Mathf.Lerp(
|
|
maxAcceleration,
|
|
0f,
|
|
motorSpeed / (Game.Settings.buggySpeed * 10f)
|
|
);
|
|
motorSpeed += vehicle.input.y * (float)motorAccel / (float)motorMass * Time.fixedDeltaTime;
|
|
motorSpeed += -motorSpeed * (vehicle.brakes ? 50 : motorDrag) / motorTorque * Time.fixedDeltaTime;
|
|
|
|
//Wheel / Terrain Collisions
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (Physics.Raycast(
|
|
transform.TransformPoint(wheelPositn[i]),
|
|
transform.up * -1f,
|
|
out hit,
|
|
suspensionRange + wheelRadius, vehicle.terrainMask
|
|
))
|
|
{
|
|
wheelsAreTouchingGround = true;
|
|
hitCompress[i] = -((hit.distance) / (suspensionRange + wheelRadius)) + 1;
|
|
hitVelocity[i] = wheels[i].InverseTransformDirection(
|
|
vehicle.myRigidbody.GetPointVelocity(transform.TransformPoint(wheelPositn[i]))
|
|
);
|
|
if (hit.rigidbody)
|
|
{
|
|
vehicle.myRigidbody.AddForceAtPosition(
|
|
(hitVelocity[i] - wheels[i].InverseTransformDirection(
|
|
hit.rigidbody.GetPointVelocity(hit.point)
|
|
)) / 4,
|
|
hit.point,
|
|
ForceMode.VelocityChange
|
|
);
|
|
//vehicle.transform.position += (hit.rigidbody.GetPointVelocity(hit.point) * Time.fixedDeltaTime) / 4;
|
|
//hitVelocity[i] = hit.rigidbody.GetPointVelocity(hit.point);
|
|
//hitVelocity[i] = hit.rigidbody.GetPointVelocity(hit.point);
|
|
}
|
|
friction = Game.Settings.buggyTr * 9 * Mathf.Lerp(0.5f, 1, hitCompress[i]) * Mathf.Max(1, (20 - hitVelocity[i].magnitude) / 4);
|
|
vehicle.myRigidbody.AddForceAtPosition(wheels[i].TransformDirection(Vector3.Min(new Vector3(
|
|
-hitVelocity[i].x * friction, //Sideslip
|
|
0,
|
|
-(hitVelocity[i].z - motorSpeed) * friction //Motor
|
|
), new Vector3(1000, 1000, 1000))), hit.point);
|
|
motorSpeed += ((hitVelocity[i].z - motorSpeed) * friction * Time.fixedDeltaTime) / motorTorque;
|
|
if (wheelMarks)
|
|
{
|
|
//Do Tire Tracks
|
|
wheelMarkIndex[i] = wheelMarks.AddSkidMark(
|
|
hit.point,
|
|
hit.normal,
|
|
(Mathf.Abs(hitVelocity[i].x) > Mathf.Abs(hitVelocity[i].z) * 0.3f ?
|
|
Mathf.Abs(vehicle.input.y) * 0.5f + 0.25f :
|
|
Mathf.Min(0.5f, friction * 0.05f)
|
|
),
|
|
wheelMarkIndex[i]
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hit.distance = -1f;
|
|
wheelMarkIndex[i] = -1;
|
|
}
|
|
hitDistance[i] = hit.distance;
|
|
}
|
|
}
|
|
|
|
//Suspension
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (hitDistance[i] == -1) continue;
|
|
vehicle.myRigidbody.AddForceAtPosition(
|
|
transform.up * (-hitVelocity[i].y * Game.Settings.buggySh * 1 * (wingOpen ? 3 : 1) + hitCompress[i] * (20 * vehicle.myRigidbody.mass) * (wingOpen && i < 2 ? 8 : 1)),
|
|
transform.TransformPoint(wheelPositn[i])
|
|
);
|
|
}
|
|
|
|
//Floating
|
|
if (
|
|
(transform.position.y < Game.Settings.lavaAlt + 0.1f && transform.position.y - Game.Settings.lavaAlt > -3f) ||
|
|
Physics.Raycast(transform.position + Vector3.up * 3f, Vector3.down, out hit, 3.1f, 1 << 4)
|
|
)
|
|
{
|
|
//Vars
|
|
if (wingOpen && hit.distance < 2f)
|
|
{
|
|
vehicle.myRigidbody.AddForce(Vector3.up * 400f);
|
|
}
|
|
float roll = (transform.eulerAngles.z > 180 ?
|
|
transform.eulerAngles.z - 360 :
|
|
transform.eulerAngles.z
|
|
);
|
|
float pitch = (transform.eulerAngles.x > 180 ?
|
|
transform.eulerAngles.x - 360 :
|
|
transform.eulerAngles.x
|
|
);
|
|
vehicle.myRigidbody.angularDrag = 2f;
|
|
|
|
//Flowing Lava
|
|
float waterAngle = default(float);
|
|
Vector3 waterAxis = default(Vector3);
|
|
if (hit.distance != 0f && (bool)hit.transform)
|
|
{
|
|
hit.transform.rotation.ToAngleAxis(out waterAngle, out waterAxis);
|
|
if (waterAngle != 0f)
|
|
{
|
|
vehicle.myRigidbody.AddForce(hit.transform.rotation.eulerAngles * 0.8f);
|
|
}
|
|
}
|
|
|
|
//BouyancyPoints
|
|
int i = 0;
|
|
Transform[] m = bouyancyPoints;
|
|
for (int length = m.Length; i < length; i++)
|
|
{
|
|
if (
|
|
m[i].position.y < Game.Settings.lavaAlt ||
|
|
Physics.Raycast(
|
|
m[i].position + (Vector3.up * 3f),
|
|
Vector3.down,
|
|
out hit,
|
|
3f,
|
|
1 << 4
|
|
)
|
|
)
|
|
{
|
|
float bouyancyY = (hit.distance != 0f ?
|
|
hit.distance - 5 :
|
|
m[i].position.y - 2 - Game.Settings.lavaAlt
|
|
);
|
|
if (bouyancyY < -1.8f)
|
|
{
|
|
bouyancyY = -1.8f;
|
|
}
|
|
vehicle.myRigidbody.AddForceAtPosition((new Vector3(
|
|
0f,
|
|
-bouyancyY * (100f + vehicle.myRigidbody.GetPointVelocity(m[i].position).magnitude * (float)((!(vehicle.myRigidbody.GetPointVelocity(m[i].position).magnitude > 15f)) ? 15 : 100)),
|
|
0f
|
|
) + vehicle.myRigidbody.GetPointVelocity(m[i].position) * -200f) / bouyancyPoints.Length, m[i].position);
|
|
}
|
|
}
|
|
if (vehicle.input.y >= 0f)
|
|
{
|
|
vehicle.myRigidbody.AddRelativeTorque(new Vector3(
|
|
vehicle.input.y * -1f * 500f * ((70f - Mathf.Min(70f, Mathf.Max(1f, pitch * -1f))) / 70f),
|
|
vehicle.input.y * vehicle.input.x * 300f,
|
|
roll * -3f + vehicle.input.y * vehicle.input.x * -50f
|
|
));
|
|
}
|
|
if (!wingOpen && hit.distance < 3f)
|
|
{
|
|
vehicle.myRigidbody.AddRelativeForce(
|
|
Vector3.forward * vehicle.input.y * 1200f
|
|
);
|
|
}
|
|
}
|
|
|
|
//Diving
|
|
else if (
|
|
transform.position.y < Game.Settings.lavaAlt ||
|
|
Physics.Raycast(
|
|
transform.position + Vector3.up * 200f,
|
|
Vector3.down, 200f,
|
|
1 << 4
|
|
)
|
|
)
|
|
{
|
|
vehicle.myRigidbody.AddForce(vehicle.myRigidbody.velocity * -8f + Vector3.up * (wingOpen ? 400 : 200));
|
|
vehicle.myRigidbody.angularDrag = 2f;
|
|
}
|
|
|
|
//Collision Friction
|
|
if (
|
|
wingOpen ||
|
|
wheelsAreTouchingGround ||
|
|
Physics.Raycast(
|
|
transform.position,
|
|
transform.up * -1f,
|
|
3f,
|
|
vehicle.terrainMask
|
|
)
|
|
)
|
|
{
|
|
buggyCollider.material.frictionCombine = PhysicMaterialCombine.Minimum;
|
|
}
|
|
else
|
|
{
|
|
buggyCollider.material.frictionCombine = PhysicMaterialCombine.Maximum;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Self righting
|
|
public void OnCollisionStay(Collision collision)
|
|
{
|
|
if (vehicle.zorbBall)
|
|
{
|
|
return;
|
|
}
|
|
int i = 0;
|
|
ContactPoint[] contact = collision.contacts;
|
|
for (int length = contact.Length; i < length; i = checked(i + 1))
|
|
{
|
|
if (
|
|
isInverted &&
|
|
Vector3.Angle(transform.up, contact[i].normal) < 50f
|
|
)
|
|
{
|
|
isInverted = false;
|
|
}
|
|
else if (
|
|
!isInverted &&
|
|
vehicle.myRigidbody.angularVelocity.sqrMagnitude < 5f &&
|
|
!wingOpen
|
|
&& Vector3.Angle(transform.up, contact[i].normal) > 120f
|
|
)
|
|
{
|
|
isInverted = true;
|
|
}
|
|
if (isInverted)
|
|
{
|
|
vehicle.myRigidbody.AddTorque(
|
|
Vector3.Cross(
|
|
transform.up,
|
|
Vector3.up
|
|
) * Vector3.Angle(transform.up, Vector3.up) * 3f
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
public IEnumerator OnSetSpecialInput()
|
|
{
|
|
while (!vehicle) yield return null;
|
|
|
|
vehicle.camSmooth = vehicle.specialInput;
|
|
if (vehicle.specialInput)
|
|
{
|
|
wingState = 1;
|
|
//wingFlaps = 0;
|
|
}
|
|
else
|
|
{
|
|
wingState = -1;
|
|
//wingFlaps = 0;
|
|
}
|
|
}
|
|
|
|
public void OnDisable()
|
|
{
|
|
if ((bool)wheelMarks)
|
|
{
|
|
UnityEngine.Object.Destroy(wheelMarks.gameObject);
|
|
}
|
|
}
|
|
|
|
public void OnLOD(int level)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
wheelGraphics[i].Find("Detailed").gameObject.SetActiveRecursively(level == 0);
|
|
wheelGraphics[i].Find("Simple").gameObject.active = level != 0;
|
|
axels[i].gameObject.SetActiveRecursively(level == 0);
|
|
}
|
|
}
|
|
} |