*
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class Accumulator : IElecticEnergySource {
|
||||
public float voltage = 12.0f;
|
||||
public float maxPower = 520.0f;
|
||||
|
||||
public override float Voltage {
|
||||
get {
|
||||
return voltage;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaxPower {
|
||||
get {
|
||||
return maxPower;
|
||||
}
|
||||
}
|
||||
public override string Name {
|
||||
get {
|
||||
return "Accumulator";
|
||||
}
|
||||
}
|
||||
|
||||
public override string ShortDescription {
|
||||
get {
|
||||
return "Accumulator";
|
||||
}
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37417f8d68420ec4baa192c11dc66130
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,132 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
|
||||
public class AdvancedGizmo {
|
||||
public static void DrawCircle(Vector3 center, Vector3 normal, float radius, Color color, int tesselation = 12, bool drawNormal = false, int diagonalCount = 0){
|
||||
if (tesselation < 3) {
|
||||
Debug.LogError("Invalid tesselation value! Should be >= 3");
|
||||
}
|
||||
Vector3 right = Vector3.right;
|
||||
if (Mathf.Abs (Vector3.Dot (right, normal)) > 0.999f) {
|
||||
right = Vector3.up;
|
||||
}
|
||||
|
||||
Vector3 front = Vector3.Cross (right, normal).normalized;
|
||||
|
||||
Gizmos.color = color;
|
||||
|
||||
for(int i = 0; i < tesselation; ++i){
|
||||
//Gizmos.DrawLine(
|
||||
Gizmos.DrawLine(
|
||||
center + Quaternion.AngleAxis((360.0f / tesselation) * (i + 0), normal) * front * radius,
|
||||
center + Quaternion.AngleAxis((360.0f / tesselation) * (i + 1), normal) * front * radius
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = 0; i < diagonalCount; ++i) {
|
||||
float a1 = (180.0f / diagonalCount) * i;
|
||||
float a2 = a1 + 180.0f;
|
||||
|
||||
Gizmos.DrawLine(
|
||||
center + Quaternion.AngleAxis(a1, normal) * front * radius,
|
||||
center + Quaternion.AngleAxis(a2, normal) * front * radius
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawGrid(Vector3 center, float width, float height, int wSections = 1, int hSections = 1){
|
||||
Vector3 topLeft = new Vector3 (-width * 0.5f, 0, height * 0.5f);
|
||||
Vector3 wStep = new Vector3 (width / wSections, 0, 0);
|
||||
Vector3 hStep = new Vector3 (0, 0, -height / hSections);
|
||||
|
||||
|
||||
//draw horizontal lines
|
||||
for (int i = 0; i <= hSections; ++i) {
|
||||
Vector3 p1 = topLeft + hStep * i + center;
|
||||
Debug.DrawLine(p1, p1 + new Vector3(width, 0, 0));
|
||||
}
|
||||
|
||||
//draw vertical lines
|
||||
for (int i = 0; i <= hSections; ++i) {
|
||||
Vector3 p1 = topLeft + wStep * i + center;
|
||||
Debug.DrawLine(p1, p1 + new Vector3(0, 0, -height));
|
||||
}
|
||||
}
|
||||
|
||||
public delegate float fx(float x);
|
||||
public static void Plot2D(fx func, Matrix4x4 tranfsorm, Vector3 center, Vector3 xAxis, Vector3 yAxis, float xLen, float xScale, float yScale, int sampleCount, Color color){
|
||||
float xStep = xLen / (sampleCount - 1);
|
||||
Vector3[] points = new Vector3[sampleCount];
|
||||
|
||||
for (int i = 0; i < sampleCount; ++i) {
|
||||
float x1 = i * xStep;
|
||||
float arg1 = (x1 / xLen) * xScale;
|
||||
float y1 = func(arg1) * yScale;
|
||||
|
||||
points[i] = center + xAxis * x1 + yAxis * y1;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Color backup = Handles.color;
|
||||
Handles.matrix = tranfsorm;
|
||||
Handles.color = color;
|
||||
Handles.DrawPolyLine(points);
|
||||
Handles.color = backup;
|
||||
Handles.matrix = Matrix4x4.identity;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void DrawMesh(Vector3[] vertices, int[] indices, bool drawNormals){
|
||||
for(int i = 0; i < indices.Length; i+=3){
|
||||
Vector3 v0 = vertices[indices[i + 0]];
|
||||
Vector3 v1 = vertices[indices[i + 1]];
|
||||
Vector3 v2 = vertices[indices[i + 2]];
|
||||
Debug.DrawLine(v0, v1);
|
||||
Debug.DrawLine(v1, v2);
|
||||
Debug.DrawLine(v2, v0);
|
||||
|
||||
if(drawNormals){
|
||||
Vector3 center = (v0 + v1 + v2) / 3.0f;
|
||||
Vector3 normal = Vector3.Cross((v1 - v0), (v2 - v0));
|
||||
Debug.DrawRay(center, normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void DrawMesh(Vector3[] vertices, bool drawNormals){
|
||||
for(int i = 0; i < vertices.Length; i+=3){
|
||||
Vector3 v0 = vertices[i + 0];
|
||||
Vector3 v1 = vertices[i + 1];
|
||||
Vector3 v2 = vertices[i + 2];
|
||||
Debug.DrawLine(v0, v1);
|
||||
Debug.DrawLine(v1, v2);
|
||||
Debug.DrawLine(v2, v0);
|
||||
|
||||
if(drawNormals){
|
||||
Vector3 center = (v0 + v1 + v2) / 3.0f;
|
||||
Vector3 normal = Vector3.Cross((v1 - v0), (v2 - v0));
|
||||
Debug.DrawRay(center, normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawTriangle(Vector3 v0, Vector3 v1, Vector3 v2, bool drawNormal){
|
||||
Debug.DrawLine(v0, v1);
|
||||
Debug.DrawLine(v1, v2);
|
||||
Debug.DrawLine(v2, v0);
|
||||
|
||||
if(drawNormal){
|
||||
Vector3 center = (v0 + v1 + v2) / 3.0f;
|
||||
Vector3 normal = Vector3.Cross((v1 - v0), (v2 - v0));
|
||||
Debug.DrawRay(center, normal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ffe24c9424a34e34784f84b7268ac367
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ea2979d086da60468850bad54c0e1e3
|
||||
folderAsset: yes
|
||||
timeCreated: 1454272673
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class EngineRod : MonoBehaviour
|
||||
{
|
||||
public Transform anchor;
|
||||
public Transform piston;
|
||||
|
||||
public float rodLength;
|
||||
public Vector3 upVector;
|
||||
|
||||
private Vector3 startPosition;
|
||||
private Quaternion rotation;
|
||||
private Quaternion pistonRotation;
|
||||
// Use this for initialization
|
||||
void Start ()
|
||||
{
|
||||
upVector = piston.position - anchor.position;
|
||||
|
||||
rodLength = (transform.localPosition - transform.parent.InverseTransformPoint(piston.position)).magnitude;
|
||||
|
||||
upVector.Normalize();
|
||||
startPosition = transform.localPosition;
|
||||
upVector = transform.parent.InverseTransformVector(upVector);
|
||||
|
||||
rotation = transform.localRotation;
|
||||
pistonRotation = piston.localRotation;
|
||||
}
|
||||
|
||||
public float projectionDistance;
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
if (anchor != null)
|
||||
{
|
||||
transform.position = anchor.position;
|
||||
|
||||
Ray r = new Ray(startPosition, upVector);
|
||||
var localPosProjected = r.Project(transform.localPosition);
|
||||
projectionDistance = (localPosProjected - transform.localPosition).magnitude;
|
||||
|
||||
float pistonOffset = Mathf.Sqrt(rodLength*rodLength - projectionDistance*projectionDistance);
|
||||
|
||||
float angle = (90.0f - Mathf.Asin(pistonOffset/rodLength) * Mathf.Rad2Deg) *- Mathf.Sign(Vector3.Dot(transform.localPosition - localPosProjected, Vector3.forward));
|
||||
|
||||
|
||||
transform.localRotation = Quaternion.AngleAxis(angle, Vector3.right) * rotation;
|
||||
|
||||
piston.localRotation = pistonRotation * Quaternion.AngleAxis(-angle, Vector3.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd6ab127f9809c7448d4d9b971a91c0b
|
||||
timeCreated: 1454273101
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class RotationAnimation : MonoBehaviour
|
||||
{
|
||||
public Vector3 axis = Vector3.right;
|
||||
public float angle;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update ()
|
||||
{
|
||||
transform.localRotation = Quaternion.AngleAxis(angle*Time.deltaTime, axis.normalized)* transform.localRotation;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cefd9fdcf43268c488994d0c89f25194
|
||||
timeCreated: 1454272681
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,77 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class CameraController : MonoBehaviour {
|
||||
public bool Active = false;
|
||||
public float sensitivity = 2F;
|
||||
|
||||
float rotationY = 0F;
|
||||
|
||||
Vector3 Speed = new Vector3();
|
||||
public float MaxSpeed = 10f;
|
||||
public float AccelerationTime = 1f;
|
||||
public float BrakingTime = 0.5f;
|
||||
|
||||
|
||||
void Start ()
|
||||
{
|
||||
rotationY = -transform.localEulerAngles.x;
|
||||
}
|
||||
|
||||
void Update ()
|
||||
{
|
||||
if(Input.GetKeyDown("mouse 1")){
|
||||
Active = !Active;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!Active) return;
|
||||
|
||||
|
||||
|
||||
|
||||
float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivity;
|
||||
|
||||
rotationY += Input.GetAxis("Mouse Y") * sensitivity;
|
||||
rotationY = Mathf.Clamp (rotationY, -90, 90);
|
||||
|
||||
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
|
||||
|
||||
|
||||
Vector3 AccelerationForce = new Vector3(
|
||||
((Input.GetKey("d")? 1f:0f)-(Input.GetKey("a")? 1f:0f)),
|
||||
((Input.GetKey("space")? 1f:0f)-(Input.GetKey("left ctrl")? 1f:0f)),
|
||||
((Input.GetKey("w")? 1f:0f)-(Input.GetKey("s")? 1f:0f))
|
||||
);
|
||||
AccelerationForce *= (Time.deltaTime/AccelerationTime);
|
||||
Speed += AccelerationForce;
|
||||
|
||||
Vector3 BrakingForce = new Vector3(
|
||||
(Input.GetKey("d")|Input.GetKey("a"))? 0f:1f,
|
||||
(Input.GetKey("space")|Input.GetKey("left ctrl"))? 0f:1f,
|
||||
(Input.GetKey("w")|Input.GetKey("s"))? 0f:1f
|
||||
);
|
||||
|
||||
BrakingForce *= (Time.deltaTime/BrakingTime);
|
||||
|
||||
|
||||
|
||||
Speed.Set(
|
||||
Speed.x-(Mathf.Sign(Speed.x)*Mathf.Min(BrakingForce.x,Mathf.Abs(Speed.x))),
|
||||
Speed.y-(Mathf.Sign(Speed.y)*Mathf.Min(BrakingForce.y,Mathf.Abs(Speed.y))),
|
||||
Speed.z-(Mathf.Sign(Speed.z)*Mathf.Min(BrakingForce.z,Mathf.Abs(Speed.z))));
|
||||
|
||||
Speed.Set(
|
||||
Mathf.Clamp(Speed.x,-1f,1f),
|
||||
Mathf.Clamp(Speed.y,-1f,1f),
|
||||
Mathf.Clamp(Speed.z,-1f,1f));
|
||||
|
||||
|
||||
transform.Translate(Time.deltaTime*Speed*MaxSpeed,Space.Self);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fbc9b5ceeae8bd24cbedbe3c800c3dd0
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,20 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class CameraFollow : MonoBehaviour {
|
||||
public Transform target;
|
||||
public Vector3 cameraOffset;
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
if(target != null) {
|
||||
cameraOffset = transform.position - target.position;
|
||||
}
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
if(target != null) {
|
||||
transform.position = target.position + cameraOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4631c89c576451b4bae21e0103bd2d7a
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,159 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
public enum CarPedal{
|
||||
Clutch = 0,
|
||||
Brake = 1,
|
||||
Accelerator = 2
|
||||
}
|
||||
|
||||
[SelectionBase]
|
||||
public class Car : MonoBehaviour {
|
||||
public Chassis chassis;
|
||||
public SteeringWheel SteeringWheel;
|
||||
public CarEngine engine;
|
||||
private float _torque = 0;
|
||||
public GameObject Driver;
|
||||
public float dragCoeff = 0.35f;
|
||||
public float frontalArea = 1.99f;
|
||||
private float[] _pedals = new float[3];
|
||||
private Rigidbody _rigidBody;
|
||||
|
||||
public AnimationCurve throlleCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 1));
|
||||
|
||||
public CarElectricSystem electric;
|
||||
public Transmission transmission;
|
||||
|
||||
public float[] Pedals{
|
||||
get{ return _pedals;}
|
||||
}
|
||||
|
||||
void OnGUI() {
|
||||
// var rb = gameObject.GetComponent<Rigidbody>();
|
||||
//Label3D.AtWorldPosition(transform.position + Vector3.up * 2, "Velocity: " + rb.velocity.ToStringEx() + " Km/h: " + rb.velocity.magnitude * 3.6f);
|
||||
|
||||
}
|
||||
|
||||
public void SetPedalState(CarPedal pedal, float state){
|
||||
_pedals [(int)pedal] = Mathf.Clamp01 (state);
|
||||
}
|
||||
|
||||
public float GetPedalState(CarPedal pedal){
|
||||
return _pedals [(int)pedal];
|
||||
}
|
||||
|
||||
public Rigidbody GetRigidBody(){
|
||||
return _rigidBody;
|
||||
}
|
||||
|
||||
public float D{
|
||||
get { return 1; } //(Wheels[2].Target.transform.position - Wheels[0].Target.transform.position).magnitude;}
|
||||
}
|
||||
|
||||
public float L{
|
||||
get { return 1; } // (Wheels[1].Target.transform.position - Wheels[0].Target.transform.position).magnitude;}
|
||||
}
|
||||
|
||||
public static float OuterWheelAngle(float innerDegree, float d, float l){
|
||||
float sign = Mathf.Sign (innerDegree);
|
||||
|
||||
float rad = Mathf.Deg2Rad * innerDegree * sign;
|
||||
float ctgB = Mathf.Cos (rad) / Mathf.Sin (rad);
|
||||
return Arcctg (ctgB + d / l) * Mathf.Rad2Deg * sign;
|
||||
//ctgA = ctgB + d/L
|
||||
}
|
||||
|
||||
static float Arcctg(float x){
|
||||
return Mathf.PI / 2.0f - Mathf.Atan (x);
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
_rigidBody = gameObject.GetComponent<Rigidbody> ();
|
||||
electric.ignition.Attach (this);
|
||||
|
||||
/*foreach (var w in Wheels) {
|
||||
w.OnStart();
|
||||
}*/
|
||||
|
||||
//SteeringWheel.OnStart ();
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
public float Torque(){
|
||||
return _torque;
|
||||
}
|
||||
|
||||
void OnDrawGizmos(){
|
||||
//var rb = gameObject.GetComponent<Rigidbody> ();
|
||||
//float airDrag = CarMath.Drag(1.25f, rb.velocity.magnitude, dragCoeff, frontalArea);
|
||||
|
||||
//var drag = -airDrag * rb.velocity.normalized ;
|
||||
|
||||
//Gizmos.DrawLine(transform.position + Vector3.up, transform.position + Vector3.up + drag);
|
||||
}
|
||||
|
||||
float lastSpeed;
|
||||
float measureTime;
|
||||
|
||||
public float testSpeed = 100.0f;
|
||||
void FixedUpdate(){
|
||||
|
||||
var rb = gameObject.GetComponent<Rigidbody> ();
|
||||
|
||||
var vel = rb.velocity.magnitude * 3.6f; //km/h
|
||||
if(lastSpeed == 0 && vel != 0) {
|
||||
measureTime = Time.fixedTime;
|
||||
Debug.Log("Go go go");
|
||||
|
||||
} else if(lastSpeed < testSpeed && vel >= testSpeed) {
|
||||
Debug.LogFormat("Reached {0} Km/h in {1}", testSpeed, (Time.fixedTime - measureTime));
|
||||
}
|
||||
lastSpeed = vel;
|
||||
|
||||
chassis.suspension[0].wheel.driveTorque =
|
||||
chassis.suspension[2].wheel.driveTorque = 1000*GetPedalState(CarPedal.Accelerator);
|
||||
|
||||
chassis.suspension[0].wheel.brakeTorque =
|
||||
chassis.suspension[2].wheel.brakeTorque = 1000 * GetPedalState(CarPedal.Brake);
|
||||
|
||||
/* if (rb) {
|
||||
float airDrag = CarMath.Drag(1.25f, rb.velocity.magnitude, dragCoeff, frontalArea);
|
||||
|
||||
var drag = -airDrag * rb.velocity.normalized;
|
||||
rb.AddForce(-airDrag * rb.velocity.normalized);
|
||||
}*/
|
||||
|
||||
/*float torqueSpeed = 20.0f;
|
||||
if (Input.GetKey (KeyCode.UpArrow)) {
|
||||
_torque += torqueSpeed * Time.fixedDeltaTime;
|
||||
|
||||
} else if (Input.GetKey (KeyCode.DownArrow)) {
|
||||
_torque -= torqueSpeed * Time.fixedDeltaTime;
|
||||
} else {
|
||||
_torque *= 0.7f;
|
||||
}*/
|
||||
//_torque = Mathf.Clamp (_torque, -_maxTorque, _maxTorque);
|
||||
//Wheels [0].Collider.motorTorque = _torque;
|
||||
//Wheels [2].Collider.motorTorque = _torque;
|
||||
|
||||
chassis.Integrate(Time.fixedDeltaTime, this);
|
||||
|
||||
/*foreach (var w in Wheels) {
|
||||
if(w != null){
|
||||
var wheelVelocity = rb.GetPointVelocity(w.transform.position);
|
||||
Vector3 wheelForce;
|
||||
w.Integrate(Time.fixedDeltaTime, wheelVelocity, (rb.mass / 4.0f * 9.81f), out wheelForce);
|
||||
rb.AddForceAtPosition(wheelForce, w.transform.position);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb64e1fd180c4e24490bb6ef339e6970
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7df5d0173a73f4a4bacb78f66bac9966
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,44 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class Brake : MonoBehaviour {
|
||||
public float _friction = 100;
|
||||
public float _radius = 0.2f;
|
||||
public float _area = 0.2f;
|
||||
public float _max_pressure = 10;
|
||||
public float _bias = 1;
|
||||
private float _threshold = 4.0e-4f;
|
||||
private bool _is_locked;
|
||||
|
||||
public Brake() {
|
||||
|
||||
}
|
||||
|
||||
public Brake (float sliding, float radius, float area, float max_pressure, float bias) {
|
||||
_friction = sliding;
|
||||
_radius = radius;
|
||||
_area = area;
|
||||
_max_pressure = max_pressure * bias;
|
||||
_bias = bias;
|
||||
}
|
||||
|
||||
public float GetTorque(float factor, float rotational_speed) {
|
||||
// `factor' is the fraction of maximum pressure applied.
|
||||
float pressure = factor * _bias * _max_pressure;
|
||||
float normal = pressure * _area;
|
||||
float torque = _friction * normal * _radius;
|
||||
float velocity = _radius * rotational_speed;
|
||||
if(velocity < 0.0f)
|
||||
torque *= -1;
|
||||
|
||||
// See if the brake is locked.
|
||||
if(Mathf.Abs(velocity) < (_threshold * normal)) {
|
||||
_is_locked = true;
|
||||
torque = 0.0f;
|
||||
} else {
|
||||
_is_locked = false;
|
||||
}
|
||||
|
||||
return torque;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2696fc12f129fb43910ceeaa8bcea37
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,110 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[Serializable]
|
||||
public class IdleThrolleController
|
||||
{
|
||||
public double IdleSpeed;
|
||||
public double SpeedThreshold = 1.0;
|
||||
public double LagConstant = 1.0;
|
||||
public double IdleThrolle = 0.0;
|
||||
|
||||
public void Integrate(double dt, double speed)
|
||||
{
|
||||
var throlleDerivative = ((0.5f*(1.0 - Math.Tanh(4.0*(speed - IdleSpeed)/SpeedThreshold))) - IdleThrolle)/LagConstant;
|
||||
IdleThrolle += throlleDerivative * dt;
|
||||
}
|
||||
}
|
||||
|
||||
public class CarEngine : MonoBehaviour {
|
||||
public Flywheel flywheel;
|
||||
public int cylinderCount = 4;
|
||||
public float startRpm = 50;
|
||||
|
||||
public double inertia = 0.3f;
|
||||
public double inputInertia = 0.0;
|
||||
public double inputTorque = 0.0;
|
||||
|
||||
/*public abstract Curve TorqueCurve { get;}
|
||||
public abstract Curve FrictionCurve { get;}*/
|
||||
public float Weight = 100;
|
||||
|
||||
public Starter starter;
|
||||
|
||||
public double inputThrolle = 0.0f;
|
||||
public double engineThrolle = 0.0f;
|
||||
public IdleThrolleController idleThrolleController;
|
||||
public double crankshaftAngle = 0.0; //radians
|
||||
public double angularSpeed;
|
||||
public double angularSpeedRPM;
|
||||
public double k_Friction = 0.000003;
|
||||
|
||||
public Curve powerCurve;
|
||||
|
||||
public double k_FrictionTorque = 0.75f;
|
||||
public double kinematicFrictionTorque = 0;
|
||||
|
||||
public double Rpm
|
||||
{
|
||||
get { return angularSpeed * MathEx.RadSToRpm; }
|
||||
}
|
||||
|
||||
|
||||
/* private static KeyValuePair<int, float>[] _starterTable = new KeyValuePair<int, float>[]{
|
||||
new KeyValuePair<int, float>(2, 12.5f),
|
||||
new KeyValuePair<int, float>(4, 8.0f),
|
||||
new KeyValuePair<int, float>(6, 6.5f),
|
||||
new KeyValuePair<int, float>(8, 6.0f),
|
||||
new KeyValuePair<int, float>(12, 5.5f)
|
||||
};*/
|
||||
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
Integrate(Time.fixedDeltaTime);
|
||||
}
|
||||
|
||||
public void Integrate(double dt) {
|
||||
//do idle throlle
|
||||
idleThrolleController.Integrate(dt, Rpm);
|
||||
engineThrolle = Math.Max(inputThrolle, idleThrolleController.IdleThrolle);
|
||||
|
||||
//integrate angular acceleration and speed
|
||||
var angularDerivative = (GetTorque(engineThrolle, Rpm) - inputTorque) / (inertia + inputInertia);
|
||||
angularSpeed += angularDerivative * dt;
|
||||
|
||||
angularSpeedRPM = MathEx.RadSToRpm * angularSpeed;
|
||||
|
||||
//integrate angle
|
||||
crankshaftAngle += angularSpeed * dt;
|
||||
|
||||
kinematicFrictionTorque = (angularSpeedRPM/60.0)*k_FrictionTorque;
|
||||
}
|
||||
|
||||
public double GetTorque(double throlle, double rpm)
|
||||
{
|
||||
var t = GetTorque(rpm);
|
||||
t = t * throlle - k_Friction * rpm * rpm * (1.0 - throlle);
|
||||
return t;
|
||||
}
|
||||
|
||||
public double GetTorque(double rpm){
|
||||
if (powerCurve == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return powerCurve.Sample((float)rpm);
|
||||
}
|
||||
|
||||
public static float GetWatts(float torque, float rpm){
|
||||
return torque * rpm / 9549.0f;
|
||||
}
|
||||
|
||||
public static float GetHp(float torque, float rpm){
|
||||
return GetWatts(torque, rpm) * 1.36f;
|
||||
}
|
||||
|
||||
public bool Started = false;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84c8f10b9cc105c4d8c0f3565df12479
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class CarEngineDebug : MonoBehaviour{
|
||||
public CarEngine engine;
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
if (engine != null)
|
||||
{
|
||||
GUI.Label(new Rect(0, 10, 200, 30), "Engine RPM: " + engine.Rpm);
|
||||
}
|
||||
|
||||
if (GUI.Button(new Rect(0, 70, 100, 30), "Reset engine"))
|
||||
{
|
||||
engine.engineThrolle = 0.0548135214770327;
|
||||
engine.inputThrolle = 0;
|
||||
engine.angularSpeed = MathEx.RpmToRadS * 500;
|
||||
engine.angularSpeedRPM = MathEx.RadSToRpm * engine.angularSpeed;
|
||||
engine.crankshaftAngle = 0.0;
|
||||
engine.idleThrolleController.IdleThrolle = 0.0548135214770327;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a5446a43ae59804f8686e318dd3d03a
|
||||
timeCreated: 1453922163
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
[Serializable]
|
||||
public class CarWheelAxis {
|
||||
public Suspension leftWheel;
|
||||
public Suspension rightWheel;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cdc318b1a3403e40b45e62d9bd84067
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class Chassis : MonoBehaviour {
|
||||
public Suspension[] suspension;
|
||||
public CarWheelAxis[] axisCollection;
|
||||
|
||||
|
||||
public void Integrate(float dt, Car car){
|
||||
foreach(var s in suspension){
|
||||
s.Integrate(dt, car);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0f74529597105e4b93451888357b273
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,61 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class Differential : MonoBehaviour {
|
||||
|
||||
public float gearRatio = 3.5f;
|
||||
|
||||
public DriveShaft left;
|
||||
public DriveShaft right;
|
||||
public DriveShaft center;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
/*if (left != null) {
|
||||
left.target = this;
|
||||
}
|
||||
if (right != null) {
|
||||
right.target = this;
|
||||
}
|
||||
if (center != null) {
|
||||
center.target = this;
|
||||
}*/
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
|
||||
}
|
||||
/*
|
||||
void OnDrawGizmos(){
|
||||
AdvancedGizmo.DrawCircle (transform.position, Vector3.up, 0.2f, Color.green, 12, false, 1);
|
||||
|
||||
Gizmos.color = Color.red;
|
||||
if (left != null) {
|
||||
Gizmos.DrawLine(left.transform.position, gameObject.transform.position);
|
||||
}
|
||||
|
||||
if (right != null) {
|
||||
Gizmos.DrawLine(right.transform.position, gameObject.transform.position);
|
||||
}
|
||||
|
||||
if (center != null) {
|
||||
Gizmos.color = Color.blue;
|
||||
|
||||
Gizmos.DrawLine(center.transform.position, gameObject.transform.position);
|
||||
}
|
||||
|
||||
var pt = Tools.WorldToGuiPoint (transform.position);
|
||||
if (pt.z > 0) {
|
||||
Tools.BeginGui ();
|
||||
var textRect = new Rect (pt.x, pt.y, 100, 20);
|
||||
Tools.DrawRectangle(textRect, new Color(0,0,0,0.7f));
|
||||
GUI.Label (textRect, "Gear: " + gearRatio);
|
||||
|
||||
Tools.EndGui ();
|
||||
}
|
||||
|
||||
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7f2e113d7104154882152882f45afdd
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,57 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class DriveShaft : MonoBehaviour
|
||||
{
|
||||
public Transform endpoint0;
|
||||
public Transform endpoint1;
|
||||
|
||||
float inv_inertia;
|
||||
|
||||
public float Inv_inertia {
|
||||
get {
|
||||
return inv_inertia;
|
||||
}
|
||||
set {
|
||||
inv_inertia = value;
|
||||
}
|
||||
}
|
||||
|
||||
float ang_velocity;
|
||||
float angle;
|
||||
|
||||
public float Angle{
|
||||
get{return angle;}
|
||||
}
|
||||
|
||||
public float AngularVelocity{
|
||||
get{return ang_velocity;}
|
||||
set {
|
||||
ang_velocity = value;
|
||||
}
|
||||
}
|
||||
|
||||
public DriveShaft() {
|
||||
inv_inertia = 1;
|
||||
ang_velocity = 0;
|
||||
angle = 0;
|
||||
}
|
||||
|
||||
// amount of momentum to reach angular velocity
|
||||
public float GetMomentum(float angvel)
|
||||
{
|
||||
|
||||
return (angvel - ang_velocity) / inv_inertia;
|
||||
}
|
||||
|
||||
// update angular velocity
|
||||
public void ApplyMomentum(float momentum)
|
||||
{
|
||||
ang_velocity += inv_inertia * momentum;
|
||||
}
|
||||
|
||||
// update angle
|
||||
public void Integrate(float dt){
|
||||
angle += ang_velocity * dt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb743870935c8804bb18ddd60eeca428
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3a5c241b3709404b8e82672a96f1b12
|
||||
folderAsset: yes
|
||||
timeCreated: 1453140670
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class EnginePowerCurve : Curve
|
||||
{
|
||||
public float maxPower = 150000; //in Watts
|
||||
public float rpmAtMaxPower = 8000;
|
||||
|
||||
public float k_p1 = 1;
|
||||
public float k_p2 = 1;
|
||||
public float k_p3 = 1;
|
||||
|
||||
public override float Sample(float arg) {
|
||||
var o_max = rpmAtMaxPower;
|
||||
double o_e = arg;
|
||||
|
||||
var p = new double[4];
|
||||
p[0] = 0;
|
||||
p[1] = maxPower / o_max * k_p1;
|
||||
p[2] = maxPower / (o_max * o_max) * k_p2;
|
||||
p[3] = -maxPower / (o_max * o_max * o_max) * k_p3;
|
||||
|
||||
double Pe = 0.0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
Pe += p[i] * Math.Pow(o_e, i);
|
||||
}
|
||||
|
||||
var t = MathEx.Torque(Pe, MathEx.RpmToRadS * (arg + 0.000001));
|
||||
return (float)t;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 242e7bc229da7d840be56306cd243fc1
|
||||
timeCreated: 1454257928
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class Flywheel : MonoBehaviour
|
||||
{
|
||||
public uint teethCount = 129;
|
||||
public float mass = 6.6f;
|
||||
public float radius = 0.14f;
|
||||
public float inertia = 0.06468f;
|
||||
|
||||
[ContextMenu("Calculate inertia")]
|
||||
void CalcInertia()
|
||||
{
|
||||
inertia = (mass*radius*radius)*0.5f;
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d20f72f97cc2b864389b190cb34b1d47
|
||||
timeCreated: 1454252724
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public enum GearboxControlType{
|
||||
Manual,
|
||||
Automatic
|
||||
}
|
||||
|
||||
public abstract class Gearbox : MonoBehaviour {
|
||||
public abstract GearboxControlType ControlType{ get;}
|
||||
public abstract float MaxOutputTorque{ get;}
|
||||
public abstract int GearsCount{ get;}
|
||||
public abstract float GetGearRatio(int gear);
|
||||
public abstract int Gear{ get; set;}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47ea6b7730855674fba79ad64b9691a1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,34 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class PacejkaParameters : MonoBehaviour {
|
||||
|
||||
|
||||
[ContextMenuItem("Reset coeffs", "resetPacejkaCoeffs")]
|
||||
public PacejkaCoeffs _coeffs = new PacejkaCoeffs();
|
||||
|
||||
[ContextMenuItem("Reset coeffs2", "resetPacejkaCoeffs2")]
|
||||
public PacejkaCoeffs2 _coeffs2;
|
||||
|
||||
public double minLoad = 0;
|
||||
public double maxLoad = 8900;
|
||||
|
||||
|
||||
private void resetPacejkaCoeffs() {
|
||||
_coeffs = new PacejkaCoeffs();
|
||||
}
|
||||
|
||||
private void resetPacejkaCoeffs2() {
|
||||
_coeffs2 = new PacejkaCoeffs2();
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb98de270c82d434c8c66084fdbf89af
|
||||
timeCreated: 1453140700
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,109 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class SimpleSteerController : SteerController {
|
||||
private float _steer;
|
||||
public float maxSteerAngle = 30.0f;
|
||||
|
||||
public WheelPhysics frontLeftWheel;
|
||||
public WheelPhysics frontRightWheel;
|
||||
public WheelPhysics rearLeftWheel;
|
||||
public WheelPhysics rearRightWheel;
|
||||
|
||||
private Vector3 frontLeftStartAngle;
|
||||
private Vector3 frontRightStartAngle;
|
||||
|
||||
public SteeringWheel steeringWheel;
|
||||
|
||||
public override float Steer {
|
||||
get {
|
||||
return _steer;
|
||||
}
|
||||
set {
|
||||
_steer = Mathf.Clamp(value, -1.0f, 1.0f);
|
||||
UpdateWheelAngles();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateWheelAngles(){
|
||||
float d = (frontRightWheel.transform.position - frontLeftWheel.transform.position).magnitude;
|
||||
float l = (frontRightWheel.transform.position - rearRightWheel.transform.position).magnitude;
|
||||
float innerAngle = maxSteerAngle * _steer;
|
||||
float outerAngle = OuterWheelAngle (innerAngle, d, l);
|
||||
|
||||
if (_steer < 0.0f) {
|
||||
UpdateWheelSteering (frontLeftWheel, frontLeftStartAngle, innerAngle);
|
||||
UpdateWheelSteering (frontRightWheel, frontRightStartAngle, outerAngle);
|
||||
} else {
|
||||
UpdateWheelSteering (frontRightWheel, frontRightStartAngle, innerAngle);
|
||||
UpdateWheelSteering (frontLeftWheel, frontLeftStartAngle, outerAngle);
|
||||
}
|
||||
|
||||
steeringWheel.SetAngle(steeringWheel.degrees*0.5f*_steer);
|
||||
}
|
||||
|
||||
void UpdateWheelSteering(WheelPhysics wheel, Vector3 initialAngles, float steerAngle){
|
||||
initialAngles.y += steerAngle;
|
||||
wheel.transform.localEulerAngles = initialAngles;
|
||||
}
|
||||
|
||||
public static float OuterWheelAngle(float innerDegree, float d, float l){
|
||||
float sign = Mathf.Sign (innerDegree);
|
||||
float rad = Mathf.Deg2Rad * innerDegree * sign;
|
||||
float ctgB = Mathf.Cos (rad) / Mathf.Sin (rad);
|
||||
return Arcctg (ctgB + d / l) * Mathf.Rad2Deg * sign;
|
||||
}
|
||||
|
||||
static float Arcctg(float x){
|
||||
return Mathf.PI / 2.0f - Mathf.Atan (x);
|
||||
}
|
||||
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
frontLeftStartAngle = frontLeftWheel.transform.localEulerAngles;
|
||||
frontRightStartAngle = frontRightWheel.transform.localEulerAngles;
|
||||
}
|
||||
|
||||
void OnGUI(){
|
||||
Steer = GUI.HorizontalSlider (new Rect (10, 10, 300, 20), Steer, -1, 1);
|
||||
}
|
||||
|
||||
public float testSteerSpeed = 20.0f;
|
||||
|
||||
public float torque = 1000;
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
float finalTorque = Input.GetKey(KeyCode.W) ? torque : (Input.GetKey(KeyCode.S) ? -torque : 0);
|
||||
frontLeftWheel.driveTorque = finalTorque;
|
||||
frontRightWheel.driveTorque = finalTorque;
|
||||
|
||||
|
||||
double breakTorque = 0;
|
||||
if (Input.GetKey(KeyCode.Space))
|
||||
{
|
||||
breakTorque = 1600;
|
||||
}
|
||||
|
||||
frontLeftWheel.brakeTorque = breakTorque;
|
||||
frontRightWheel.brakeTorque = breakTorque;
|
||||
rearLeftWheel.brakeTorque = breakTorque;
|
||||
rearRightWheel.brakeTorque = breakTorque;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
float steerDelta = testSteerSpeed * Time.fixedDeltaTime;
|
||||
if (Input.GetKey (KeyCode.D)) {
|
||||
Steer += steerDelta;
|
||||
}
|
||||
if (Input.GetKey (KeyCode.A)) {
|
||||
Steer -= steerDelta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ff6449b097dd764d99cf320db63ebce
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,33 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class SimpleSuspension : Suspension {
|
||||
private Quaternion _startupRotation;
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
_startupRotation = transform.localRotation;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
public override void OnSteerChanged()
|
||||
{
|
||||
transform.localRotation = _startupRotation * Quaternion.AngleAxis((float)Steer, Vector3.up);
|
||||
}
|
||||
|
||||
void OnDrawGizmos(){
|
||||
var up = transform.up;
|
||||
var center = transform.position;
|
||||
Gizmos.DrawLine(center + up * (float)((1.0 - suspensionTarget) * travelDistance), center - up * (float)(suspensionTarget* travelDistance));
|
||||
|
||||
bool front = wheel.name[wheel.name.Length - 2] == 'f';
|
||||
Vector3 vOffset = front ? Vector3.up : Vector3.up * 0.5f;
|
||||
|
||||
Gizmos.DrawLine(dbgWheelForcePos + vOffset, dbgWheelForcePos + dbgWheelForce + vOffset);
|
||||
|
||||
Gizmos.DrawLine(dbgWheelForcePos + vOffset, dbgWheelForcePos);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d16ee8693777b14b952662a59be4ad7
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,7 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public abstract class SteerController : MonoBehaviour {
|
||||
|
||||
public abstract float Steer{ get; set; }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd8405aff4937ff4e948598fa5c04f53
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,142 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public abstract class Suspension : MonoBehaviour {
|
||||
|
||||
private double _steer;
|
||||
protected double _normalForce;
|
||||
public WheelPhysics wheel;
|
||||
public double travelDistance = 0.2f;
|
||||
public double suspensionTarget = 0.2f;
|
||||
private double _displacement;
|
||||
protected double _previousFraction;
|
||||
private double _overtravel;
|
||||
private double _lastDisplacement;
|
||||
public double springForce = 9000;
|
||||
public double springDamping = 400;
|
||||
|
||||
public double Steer{
|
||||
get{return _steer;}
|
||||
set
|
||||
{
|
||||
_steer = value;
|
||||
OnSteerChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnSteerChanged() {
|
||||
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
public double Displacement {
|
||||
get{return _displacement;}
|
||||
set{
|
||||
_lastDisplacement = _displacement;
|
||||
_displacement = MathEx.Clamp(value, 0, travelDistance);
|
||||
_overtravel = value - travelDistance;
|
||||
if(_overtravel < 0){
|
||||
_overtravel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CalculateForce(double dt){
|
||||
double velocity = ((_displacement - _lastDisplacement) / travelDistance) / dt;
|
||||
double spring = (_displacement / travelDistance) * springForce;
|
||||
double damping = velocity * springDamping;
|
||||
_normalForce = damping + spring;
|
||||
}
|
||||
|
||||
|
||||
double computeImpulseDenominator(Vector3 pos, Vector3 normal, Rigidbody rb){
|
||||
Vector3 r0 = pos - rb.worldCenterOfMass;
|
||||
Vector3 c0 = Vector3.Cross(r0, normal);
|
||||
|
||||
|
||||
var tensorLocal = Matrix4x4.TRS(rb.worldCenterOfMass, rb.inertiaTensorRotation, rb.inertiaTensor);
|
||||
var tensorWorld = transform.localToWorldMatrix * tensorLocal;
|
||||
tensorWorld = Matrix4x4.Inverse(tensorWorld);
|
||||
Vector3 vec = Vector3.Cross(tensorWorld.MultiplyPoint(c0), r0);
|
||||
|
||||
return 1.0f / rb.mass + Vector3.Dot(normal, vec);
|
||||
}
|
||||
|
||||
protected Vector3 dbgWheelForce;
|
||||
protected Vector3 dbgWheelForcePos;
|
||||
|
||||
public void Integrate(double dt, Car car){
|
||||
if(wheel != null){
|
||||
//var rb = car.GetRigidBody();
|
||||
|
||||
//raycast wheel
|
||||
wheel.UpdateContactPoint(car.transform.up);
|
||||
double fraction;
|
||||
double relativeDisplacement = wheel.TotalWheelRadius - wheel.Contact.hit.distance;
|
||||
Displacement += relativeDisplacement;
|
||||
|
||||
fraction = _displacement / travelDistance;
|
||||
CalculateForce(dt);
|
||||
|
||||
var wheelWorldVelocity = car.GetRigidBody().GetPointVelocity(wheel.transform.position);
|
||||
|
||||
if (_overtravel > 0)
|
||||
{
|
||||
double correction_factor = 0.0f;
|
||||
double dv = Vector3.Dot(wheelWorldVelocity, transform.up);// body->getVelocityInLocalPoint(suspension_force_application_point).dot(forcedirection);
|
||||
dv -= correction_factor * _overtravel / dt;
|
||||
// double effectiveMass = 1.0 / computeImpulseDenominator(wheel.transform.position, transform.up, car.GetRigidBody());//1.0 / body->computeImpulseDenominator(wheel_position[i], forcedirection);
|
||||
// double correction = -effectiveMass * dv / dt;
|
||||
/*if (correction > 0)
|
||||
{
|
||||
_normalForce = correction;
|
||||
}*/
|
||||
}
|
||||
|
||||
if(!wheel.Contact.hasHit) {
|
||||
_normalForce = 0;
|
||||
}
|
||||
|
||||
if(_normalForce > 0.0f){
|
||||
car.GetRigidBody().AddForceAtPosition(wheel.Contact.hit.normal * (float)_normalForce, transform.position);
|
||||
}
|
||||
|
||||
wheel.transform.position = GetWheelPosition(fraction);
|
||||
|
||||
Vector3 wheelForce;
|
||||
wheel.Integrate(dt, wheelWorldVelocity, _normalForce, out wheelForce);
|
||||
car.GetRigidBody().AddForceAtPosition(wheelForce, wheel.transform.position);
|
||||
|
||||
dbgWheelForce = wheelForce;
|
||||
dbgWheelForcePos = wheel.transform.position;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void CalculateSuspensionForce(double dt, double fraction) {
|
||||
_normalForce = springForce * (suspensionTarget - fraction) + springDamping * (_previousFraction - fraction) / dt;
|
||||
_previousFraction = fraction;
|
||||
}
|
||||
|
||||
public Vector3 GetWheelPosition(double fraction) {
|
||||
var up = transform.up;
|
||||
var center = transform.position;
|
||||
var top = center + up * (float)((1.0 - suspensionTarget) * travelDistance);
|
||||
var bottom = center - up * (float)(suspensionTarget * travelDistance);
|
||||
|
||||
return bottom + (top - bottom) * Mathf.Clamp01((float)fraction);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
/* */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd4c241e105bc7144a70f4d5e141b4bb
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,150 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class Tyre : MonoBehaviour {
|
||||
public double height = 0.15f;
|
||||
public double k_RollLinear = 0.0038;
|
||||
public double k_RollQuad = 0.000026;
|
||||
|
||||
public double GetRollingResistance(double Fz, double wheelEffectiveRadius, double velocity, double resistanceFactor) {
|
||||
return Fz * wheelEffectiveRadius * resistanceFactor * (k_RollLinear + k_RollQuad * (velocity )) * Math.Sign(velocity);
|
||||
}
|
||||
|
||||
private double oldLatSlip;
|
||||
public double latFilter = 0.85f;
|
||||
|
||||
|
||||
public PacejkaParameters pacejkaParams;
|
||||
|
||||
|
||||
|
||||
/* public void Slip(double patch_speed, Vector3 hub_velocity, out double slipLon, out double slipLat) {
|
||||
var absLongVelocity = (double)Mathf.Abs(hub_velocity.z);
|
||||
absLongVelocity = Math.Max(absLongVelocity, dampAbsRoadVelo);
|
||||
slipLon = CalcSlipRatio(patch_speed, hub_velocity) * 100.0f;
|
||||
slipLat = (Mathf.Atan2(hub_velocity.x, (float)absLongVelocity)) * Mathf.Rad2Deg;
|
||||
}
|
||||
|
||||
public Double3 FrictionForce(double normalForce, double slipLon, double slipLat, double camber, PacejkaCoeffs coeffs) {
|
||||
if(normalForce < 1e-4f) { return Double3.zero; }
|
||||
|
||||
normalForce = MathEx.Clamp(normalForce, 0, 100000);
|
||||
|
||||
//compute Pacejka params
|
||||
var lateralParams = Pacejka.LateralParams(normalForce, camber, coeffs);
|
||||
var longitudinalParams = Pacejka.LongitudinalParams(normalForce, coeffs);
|
||||
var aligningParams = Pacejka.AligningParams(normalForce, camber, coeffs);
|
||||
|
||||
//compute friction forces
|
||||
Double3 result;
|
||||
result.x = Pacejka.MagicFormula(slipLon, longitudinalParams);
|
||||
result.y = Pacejka.MagicFormula(slipLat, lateralParams);
|
||||
result.z = Pacejka.MagicFormula(slipLat, aligningParams);
|
||||
|
||||
/* //do combined friction
|
||||
double d_lon = slipLon / (1.0 + slipLon);
|
||||
double d_lat = Math.Tan(slipLat) / (1.0 + slipLon);
|
||||
double d = Math.Sqrt(d_lat * d_lat + d_lon * d_lon);
|
||||
|
||||
if(d > 0.001) {
|
||||
result.x *= (float)Math.Abs(d_lon / d);
|
||||
result.y *= (float)Math.Abs(d_lat / d);
|
||||
}*/
|
||||
// return result;
|
||||
// }
|
||||
|
||||
|
||||
void OnValidate() {
|
||||
if(enabled) {
|
||||
if(transform.parent != null && gameObject.activeInHierarchy)
|
||||
{
|
||||
SceneView.RepaintAll();
|
||||
// transform.parent.gameObject.SendMessage("OnValidate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SAE950311 implementation
|
||||
// private double lastU;
|
||||
// private double signU = 1;
|
||||
//private double oldSlip = 0;
|
||||
// public double tau;
|
||||
// public double B = 0.091f;//relaxationLengthLong
|
||||
public double relaxLong = 0.00172688486f;
|
||||
// private double _integratedSlip;
|
||||
public double speedThreshold = 3.0f;
|
||||
public double dampAbsRoadVelo = 1;
|
||||
public double kBLong = 0.35f;
|
||||
|
||||
public double fixedTimeBase = 0.02f;
|
||||
|
||||
|
||||
public double CalcSlipRatio(double patch_speed, Vector3 hub_velocity) {
|
||||
bool IsOnSurface = true;
|
||||
if(!IsOnSurface) {
|
||||
// _integratedSlip = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* double deltaTime = Time.fixedDeltaTime;
|
||||
double dampSRreversal = 0.5f;
|
||||
double B = relaxLong*100;
|
||||
double fixedTimeStepScalar = fixedTimeBase / Time.fixedDeltaTime;
|
||||
double invFixedTimeStepScalar = 1.0f / fixedTimeStepScalar;
|
||||
|
||||
if(B < kBLong * invFixedTimeStepScalar)
|
||||
B = kBLong * invFixedTimeStepScalar;
|
||||
|
||||
// damp sliAngle and slipRatio oscilation
|
||||
|
||||
|
||||
double factor = hub_velocity.z * 3.6f * 0.02f; // divided by 50
|
||||
if(factor < 1)
|
||||
factor = 1;
|
||||
B *= factor;
|
||||
*/
|
||||
|
||||
// SAE950311 algorithm
|
||||
|
||||
var longVelocity = (double)hub_velocity.z;
|
||||
// var absLongVelocity = Math.Abs(longVelocity);
|
||||
|
||||
|
||||
|
||||
if (Math.Abs(longVelocity - patch_speed) > 1.0e-4)
|
||||
{
|
||||
double denom = Math.Max(Math.Abs(longVelocity), dampAbsRoadVelo);
|
||||
return MathEx.Clamp((patch_speed - longVelocity)/denom, -1.0, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
absLongVelocity = Math.Max(absLongVelocity, dampAbsRoadVelo);
|
||||
|
||||
|
||||
|
||||
|
||||
if((lastU < 0 && longVelocity >= 0) || (lastU >= 0 && longVelocity < 0)) {
|
||||
_integratedSlip = -dampSRreversal * _integratedSlip;
|
||||
}
|
||||
|
||||
lastU = Math.Sign(longVelocity);
|
||||
|
||||
double derivative = (patch_speed - longVelocity) - absLongVelocity * _integratedSlip;
|
||||
derivative /= B;
|
||||
|
||||
// Integrate
|
||||
_integratedSlip += derivative * deltaTime;
|
||||
|
||||
return MathEx.Clamp(_integratedSlip + tau * derivative, -1.5, 1.5);*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70404261169dc6f498752a2108433b55
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class Wheel : MonoBehaviour {
|
||||
|
||||
public Tyre tyre;
|
||||
public Brake brake;
|
||||
|
||||
public DriveShaft _shaft;
|
||||
|
||||
public float discRadius = 0.385f; //15 inch by default
|
||||
private float _totalWheelRadius;
|
||||
|
||||
public float TotalWheelRadius {
|
||||
get {
|
||||
return _totalWheelRadius;
|
||||
}
|
||||
}
|
||||
|
||||
public float _slipLon;
|
||||
public float _slipLat;
|
||||
private Vector3 _localVelocity;
|
||||
private Vector3 _friction;
|
||||
private Vector3 _peakSlip;
|
||||
public float camber;
|
||||
public bool DrawDebug = true;
|
||||
public float weight = 50;
|
||||
|
||||
public float driveTorque = 0.0f;
|
||||
public float brakeTorque = 0.0f;
|
||||
|
||||
|
||||
public float brakingState = 0.0f;
|
||||
private WheelContact _contact;
|
||||
public Oscilloscope oscilloscope;
|
||||
private int t;
|
||||
|
||||
public bool Grounded {
|
||||
get {
|
||||
return _contact.grounded;
|
||||
}
|
||||
}
|
||||
|
||||
public WheelContact Contact {
|
||||
get {
|
||||
return _contact;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[ContextMenuItem("Reset coeffs", "resetPacejkaCoeffs")]
|
||||
public PacejkaCoeffs _coeffs = new PacejkaCoeffs();
|
||||
|
||||
public float dtMul = 1;
|
||||
|
||||
private void resetPacejkaCoeffs() {
|
||||
_coeffs = new PacejkaCoeffs();
|
||||
}
|
||||
|
||||
public float AngularVelocity {
|
||||
get { return _shaft.AngularVelocity; }
|
||||
set {
|
||||
_shaft.AngularVelocity = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
InitWheel();
|
||||
float normalForce = 3.210758f * 1000.0f;
|
||||
var lateralParams = Pacejka.LateralParams(normalForce, 0, _coeffs);
|
||||
var longitudinalParams = Pacejka.LongitudinalParams(normalForce, _coeffs);
|
||||
var aligningParams = Pacejka.AligningParams(normalForce, 0, _coeffs);
|
||||
|
||||
_peakSlip.x = Pacejka.Extremum(longitudinalParams);
|
||||
_peakSlip.y = Pacejka.Extremum(lateralParams);
|
||||
_peakSlip.z = Pacejka.Extremum(aligningParams);
|
||||
|
||||
if(oscilloscope != null)
|
||||
{
|
||||
oscilloscope.channels[0].sampler = Sampler0;
|
||||
oscilloscope.channels[1].sampler = Sampler1;
|
||||
oscilloscope.channels[2].sampler = Sampler2;
|
||||
}
|
||||
}
|
||||
|
||||
float Sampler0()
|
||||
{
|
||||
return _slipLat;
|
||||
}
|
||||
|
||||
float Sampler1()
|
||||
{
|
||||
return localVelocity.x;
|
||||
}
|
||||
|
||||
float Sampler2()
|
||||
{
|
||||
return 0;//Mathf.Repeat(_shaft.Angle, Mathf.PI * 2);
|
||||
}
|
||||
|
||||
float Inertia{
|
||||
get{return 1.0f / _shaft.Inv_inertia;}
|
||||
set{_shaft.Inv_inertia = 1.0f / value;}
|
||||
}
|
||||
|
||||
void InitWheel() {
|
||||
if (_shaft == null) {
|
||||
_shaft = new DriveShaft();
|
||||
}
|
||||
|
||||
|
||||
if (tyre != null) {
|
||||
_totalWheelRadius = discRadius + tyre.height;
|
||||
}
|
||||
|
||||
Inertia = weight*_totalWheelRadius*_totalWheelRadius*0.5f;
|
||||
|
||||
}
|
||||
void OnValidate() {
|
||||
InitWheel();
|
||||
}
|
||||
|
||||
|
||||
public void SetBraking(float amount) {
|
||||
brakingState = Mathf.Clamp01(amount);
|
||||
|
||||
}
|
||||
|
||||
void SetTorque(float torque, float dt) {
|
||||
_shaft.ApplyMomentum(torque * dt);
|
||||
}
|
||||
|
||||
|
||||
void OnDrawGizmosSelected() {
|
||||
if (!DrawDebug) {
|
||||
return;
|
||||
}
|
||||
var p = _coeffs;
|
||||
|
||||
Curve[] curves = new Curve[]{new Curve(), new Curve(), new Curve()};
|
||||
|
||||
int sampleCnt = 250;
|
||||
float minArg = -100;
|
||||
float maxArg = 100;
|
||||
float argDiff = maxArg - minArg;
|
||||
|
||||
for (int i = 0; i < sampleCnt; ++i) {
|
||||
var arg = minArg + argDiff / ((float)sampleCnt - 1) * i;
|
||||
curves[0].AddArg(arg);
|
||||
curves[1].AddArg(arg);
|
||||
curves[2].AddArg(arg);
|
||||
|
||||
curves[0].AddVal(Pacejka.LongitudinalForce (5000.0f, arg, p));
|
||||
curves[1].AddVal(Pacejka.LateralForce (5000.0f, camber, arg, p));
|
||||
curves[2].AddVal(Pacejka.AligningForce (5000.0f, camber, arg, p));
|
||||
}
|
||||
|
||||
float maxSlip = MathEx.FindExtremumValue(x => Pacejka.LongitudinalForce(5000.0f, x, p), 0, 100, 0.5f);
|
||||
|
||||
Tools.BeginGui ();
|
||||
|
||||
GUI.Label(new Rect(20,30,300,100), "Maximum wheel slip: " + maxSlip + " Value at that slip: " + Pacejka.LongitudinalForce(5000.0f, maxSlip, p));
|
||||
Plot2D plot = new Plot2D(curves[0]);
|
||||
|
||||
plot.Title = "Longitudinal friction";
|
||||
plot.OnGUI(new Rect(90,100,500,400));
|
||||
|
||||
camber = GUI.HorizontalSlider (new Rect (10, 10, 100, 10), camber, -10, 10);
|
||||
Tools.EndGui ();
|
||||
}
|
||||
|
||||
float GetTorque(float new_angvel, float dt) {
|
||||
return _shaft.GetMomentum(new_angvel) / dt;
|
||||
}
|
||||
|
||||
|
||||
private float roll_resistance_lin = 0.00001f;
|
||||
private float roll_resistance_quad = 0.00001f;
|
||||
float getRollingResistance(
|
||||
float velocity,
|
||||
float resistance_factor)
|
||||
{
|
||||
// surface influence on rolling resistance
|
||||
float rolling_resistance = resistance_factor * roll_resistance_lin;
|
||||
|
||||
// heat due to tire deformation increases rolling resistance
|
||||
// approximate by quadratic function
|
||||
rolling_resistance += velocity * velocity * roll_resistance_quad;
|
||||
|
||||
// rolling resistance direction
|
||||
float resistance = -rolling_resistance;
|
||||
if (velocity < 0) resistance = -resistance;
|
||||
|
||||
return resistance;
|
||||
}
|
||||
|
||||
|
||||
public void UpdateContactPoint(Vector3 up){
|
||||
var raycastRay = new Ray (transform.position, -up);
|
||||
|
||||
_contact.hasHit = false;
|
||||
_contact.grounded = false;
|
||||
if (Physics.Raycast (raycastRay, out _contact.hit)) {
|
||||
_contact.hasHit = true;
|
||||
if(_contact.hit.distance <= _totalWheelRadius){
|
||||
_contact.grounded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int pp = 0;
|
||||
private Vector3 lonForce;
|
||||
private Vector3 latForce;
|
||||
private float wheel_torque;
|
||||
public float dampOsc = 0.85f;
|
||||
public float fixedTimeBase = 0.02f;
|
||||
private Vector3 localVelocity;
|
||||
|
||||
public void Integrate(float dt, Vector3 wheelWorldVelocity, float normal_force, out Vector3 force)
|
||||
{
|
||||
//normal_force = 5000.0f;
|
||||
float wheel_drive_torque = driveTorque;
|
||||
float patch_speed = AngularVelocity * _totalWheelRadius;
|
||||
localVelocity = transform.InverseTransformDirection(wheelWorldVelocity);
|
||||
|
||||
tyre.Slip(patch_speed, localVelocity, out _slipLon, out _slipLat);
|
||||
|
||||
Vector3 friction_force = tyre.FrictionForce(normal_force, _slipLon, _slipLat, 0, _coeffs);
|
||||
|
||||
lonForce = transform.forward * friction_force[0];
|
||||
latForce = -transform.right * friction_force[1];
|
||||
|
||||
Vector3 tire_force = lonForce + latForce;
|
||||
|
||||
float tire_friction_torque = friction_force[0] * _totalWheelRadius;
|
||||
|
||||
//calculate brake torque
|
||||
float wheel_lock_torque = -AngularVelocity / dt * Inertia;
|
||||
float wheel_brake_torque = wheel_lock_torque - wheel_drive_torque + tire_friction_torque;
|
||||
float maxBreakTorque = brakeTorque;
|
||||
if (wheel_brake_torque > 0 && wheel_brake_torque > maxBreakTorque)
|
||||
{
|
||||
wheel_brake_torque = maxBreakTorque;
|
||||
}
|
||||
else if (wheel_brake_torque < 0 && wheel_brake_torque < -maxBreakTorque)
|
||||
{
|
||||
wheel_brake_torque = -maxBreakTorque;
|
||||
}
|
||||
|
||||
//limit the reaction torque to the applied drive and braking torque
|
||||
float reaction_torque = tire_friction_torque;
|
||||
float applied_torque = wheel_drive_torque + wheel_brake_torque;
|
||||
if ( ( applied_torque > 0 && reaction_torque > applied_torque ) ||
|
||||
( applied_torque < 0 && reaction_torque < applied_torque ) )
|
||||
reaction_torque = applied_torque;
|
||||
Vector3 tire_torque = Vector3.right * reaction_torque;// - direction::up * friction_force[2];
|
||||
|
||||
//set wheel torque due to tire rolling resistance
|
||||
float rollResistanceCoefficient = 0;
|
||||
float rolling_resistance = getRollingResistance(AngularVelocity, rollResistanceCoefficient);
|
||||
float rolling_resistance_torque = rolling_resistance * _totalWheelRadius - tire_friction_torque;
|
||||
|
||||
|
||||
wheel_torque = wheel_drive_torque + wheel_brake_torque + rolling_resistance_torque;
|
||||
|
||||
//have the wheels internally apply forces, or just forcibly set the wheel speed if the brakes are locked
|
||||
|
||||
float oldAngularVelocity = AngularVelocity;
|
||||
SetTorque(wheel_torque, dt);
|
||||
|
||||
/ *float fixedTimeStepScalar = fixedTimeBase / Time.fixedDeltaTime;
|
||||
float invFixedTimeStepScalar = 1.0f / fixedTimeStepScalar;
|
||||
|
||||
// damp low speed wheel oscillations
|
||||
float deltaAngularVelocity = AngularVelocity - oldAngularVelocity;
|
||||
float delta = deltaAngularVelocity * dampOsc * Mathf.Clamp01(invFixedTimeStepScalar);
|
||||
AngularVelocity -= delta;* /
|
||||
|
||||
_shaft.Integrate(dt);
|
||||
|
||||
//viscous tire contact drag (hack)
|
||||
float rollingDrag = 0.0f;
|
||||
Vector3 wheel_drag = _localVelocity * rollingDrag;
|
||||
|
||||
|
||||
force = Vector3.zero;
|
||||
//apply forces to body
|
||||
// Vector3 tire_pos = wheel_position[i] - body->getCenterOfMassPosition();
|
||||
Vector3 world_tire_force = tire_force;
|
||||
//Vector3 world_tire_torque = quatRotate ( wheel_orientation[i], tire_torque);
|
||||
world_tire_force += wheel_drag;
|
||||
//world_tire_torque += tire_pos.cross(world_tire_force);
|
||||
force = world_tire_force;
|
||||
|
||||
|
||||
//torque = torque + world_tire_torque;
|
||||
}
|
||||
|
||||
float RPM
|
||||
{
|
||||
get {
|
||||
return _shaft.AngularVelocity * 30.0f / 3.1415926535f;
|
||||
}
|
||||
}
|
||||
|
||||
public DriveShaft Shaft {
|
||||
get {
|
||||
return _shaft;
|
||||
}
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
DrawLabels();
|
||||
}
|
||||
|
||||
void DrawLabels() {
|
||||
Label3D.AtWorldPosition(transform.position + Vector3.up * 1, "RPM: " + RPM);
|
||||
Label3D.AtWorldPosition(transform.position + Vector3.up * 1.3f, "F: " + _friction.x + " S: " + _slipLon);
|
||||
}
|
||||
|
||||
void OnDrawGizmos() {
|
||||
|
||||
if (tyre == null || _shaft == null) {
|
||||
return;
|
||||
}
|
||||
DrawLabels();
|
||||
var forward = transform.forward;
|
||||
var right = transform.right;
|
||||
|
||||
//draw wheel radius
|
||||
var wheelCenter = transform.position;
|
||||
var rollMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(_shaft.Angle * Mathf.Rad2Deg, right), Vector3.one);
|
||||
var radiusP0 = -forward * _totalWheelRadius;
|
||||
var radiusP1 = forward * _totalWheelRadius * 1.2f;
|
||||
radiusP0 = rollMatrix.MultiplyPoint3x4 (radiusP0);
|
||||
radiusP1 = rollMatrix.MultiplyPoint3x4 (radiusP1);
|
||||
Gizmos.DrawLine (wheelCenter + radiusP0, wheelCenter + radiusP1);
|
||||
|
||||
//draw wheel outer circle
|
||||
AdvancedGizmo.DrawCircle(wheelCenter, right, _totalWheelRadius, Color.green, 36);
|
||||
|
||||
//draw wheel inner circle
|
||||
AdvancedGizmo.DrawCircle(wheelCenter, right, discRadius, Color.green, 36);
|
||||
|
||||
//draw forces
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawLine(wheelCenter, wheelCenter + lonForce);
|
||||
|
||||
Gizmos.color = Color.green;
|
||||
Gizmos.DrawLine(wheelCenter, wheelCenter + latForce);
|
||||
|
||||
Gizmos.color = Color.blue;
|
||||
Gizmos.DrawLine(wheelCenter, wheelCenter + latForce + lonForce);
|
||||
|
||||
Gizmos.color = Color.black;
|
||||
Gizmos.DrawLine(wheelCenter, wheelCenter + forward * 100);
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0c7faf1940de454e9a95ef9e629f173
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,169 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Net.Security;
|
||||
using System;
|
||||
|
||||
public struct WheelContact {
|
||||
public RaycastHit hit;
|
||||
public bool hasHit;
|
||||
public bool grounded;
|
||||
}
|
||||
|
||||
public class WheelPhysics : MonoBehaviour {
|
||||
public Tyre tyre;
|
||||
public Brake brake;
|
||||
|
||||
public double driveTorque = 0.0f;
|
||||
public double brakeTorque = 0.0f;
|
||||
|
||||
public double angularVelocity; //rad/sec
|
||||
public double inertiaMomentum = 3.45f;
|
||||
public double angle; //radian
|
||||
|
||||
private WheelContact _contact;
|
||||
public bool Grounded {
|
||||
get {
|
||||
return _contact.grounded;
|
||||
}
|
||||
}
|
||||
|
||||
public double discRadius = 0.385f; //15 inch by default
|
||||
|
||||
public double TotalWheelRadius {
|
||||
get {
|
||||
return discRadius + tyre.height;
|
||||
}
|
||||
}
|
||||
|
||||
public WheelContact Contact {
|
||||
get {
|
||||
return _contact;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private double _slipLon;
|
||||
private double _slipLat;
|
||||
private Vector3 localVelocity;
|
||||
|
||||
private int t = 0;
|
||||
|
||||
public double reactionTorque;
|
||||
|
||||
public void Integrate(double dt, Vector3 wheelWorldVelocity, double normal_force, out Vector3 force) {
|
||||
|
||||
t++;
|
||||
localVelocity = transform.InverseTransformDirection(wheelWorldVelocity);
|
||||
double patchSpeed = angularVelocity * TotalWheelRadius;
|
||||
|
||||
|
||||
|
||||
// tyre.Slip(patchSpeed, localVelocity, out _slipLon, out _slipLat);
|
||||
|
||||
|
||||
var Vc = new Double3(localVelocity.z, localVelocity.x, localVelocity.y);
|
||||
|
||||
Double3 frictionForces = Pacejka.CalcPacejka(Vc, angularVelocity, TotalWheelRadius, TotalWheelRadius, normal_force, 0, tyre.pacejkaParams._coeffs2, true);
|
||||
frictionForces.y *= -1.0;
|
||||
// Double3 frictionForces = tyre.FrictionForce(normal_force, _slipLon, _slipLat, 0, tyre.pacejkaParams._coeffs);
|
||||
|
||||
/* if (name[name.Length - 2] == 'f' && t % 250 == 0) {
|
||||
Debug.LogFormat("Fz = {0} Fx = {1} Slip = {2} Vlon = {4} Name = {3}", normal_force, frictionForces.x, _slipLon, name, localVelocity.z);
|
||||
}*/
|
||||
|
||||
|
||||
double T_engine = driveTorque;
|
||||
double T_break = brakeTorque * -Math.Sign(angularVelocity);
|
||||
|
||||
double T_input = T_engine + T_break;
|
||||
|
||||
double T_reaction = frictionForces.x * TotalWheelRadius;
|
||||
|
||||
reactionTorque = T_reaction;
|
||||
/*if (T_input < 0 && (T_reaction < T_input) || (T_input > 0 && (T_reaction > T_input)))
|
||||
{
|
||||
T_reaction = T_input;
|
||||
}*/
|
||||
|
||||
|
||||
double T_rolling_resist = tyre.GetRollingResistance(normal_force, TotalWheelRadius, localVelocity.z, 1.0f);
|
||||
|
||||
double angularAcceleration = (T_engine - T_reaction + T_break - T_rolling_resist) /inertiaMomentum;
|
||||
angularVelocity += angularAcceleration * dt;
|
||||
//dw/dt = (T_engine + T_reaction - T_break - T_friction) / WheelInertia
|
||||
|
||||
angle += angularVelocity * dt;
|
||||
|
||||
Vector3 lonForce = transform.forward * (float)frictionForces.x;
|
||||
Vector3 latForce = -transform.right * (float)frictionForces.y;
|
||||
force = lonForce + latForce;
|
||||
}
|
||||
|
||||
public void UpdateContactPoint(Vector3 up) {
|
||||
var raycastRay = new Ray(transform.position, -up);
|
||||
|
||||
_contact.hasHit = false;
|
||||
_contact.grounded = false;
|
||||
if (Physics.Raycast(raycastRay, out _contact.hit)) {
|
||||
_contact.hasHit = true;
|
||||
if (_contact.hit.distance <= TotalWheelRadius) {
|
||||
_contact.grounded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OnDrawGizmos() {
|
||||
|
||||
if (tyre == null) {
|
||||
return;
|
||||
}
|
||||
//DrawLabels();
|
||||
var forward = transform.forward;
|
||||
var right = transform.right;
|
||||
|
||||
//draw wheel radius
|
||||
var wheelCenter = transform.position;
|
||||
//var rollMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(_shaft.Angle * Mathf.Rad2Deg, right), Vector3.one);
|
||||
var rollMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(0, right), Vector3.one);
|
||||
var radiusP0 = -forward * (float)TotalWheelRadius;
|
||||
var radiusP1 = forward * (float)(TotalWheelRadius * 1.2);
|
||||
radiusP0 = rollMatrix.MultiplyPoint3x4(radiusP0);
|
||||
radiusP1 = rollMatrix.MultiplyPoint3x4(radiusP1);
|
||||
Gizmos.DrawLine(wheelCenter + radiusP0, wheelCenter + radiusP1);
|
||||
|
||||
//draw wheel outer circle
|
||||
AdvancedGizmo.DrawCircle(wheelCenter, right, (float)TotalWheelRadius, Color.green, 36);
|
||||
|
||||
//draw wheel inner circle
|
||||
AdvancedGizmo.DrawCircle(wheelCenter, right, (float)discRadius, Color.green, 36);
|
||||
|
||||
//draw forces
|
||||
/*Gizmos.color = Color.red;
|
||||
Gizmos.DrawLine(wheelCenter, wheelCenter + lonForce);
|
||||
|
||||
Gizmos.color = Color.green;
|
||||
Gizmos.DrawLine(wheelCenter, wheelCenter + latForce);
|
||||
|
||||
Gizmos.color = Color.blue;
|
||||
Gizmos.DrawLine(wheelCenter, wheelCenter + latForce + lonForce);
|
||||
|
||||
Gizmos.color = Color.black;
|
||||
Gizmos.DrawLine(wheelCenter, wheelCenter + forward * 100);*/
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0f3b45c60aa04c4c9e0c48be7e96fa3
|
||||
timeCreated: 1453062224
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class CarDashboard : MonoBehaviour {
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de5d28a979b679246ababb0c34743987
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class CarDebug : MonoBehaviour {
|
||||
public bool showTorquePlot = true;
|
||||
public bool showHpPlot = true;
|
||||
|
||||
void OnDrawGizmosSelected(){
|
||||
if (enabled) {
|
||||
var car = GetComponent<Car> ();
|
||||
if (car != null) {
|
||||
if(car.engine != null){
|
||||
Handles.BeginGUI ();
|
||||
Handles.EndGUI ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a53750ffe9e631f479429fe502b35b00
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public enum PowerBusType{
|
||||
Acc = 0,
|
||||
On = 1
|
||||
}
|
||||
|
||||
public class CarElectricSystem : MonoBehaviour {
|
||||
|
||||
public IElecticEnergySource energySource;
|
||||
public IgnitionSystem ignition;
|
||||
private PowerBus[] _powerBus;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
//create electric power buses
|
||||
_powerBus = new PowerBus[]{new PowerBus(), new PowerBus()};
|
||||
foreach (var bus in _powerBus) {
|
||||
bus.ElectricSystem = this;
|
||||
}
|
||||
|
||||
//attach to ignition system
|
||||
if (ignition != null) {
|
||||
ignition.PowerBus = _powerBus [(int)PowerBusType.On];
|
||||
ignition.StateChanged += HandleIgnitionStateChanged;
|
||||
} else {
|
||||
Debug.LogWarning("Electric system: no ignition system attached");
|
||||
}
|
||||
}
|
||||
|
||||
void HandleIgnitionStateChanged (IgnitionSystem caller, IgnitionState oldState, IgnitionState newState){
|
||||
_powerBus [(int)PowerBusType.Acc].Enabled = newState != IgnitionState.Lock;
|
||||
_powerBus [(int)PowerBusType.On].Enabled = (newState != IgnitionState.Lock) && (newState != IgnitionState.Acc);
|
||||
}
|
||||
|
||||
public PowerBus GetPowerBus(PowerBusType busType){
|
||||
return _powerBus[(int)busType];
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45b7fc88ee501014cb568bf406af0b88
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,37 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class CarGUI : MonoBehaviour {
|
||||
private Car _car;
|
||||
private VerticalProgressBar _pedalBar;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
_car = GetComponent<Car> ();
|
||||
_pedalBar = new VerticalProgressBar ();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
void OnGUI(){
|
||||
if (_car != null) {
|
||||
var pedals = _car.Pedals;
|
||||
|
||||
Vector2 topLeft = new Vector2(100,400);
|
||||
Vector2 size = new Vector2(30,200);
|
||||
float margin = 10;
|
||||
|
||||
for(int i = 0; i < pedals.Length; ++i){
|
||||
var pedal = (CarPedal)i;
|
||||
if(pedals != null && pedals.Length > i && pedals[i] != null){
|
||||
_pedalBar.Value = pedals[i];
|
||||
_pedalBar.OnGUI(new Rect(topLeft.x + (size.x + margin) * i,topLeft.y,size.x,size.y));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e9ab79b375a83341bb9a72438364ee6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,57 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public interface IDevice {
|
||||
string Name { get; }
|
||||
string ShortDescription { get; }
|
||||
}
|
||||
|
||||
public interface IElectricDevice : IDevice {
|
||||
void SetPowerBus(PowerBus bus);
|
||||
bool On { get; set; }
|
||||
}
|
||||
|
||||
public abstract class IElecticEnergySource : MonoBehaviour, IDevice{
|
||||
public abstract float Voltage{ get; }
|
||||
public abstract float MaxPower{ get; }
|
||||
public abstract string Name{ get; }
|
||||
public abstract string ShortDescription{ get; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public interface IGear{
|
||||
float Direction{ get; }
|
||||
float Radius{ get; }
|
||||
float InternalStopMoment{ get; }
|
||||
float ExternalStopMoment{ get; set; }
|
||||
float Torque{ get; }
|
||||
float Rpm{ get; }
|
||||
}
|
||||
|
||||
public interface IMotor{
|
||||
|
||||
}
|
||||
|
||||
public class GearJoint{
|
||||
private IGear _a;
|
||||
private IGear _b;
|
||||
private float _ratio;
|
||||
|
||||
public GearJoint(IGear a, IGear b){
|
||||
_a = a;
|
||||
_b = b;
|
||||
_ratio = _a.Radius / _b.Radius;
|
||||
}
|
||||
|
||||
public void Solve(){
|
||||
//сначала обмениваемся стоп моментами чтобы понять есть ли преодолевшие его движки
|
||||
_b.ExternalStopMoment = (_a.InternalStopMoment / _ratio);
|
||||
_a.ExternalStopMoment = (_b.InternalStopMoment * _ratio);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 412239d2566c97c4b9f8222fd26b1205
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public static class CarMath {
|
||||
|
||||
public static float Drag(float environmentDensity, float velocity, float dragCoeff, float area){
|
||||
return 0.5f * environmentDensity * (velocity * velocity) * dragCoeff * area;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ad7d95a56657c14c884da9586f8b794
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class CarSuspension : MonoBehaviour {
|
||||
public float suspensionDistance = 0.2f;
|
||||
public float targetPosition = 0.2f;
|
||||
public float suspensionSpring = 35000.0f;
|
||||
public float suspensionDamper = 4500.0f;
|
||||
private float _suspensionForce;
|
||||
private float previousLength = 0.0f;
|
||||
private float currentLength = 0.0f;
|
||||
private float _currentSuspensionPosition = 1;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 462523a99a69aab48ac5f29cd7e52713
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,414 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
public class CarWheelHit{
|
||||
public Vector3 point;
|
||||
public Vector3 normal;
|
||||
}
|
||||
|
||||
public class CarWheelCollider : MonoBehaviour {
|
||||
public float wheelRadius = 0.33f;
|
||||
public float _steerAngle;
|
||||
|
||||
public bool DrawDebug = true;
|
||||
[ContextMenuItem("Reset coeffs", "resetPacejkaCoeffs")]
|
||||
public PacejkaCoeffs _coeffs = new PacejkaCoeffs();
|
||||
|
||||
|
||||
private Rigidbody _chassisRigidBody;
|
||||
*/
|
||||
/*private CarWheelHit _hit = new CarWheelHit();
|
||||
private bool _isGrounded;
|
||||
private Vector3 _relativePosition; //Relative to car body
|
||||
private Vector3 _velocity;
|
||||
private Vector3 _localVelocity;
|
||||
public float camber;
|
||||
private Vector3 _friction = new Vector3 ();
|
||||
public float _appliedTorque;
|
||||
private Vector2 _slip; //X = lateral, Y = longitudinal
|
||||
private Vector3 _peakSlip;
|
||||
private float _driveTorque;
|
||||
private float _breakTorque;*/
|
||||
|
||||
/*
|
||||
private DriveShaft _driveShaft = new DriveShaft();
|
||||
|
||||
|
||||
private void resetPacejkaCoeffs() {
|
||||
_coeffs = new PacejkaCoeffs();
|
||||
}
|
||||
*/
|
||||
|
||||
/*public float SteerAngle {
|
||||
get {
|
||||
return _steerAngle;
|
||||
}
|
||||
set {
|
||||
_steerAngle = value;
|
||||
}
|
||||
}*/
|
||||
|
||||
/*void SetTorque(float torque, float dt){
|
||||
_driveShaft.applyMomentum(torque * dt);
|
||||
}
|
||||
|
||||
float RPM{
|
||||
get{return _driveShaft.AngularVelocity * 30.0f / 3.141593f;}
|
||||
}
|
||||
|
||||
void Integrate(float dt){
|
||||
_driveShaft.integrate(dt);
|
||||
}
|
||||
|
||||
private void UpdateRelativePosition(){
|
||||
_relativePosition = _chassisRigidBody.transform.InverseTransformPoint (transform.position);
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
_chassisRigidBody = FindFirstParentRigidBody ();
|
||||
UpdateRelativePosition ();
|
||||
|
||||
|
||||
//_breakTorque = 10000;
|
||||
float tire_mass = 4.0f;
|
||||
float rim_mass = 15.0f;
|
||||
float rim_radius = 0.331f;
|
||||
float tire_radius = 0.556f;
|
||||
|
||||
float tire_inertia = tire_mass * tire_radius * tire_radius;
|
||||
float rim_inertia = rim_mass * rim_radius * rim_radius;
|
||||
SetInertia(tire_inertia + rim_inertia);
|
||||
}
|
||||
|
||||
void SetInertia(float value)
|
||||
{
|
||||
_driveShaft.Inv_inertia = 1.0f / value;
|
||||
}
|
||||
|
||||
private void UpdateSlipAngles(){
|
||||
_localVelocity = transform.InverseTransformDirection (_velocity);
|
||||
Quaternion q = Quaternion.AngleAxis (-SteerAngle, transform.up);
|
||||
var trs = Matrix4x4.TRS (Vector3.zero, q, Vector3.one);
|
||||
_localVelocity = trs.MultiplyPoint3x4 (_localVelocity);
|
||||
|
||||
float rot_velocity = AngularVelocity * wheelRadius;
|
||||
float lon_velocity = _localVelocity.z;
|
||||
float lat_velocity = _localVelocity.x;
|
||||
float lon_slip_velocity = lon_velocity - rot_velocity;
|
||||
|
||||
if (Mathf.Abs (lon_slip_velocity) <= 1.0e-4f)
|
||||
{
|
||||
_slip = Vector2.zero;
|
||||
return;
|
||||
}
|
||||
|
||||
float denom = Mathf.Max(Mathf.Abs(lon_velocity), 1e-0f);
|
||||
_slip.x = -lon_slip_velocity / denom;
|
||||
_slip.y = Mathf.Atan(lat_velocity / denom);
|
||||
}
|
||||
|
||||
private void UpdateFriction(){
|
||||
float surfaceFriction = 0.9f;
|
||||
|
||||
var normalForce = 4000.0f;// Mathf.Clamp(-_suspensionForce, 0, 10000);
|
||||
if(normalForce * surfaceFriction < 0.00001f){
|
||||
_peakSlip = Vector3.one;
|
||||
_friction = Vector3.zero;
|
||||
return;
|
||||
}
|
||||
|
||||
//compute Pacejka params
|
||||
var lateralParams = Pacejka.LateralParams(normalForce, camber, _coeffs);
|
||||
var longitudinalParams = Pacejka.LongitudinalParams(normalForce, _coeffs);
|
||||
var aligningParams = Pacejka.AligningParams(normalForce, camber, _coeffs);
|
||||
|
||||
_peakSlip.x = Pacejka.Extremum(longitudinalParams);
|
||||
_peakSlip.y = Pacejka.Extremum(lateralParams);
|
||||
_peakSlip.z = Pacejka.Extremum(aligningParams);
|
||||
|
||||
float epsilon = 0.000001f;
|
||||
|
||||
Vector3 slip = new Vector3();
|
||||
if(Mathf.Abs(_peakSlip.x) >= epsilon){
|
||||
slip.x = _slip.x / _peakSlip.x;
|
||||
}
|
||||
if(Mathf.Abs(_peakSlip.y) >= epsilon){
|
||||
slip.y = _slip.y / _peakSlip.y;
|
||||
}
|
||||
if(Mathf.Abs(_peakSlip.z) >= epsilon){
|
||||
slip.z = _slip.y / _peakSlip.z;
|
||||
}
|
||||
|
||||
|
||||
//Combined friction (friction circle)
|
||||
float slip_xy = new Vector3 (slip.x, slip.y, 0.0f).magnitude;
|
||||
float slip_xz = new Vector3 (slip.x, 0.0f, slip.z).magnitude;
|
||||
|
||||
|
||||
if ((Mathf.Abs(normalForce) > epsilon) && (_localVelocity.magnitude > 0.001f)) {
|
||||
_friction.x = Pacejka.MagicFormula(Mathf.Sign(slip.x) * slip_xy * _peakSlip.x, longitudinalParams) * surfaceFriction;
|
||||
_friction.y = Pacejka.MagicFormula(Mathf.Sign(slip.y) * slip_xy * _peakSlip.y, lateralParams) * surfaceFriction;
|
||||
_friction.z = Pacejka.MagicFormula(slip_xz * _peakSlip.z, aligningParams) * surfaceFriction;
|
||||
|
||||
if (slip_xy > epsilon)
|
||||
{
|
||||
_friction.x *= Mathf.Abs (slip.x) / slip_xy;
|
||||
_friction.y *= Mathf.Abs (slip.y) / slip_xy;
|
||||
}
|
||||
if (slip_xz > epsilon)
|
||||
_friction.z *= slip.z / slip_xz;
|
||||
}else{
|
||||
_friction = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
public float AngularVelocity{
|
||||
get{return _driveShaft.AngularVelocity;}
|
||||
}
|
||||
|
||||
public void FixedUpdate(){
|
||||
UpdateRelativePosition ();
|
||||
|
||||
|
||||
Quaternion q = Quaternion.AngleAxis (SteerAngle, transform.up);
|
||||
var trs = Matrix4x4.TRS (Vector3.zero, q, Vector3.one);
|
||||
var right = trs.MultiplyPoint3x4 (transform.right).normalized;
|
||||
var forward = trs.MultiplyPoint3x4 (transform.forward).normalized;
|
||||
|
||||
//get wheel joint velocity
|
||||
_velocity = _chassisRigidBody.GetPointVelocity (transform.position);
|
||||
|
||||
|
||||
UpdateSlipAngles ();
|
||||
UpdateFriction ();
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*var raycastRay = new Ray (transform.position, -transform.up);
|
||||
|
||||
RaycastHit rayHit;
|
||||
if (Physics.Raycast (raycastRay, out rayHit)) {
|
||||
if(rayHit.distance <= (wheelRadius + suspensionDistance)){
|
||||
_isGrounded = true;
|
||||
currentLength = 1.0f - (rayHit.distance - wheelRadius) / suspensionDistance;
|
||||
|
||||
|
||||
_suspensionForce = suspensionSpring * (targetPosition - currentLength) + suspensionDamper * (previousLength - currentLength) / Time.fixedDeltaTime;
|
||||
//_chassisRigidBody.AddForceAtPosition(rayHit.normal * -_suspensionForce, transform.position);
|
||||
|
||||
|
||||
previousLength = currentLength;
|
||||
_hit.point = rayHit.point;
|
||||
_hit.normal = rayHit.normal;
|
||||
|
||||
|
||||
|
||||
|
||||
var friction = forward * _friction.x- right * _friction.y;
|
||||
var frictionTorque = _friction.x * wheelRadius;
|
||||
|
||||
var reaction_torque = frictionTorque;
|
||||
var applied_torque = _driveTorque + _breakTorque;
|
||||
|
||||
if ( ( applied_torque > 0 && reaction_torque > applied_torque ) ||
|
||||
( applied_torque < 0 && reaction_torque < applied_torque ) )
|
||||
reaction_torque = applied_torque;
|
||||
|
||||
var tire_torque = right * reaction_torque;
|
||||
|
||||
float matFriction = 0.8f;
|
||||
float rolling = 0;// matFriction * (0.0136f + 0.4e-7f * AngularVelocity * AngularVelocity);
|
||||
|
||||
float rolling_resistance_torque = rolling * wheelRadius - frictionTorque;
|
||||
float wheel_torque = _driveTorque + _breakTorque + rolling_resistance_torque;
|
||||
|
||||
|
||||
this.SetTorque(wheel_torque, Time.fixedDeltaTime);
|
||||
this.Integrate(Time.fixedDeltaTime);
|
||||
|
||||
|
||||
|
||||
_chassisRigidBody.AddForceAtPosition(friction, rayHit.point);
|
||||
//_chassisRigidBody.AddForceAtPosition(forward * _friction.x, transform.position);
|
||||
|
||||
}else{
|
||||
currentLength = suspensionDistance;
|
||||
previousLength = currentLength;
|
||||
_isGrounded = false;
|
||||
_friction = Vector3.zero;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
currentLength = suspensionDistance;
|
||||
previousLength = currentLength;
|
||||
_isGrounded = false;
|
||||
_friction = Vector3.zero;
|
||||
}
|
||||
|
||||
_currentSuspensionPosition = currentLength;*/
|
||||
/*}
|
||||
|
||||
private Rigidbody FindFirstParentRigidBody(){
|
||||
var currentTransform = transform;
|
||||
while (true) {
|
||||
var parent = currentTransform.parent;
|
||||
if(parent == null){
|
||||
return null;
|
||||
}
|
||||
|
||||
var rb = parent.gameObject.GetComponent<Rigidbody>();
|
||||
if(rb != null){
|
||||
return rb;
|
||||
}
|
||||
currentTransform = parent;
|
||||
}
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
void OnGUI(){
|
||||
int id = int.Parse (name [name.Length - 1].ToString ());
|
||||
SteerAngle = GUI.HorizontalSlider (new Rect(10, 20 * id, 100,20), SteerAngle, -30, 30);
|
||||
GUI.Label (new Rect (120, 20 * id, 100, 20), SteerAngle.ToString());
|
||||
}
|
||||
|
||||
|
||||
void OnDrawGizmosSelected(){
|
||||
if (!DrawDebug) {
|
||||
return;
|
||||
}
|
||||
var p = _coeffs;
|
||||
|
||||
Curve[] curves = new Curve[]{new Curve(), new Curve(), new Curve()};
|
||||
|
||||
int sampleCnt = 150;
|
||||
float minArg = -20;
|
||||
float maxArg = 20;
|
||||
float argDiff = maxArg - minArg;
|
||||
|
||||
for (int i = 0; i < sampleCnt; ++i) {
|
||||
var arg = minArg + argDiff / ((float)sampleCnt - 1) * (float)i;
|
||||
curves[0].AddArg(arg);
|
||||
curves[1].AddArg(arg);
|
||||
curves[2].AddArg(arg);
|
||||
|
||||
curves[0].AddVal(Pacejka.LongitudinalForce (5000.0f, arg, p));
|
||||
curves[1].AddVal(Pacejka.LateralForce (5000.0f, camber, arg, p));
|
||||
curves[2].AddVal(Pacejka.AligningForce (5000.0f, camber, arg, p));
|
||||
}
|
||||
|
||||
|
||||
Tools.BeginGui ();
|
||||
Plot2D plot = new Plot2D(curves[1]);
|
||||
|
||||
//Slip.peak_slip(
|
||||
|
||||
plot.Title = "Longitudinal friction";
|
||||
plot.OnGUI(new Rect(90,100,500,400));
|
||||
|
||||
camber = GUI.HorizontalSlider (new Rect (10, 10, 100, 10), camber, -10, 10);
|
||||
Tools.EndGui ();
|
||||
}*/
|
||||
|
||||
//void OnDrawGizmos(){
|
||||
|
||||
//_suspensionForce = 5000.0f;
|
||||
//UpdateSlipAngles ();
|
||||
//UpdateFriction ();
|
||||
|
||||
|
||||
/*if (suspensionDistance < 0.01f) {
|
||||
suspensionDistance = 0.01f;
|
||||
}*/
|
||||
/*if (wheelRadius < 0.01f) {
|
||||
wheelRadius = 0.01f;
|
||||
}
|
||||
//targetPosition = Mathf.Clamp01 (targetPosition);
|
||||
|
||||
Vector3 wheelPosition;
|
||||
Vector3 bottom;
|
||||
*/
|
||||
/*if (Application.isPlaying) {
|
||||
wheelPosition = transform.position - transform.up.normalized * (1 - _currentSuspensionPosition) * suspensionDistance;
|
||||
|
||||
}else{
|
||||
wheelPosition = transform.position;
|
||||
}*/
|
||||
|
||||
|
||||
//bottom = transform.position - transform.up.normalized * suspensionDistance;
|
||||
|
||||
/*float kSuspW = 0.1f;
|
||||
float suspHW = wheelRadius * kSuspW * 0.5f;
|
||||
|
||||
Quaternion q = Quaternion.AngleAxis (SteerAngle, transform.up);
|
||||
var trs = Matrix4x4.TRS (Vector3.zero, q, Vector3.one);
|
||||
var right = trs.MultiplyPoint3x4 (transform.right);
|
||||
var forward = trs.MultiplyPoint3x4 (transform.forward);
|
||||
*/
|
||||
|
||||
/*Gizmos.color = Color.red;
|
||||
//draw suspension
|
||||
Gizmos.DrawLine (transform.position, bottom);
|
||||
Gizmos.DrawLine (transform.position - forward * suspHW * 1.5f, transform.position + forward * suspHW* 1.5f);
|
||||
Gizmos.DrawLine (bottom - forward * suspHW, bottom + forward * suspHW);
|
||||
*/
|
||||
|
||||
|
||||
/*var colliderColor = new Color (0, 1, 0, 0.5f);
|
||||
Gizmos.color = colliderColor;
|
||||
|
||||
|
||||
//draw wheel radius
|
||||
var wheelCenter = transform.position;
|
||||
var rollMatrix = Matrix4x4.TRS (Vector3.zero, Quaternion.AngleAxis(_driveShaft.Angle * Mathf.Rad2Deg, right), Vector3.one);
|
||||
var radiusP0 = -forward * wheelRadius;
|
||||
var radiusP1 = forward * wheelRadius * 1.2f;
|
||||
radiusP0 = rollMatrix.MultiplyPoint3x4 (radiusP0);
|
||||
radiusP1 = rollMatrix.MultiplyPoint3x4 (radiusP1);
|
||||
Gizmos.DrawLine (wheelCenter + radiusP0, wheelCenter + radiusP1);
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//draw wheel circle
|
||||
//AdvancedGizmo.DrawCircle (wheelCenter, right, wheelRadius, colliderColor, 36);
|
||||
|
||||
//draw force point
|
||||
/*var wheelBottom = wheelCenter - transform.up * wheelRadius;
|
||||
AdvancedGizmo.DrawCircle (wheelBottom, forward, wheelRadius * kSuspW, colliderColor);
|
||||
AdvancedGizmo.DrawCircle (wheelBottom, right, wheelRadius * kSuspW, colliderColor);
|
||||
AdvancedGizmo.DrawCircle (wheelBottom, transform.up, wheelRadius * kSuspW, colliderColor);
|
||||
*/
|
||||
//draw friction
|
||||
/*Gizmos.color = Color.red;
|
||||
Gizmos.DrawLine (transform.position, transform.position + forward * _friction.x);
|
||||
|
||||
//draw wheel velocity
|
||||
Gizmos.color = colliderColor;
|
||||
Gizmos.DrawLine (transform.position, transform.position + _velocity);
|
||||
|
||||
var p = Camera.current.WorldToScreenPoint (transform.position + Vector3.up);
|
||||
p.y = Camera.current.pixelHeight - p.y;
|
||||
|
||||
|
||||
|
||||
|
||||
Tools.BeginGui ();
|
||||
var labelRect = new Rect (p.x, p.y, 90, 20);
|
||||
Tools.DrawRectangle (labelRect, new Color(0,0,0,0.5f));
|
||||
GUI.Label (new Rect (p.x, p.y, 100, 100), _friction.x.ToString ());
|
||||
|
||||
Tools.EndGui ();
|
||||
}*/
|
||||
//}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d2045ac6b2191949ba985c5f8d8cf23
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class CarWheelDebugger : MonoBehaviour {
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd0e2d6bdf207664db5eb88eb19512aa
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,19 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class CenterOfMass : MonoBehaviour {
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
void OnDrawGizmos(){
|
||||
Gizmos.DrawWireCube (transform.position, new Vector3 (0.1f, 0.1f, 0.1f));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08c70305f88768c47ae1f6179c937806
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,26 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class Clutch : MonoBehaviour {
|
||||
|
||||
public CarEngine engine;
|
||||
public Gearbox gearbox;
|
||||
private float _pressure = 1.0f;
|
||||
|
||||
public float Pressure{
|
||||
get{ return _pressure;}
|
||||
set{
|
||||
_pressure = Mathf.Clamp01(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9a5d0ceff39c2d4da746187c752d66f
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,14 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public static class ColorEx {
|
||||
|
||||
public static string ToHex(this Color color)
|
||||
{
|
||||
return string.Format("#{0}{1}{2}{3}",
|
||||
(((int)(color.r * 255.0f))&0xff).ToString("X2"),
|
||||
(((int)(color.g * 255.0f))&0xff).ToString("X2"),
|
||||
(((int)(color.b * 255.0f))&0xff).ToString("X2"),
|
||||
(((int)(color.a * 255.0f))&0xff).ToString("X2"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca64549d1cac22a419dcfbc203873c0e
|
||||
timeCreated: 1461872157
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class ConstantAngularSpeed : MonoBehaviour
|
||||
{
|
||||
|
||||
public Vector3 angularVelocity;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
GetComponent<Rigidbody>().angularVelocity = angularVelocity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdaa4477408108745b8d01968739a76a
|
||||
timeCreated: 1430743113
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class Curve : MonoBehaviour {
|
||||
public virtual float Sample(float arg)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 917382405abb03e478b65ea3b7c5b2b3
|
||||
timeCreated: 1454257651
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4013a7cdee5e4ce478b06ca99a16009c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,30 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class ConstantForce : MonoBehaviour {
|
||||
|
||||
public Vector3 force;
|
||||
public Rigidbody body;
|
||||
public float maxSpeed = 1000;
|
||||
public bool localSpace = true;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void FixedUpdate () {
|
||||
if (body != null) {
|
||||
var vel = body.velocity.magnitude;
|
||||
if(vel < maxSpeed) {
|
||||
if(localSpace) {
|
||||
var f = transform.TransformDirection(force);
|
||||
body.AddForce(f);
|
||||
} else {
|
||||
body.AddForce(force);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3052e159dd821b343b26054f95fee9fd
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class ConstantVelocity : MonoBehaviour {
|
||||
public Rigidbody target;
|
||||
public Vector3 velocity = Vector3.forward;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
void FixedUpdate() {
|
||||
if (target != null) {
|
||||
target.velocity = velocity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2447c867112e08944a68a1b2a72389f4
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -100
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,35 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
|
||||
public class DebugSpeedometer : MonoBehaviour
|
||||
{
|
||||
public WheelPhysics[] wheels;
|
||||
public Rigidbody car;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
float speed_ms = 0;
|
||||
if (wheels != null)
|
||||
{
|
||||
speed_ms = Mathf.Abs((float)wheels.Select(v => v.angularVelocity*v.TotalWheelRadius).Sum() / wheels.Length);
|
||||
}
|
||||
|
||||
var speed_kmph = (speed_ms*60.0f*60.0f)/1000.0f;
|
||||
var car_speed = car.velocity.magnitude*3.6f;
|
||||
|
||||
|
||||
GUI.Label(new Rect(20, 100, 200, 40), "Wheels speed [km/h]: " + speed_kmph);
|
||||
GUI.Label(new Rect(20, 140, 200, 40), "Real speed [km/h]: " + car_speed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f076152b0f182a946abb77db1b200bbb
|
||||
timeCreated: 1453672668
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class GetPhysicsDeltaTime : MonoBehaviour {
|
||||
public Rigidbody source;
|
||||
private Vector3 lastPos;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
lastPos = source.position;
|
||||
source.velocity = Vector3.forward;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void FixedUpdate() {
|
||||
var currentPos = source.position;
|
||||
var delta = currentPos - lastPos;
|
||||
var distance = delta.magnitude;
|
||||
lastPos = currentPos;
|
||||
|
||||
Debug.Log("Delta time = " + distance+ " Fixed delta: " + Time.fixedDeltaTime);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37b12b0ffde576c48976e47fb0d4ec9f
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,17 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public static class Label3D {
|
||||
/*
|
||||
public static void AtWorldPosition(Vector3 position, string text) {
|
||||
var screenPosition = Camera.main.WorldToScreenPoint(position);
|
||||
screenPosition.y = Camera.main.pixelHeight - screenPosition.y;
|
||||
|
||||
var labelContent = new GUIContent(text);
|
||||
var size = GUI.skin.label.CalcSize(new GUIContent(text));
|
||||
var labelRect = new Rect(screenPosition.x, screenPosition.y, size.x, size.y);
|
||||
Tools.DrawRectangle(labelRect, new Color(0,0,0,0.5f));
|
||||
GUI.Label(labelRect, labelContent);
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43b38c3c19f944d4b8c5fed125847963
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,66 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
public class Plot2DVariableFunction : Plot2DFunction
|
||||
{
|
||||
public GameObject target;
|
||||
public string variable;
|
||||
|
||||
// Use this for initialization
|
||||
void Start ()
|
||||
{
|
||||
ReadValue();
|
||||
|
||||
}
|
||||
|
||||
public override float f(float x)
|
||||
{
|
||||
return ReadValue();
|
||||
}
|
||||
|
||||
float ReadValue()
|
||||
{
|
||||
if (target != null) {
|
||||
var pathBlocks = variable.Split('.');
|
||||
var c = target.GetComponent(pathBlocks[0]);
|
||||
|
||||
if (c == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
//find target
|
||||
int depth = 1;
|
||||
object o = c;
|
||||
System.Reflection.FieldInfo field = null ;
|
||||
|
||||
while (depth < pathBlocks.Length) {
|
||||
var t = o.GetType();
|
||||
field = t.GetField(pathBlocks[depth], System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
|
||||
if (field == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
o = field.GetValue(o);
|
||||
depth++;
|
||||
}
|
||||
try
|
||||
{
|
||||
float val = Convert.ToSingle(o);
|
||||
return val;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogFormat("Failed to convert property {0} to float type!", field.Name);
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 477c3138005e6c64da3d6bc84e51dec9
|
||||
timeCreated: 1454231920
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,117 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
|
||||
public class TyreCurvesView : MonoBehaviour
|
||||
{
|
||||
|
||||
public OscilloscopeDisplay display;
|
||||
public float Fz = 5000;
|
||||
|
||||
public bool autoVerticalScale = true;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (display == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var tyre = GetComponent<Tyre>();
|
||||
|
||||
if (display.plot.channels.Length < 4) {
|
||||
Array.Resize(ref display.plot.channels, 4);
|
||||
}
|
||||
|
||||
int samplesCount = 400;
|
||||
|
||||
|
||||
Color[] channel_colors = new[] {Color.red, Color.green, Color.blue};
|
||||
|
||||
double r = 0.33;
|
||||
double r0 = r;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
var channel = display.plot.channels[i];
|
||||
channel.ResizeBuffers(samplesCount);
|
||||
channel.SampleBufferPosition = samplesCount - 1;
|
||||
channel.color = channel_colors[i];
|
||||
if (autoVerticalScale)
|
||||
{
|
||||
channel.cellValue = Fz / display.halfYCellCount;
|
||||
}
|
||||
|
||||
channel.cellTime = 1.0f / display.halfXCellCount;
|
||||
|
||||
if (i == 0){
|
||||
for (int j = 0; j < samplesCount; ++j) {
|
||||
float k = ((1.0f / (float)(samplesCount - 1)) * j) * 2.0f - 1.0f;
|
||||
var Vc = new Double3(10, 0, 0);
|
||||
var forces = Pacejka.CalcPacejka(Vc, (Vc.x + Vc.x * k) / r, r0, r, Fz, 0, tyre.pacejkaParams._coeffs2, false);
|
||||
channel.SetSample(j, k, (float)forces.x);
|
||||
}
|
||||
} else if (i == 1) {
|
||||
for (int j = 0; j < samplesCount; ++j) {
|
||||
float k = ((1.0f / (float)(samplesCount - 1)) * j) * 2.0f - 1.0f;
|
||||
Vector3 angle_zero = new Vector3(10, 0, 0);
|
||||
Vector3 angle_90 = new Vector3(0, 10, 0);
|
||||
Vector3 Vc = (Vector3.Lerp(angle_zero, angle_90, Mathf.Abs(k))*Mathf.Sign(k)).normalized * 10;
|
||||
var forces = Pacejka.CalcPacejka(new Double3(Vc.x, Vc.y, Vc.z), 10.0 / r, r0, r, Fz, 0, tyre.pacejkaParams._coeffs2, false);
|
||||
channel.SetSample(j, k, (float)forces.y);
|
||||
}
|
||||
} else if (i == 2) {
|
||||
for (int j = 0; j < samplesCount; ++j) {
|
||||
float k = ((1.0f / (float)(samplesCount - 1)) * j) * 2.0f - 1.0f;
|
||||
Vector3 angle_zero = new Vector3(10, 0, 0);
|
||||
Vector3 angle_90 = new Vector3(0, 10, 0);
|
||||
Vector3 Vc = (Vector3.Lerp(angle_zero, angle_90, Mathf.Abs(k))).normalized * 10;
|
||||
Vc.y *= Mathf.Sign(k);
|
||||
var forces = Pacejka.CalcPacejka(new Double3(Vc.x, Vc.y, Vc.z), 10.0 / r, r0, r, Fz, 0, tyre.pacejkaParams._coeffs2, false);
|
||||
channel.SetSample(j, k, (float)forces.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//draw friction circle
|
||||
var combined_channel = display.plot.channels[3];
|
||||
combined_channel.ResizeBuffers(samplesCount);
|
||||
combined_channel.SampleBufferPosition = samplesCount - 1;
|
||||
combined_channel.color = Color.white;
|
||||
combined_channel.cellValue = combined_channel.cellTime = 3000 / display.halfYCellCount;
|
||||
|
||||
for (int j = 0; j < samplesCount; ++j) {
|
||||
float k = ((1.0f / (float)(samplesCount - 1)) * j) * 2.0f - 1.0f;
|
||||
|
||||
// float k = ((1.0f / (float)(samplesCount - 1)) * j);
|
||||
/*float angle = Mathf.PI*2.0f*k;
|
||||
var v = new Vector3(Mathf.Sin(angle), Mathf.Cos(angle), 0) * 1000;
|
||||
combined_channel.SetSample(j, (float)v.x, (float)v.y);*/
|
||||
|
||||
Vector3 angle_zero = new Vector3(1, 0, 0);
|
||||
Vector3 angle_90 = new Vector3(0, 1, 0);
|
||||
|
||||
|
||||
Vector3 Vc = (Vector3.Lerp(angle_zero, angle_90, Mathf.Abs(k)) ).normalized * 10;
|
||||
Vc.y *= Mathf.Sign(k);
|
||||
var forces = Pacejka.CalcPacejka(new Double3(Vc.x, Vc.y, Vc.z), 8.0 / r, r0, r, Fz, 0, tyre.pacejkaParams._coeffs2, true);
|
||||
|
||||
combined_channel.SetSample(j, (float)forces.x, (float)forces.y);
|
||||
// combined_channel.SetSample(j, k * 3000, (float)forces.x);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68fb46041ea99004b9edd5d7fc9133da
|
||||
timeCreated: 1453127428
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public static class GameObjectEx {
|
||||
|
||||
public static Vector3 GetEulerAnglesLocal(this GameObject obj){
|
||||
return obj.transform.localEulerAngles;
|
||||
}
|
||||
|
||||
public static Vector3 SetEulerAnglesLocal(this GameObject obj, Vector3 angles){
|
||||
return obj.transform.localEulerAngles = angles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46281f2baa585724aafa4fc416a1ff24
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,57 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public enum Gears{
|
||||
Rear = -1,
|
||||
Neutral = 0,
|
||||
Gear1 = 1,
|
||||
Gear2 = 2,
|
||||
Gear3 = 3,
|
||||
Gear4 = 4,
|
||||
Gear5 = 5
|
||||
}
|
||||
|
||||
public class GearboxDefault : Gearbox {
|
||||
private float[] _gearRatios = new float[]{3.5f, 0.0f, 3.636f, 1.95f, 1.375f, 0.941f, 0.784f};
|
||||
private int _currentGear = (int)Gears.Neutral;
|
||||
|
||||
public override float GetGearRatio (int gear)
|
||||
{
|
||||
throw new System.NotImplementedException ();
|
||||
}
|
||||
|
||||
public override int Gear{
|
||||
get{ return _currentGear;}
|
||||
set{
|
||||
if (_currentGear != value) {
|
||||
_currentGear = value;
|
||||
Debug.Log("Set gear to: " + (Gears)_currentGear);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override GearboxControlType ControlType {
|
||||
get {
|
||||
return GearboxControlType.Manual;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaxOutputTorque {
|
||||
get {
|
||||
return 600.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GearsCount {get {return _gearRatios.Length;}}
|
||||
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5ee2c816bfcf0b4fa4d39b321073968
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user