void AddWheel(Transform wheel) { GameObject go = new GameObject("Collider for " + wheel.name); go.transform.SetParent(wheelColliderHolder.transform); WheelCollider wheelCollider = go.AddComponent <WheelCollider>(); wheelCollider.mass = 30f; wheelCollider.suspensionDistance = 0.3f; wheelCollider.forceAppPointDistance = 0.2f; wheelCollider.suspensionSpring = new JointSpring { spring = 35000f, damper = 8000, targetPosition = 0.5f }; wheelCollider.forwardFriction = new WheelFrictionCurve { extremumSlip = 0.4f, extremumValue = 1f, asymptoteSlip = 0.8f, asymptoteValue = 0.5f, stiffness = 1.2f }; wheelCollider.sidewaysFriction = new WheelFrictionCurve { extremumSlip = 0.2f, extremumValue = 1f, asymptoteSlip = 1.5f, asymptoteValue = 1f, stiffness = 2.2f }; go.transform.position = wheel.position; wheelCollider.center = new Vector3(0f, go.transform.localPosition.y / 2, 0f); wheelCollider.radius = wheel.GetComponent <MeshFilter>().mesh.bounds.extents.z; wheelCollider.ConfigureVehicleSubsteps(5.0f, 30, 10); wheelCollider.wheelDampingRate = wheelDampingRate; var data = new WheelData() { transform = wheel, collider = wheelCollider, steering = wheel.name.Contains("Front") }; wheels.Add(data); DistributeTransform(wheel); }
WheelData SetupWheels(Transform wheel) { WheelData result = new WheelData(); GameObject go = new GameObject("Collider_" + wheel.name); go.transform.parent = transform; go.transform.position = wheel.position; go.transform.localRotation = Quaternion.Euler(0, wheel.localRotation.y, 0); WheelCollider col = (WheelCollider)go.AddComponent(typeof(WheelCollider)); WheelCollider colPref = WheelPerfab.GetComponent <WheelCollider>(); col.mass = colPref.mass; col.center = colPref.center; col.radius = colPref.radius; col.suspensionDistance = colPref.suspensionDistance; col.suspensionSpring = colPref.suspensionSpring; col.forwardFriction = colPref.forwardFriction; col.sidewaysFriction = colPref.sidewaysFriction; result.wheelTransform = wheel; result.col = col; result.wheelStartPos = wheel.transform.localPosition; result.startWheelAngle = wheel.transform.localRotation; return(result); }
WheelData[] wheels; // array with the wheel data // setup wheelcollider for given wheel data // wheel is the transform of the wheel // maxSteer is the angle in degrees the wheel can steer (0f for no steering) // motor if wheel is driven by engine or not WheelData SetWheelParams(Transform wheel, float maxSteer, bool motor) { if (wheel == null) { throw new System.Exception("wheel not connected to script!"); } WheelData result = new WheelData(); // the container of wheel specific data // we create a new gameobject for the collider and move, transform it to match // the position of the wheel it represents. This allows us to do transforms // on the wheel itself without disturbing the collider. GameObject go = new GameObject("WheelCollider"); go.transform.parent = transform; // the car, not the wheel is parent go.transform.position = wheel.position; // match wheel pos // create the actual wheel collider in the collider game object WheelCollider col = (WheelCollider)go.AddComponent(typeof(WheelCollider)); col.motorTorque = 0.0f; // store some useful references in the wheeldata object result.transform = wheel; // access to wheel transform result.go = go; // store the collider game object result.col = col; // store the collider self result.startPos = go.transform.localPosition; // store the current local pos of wheel result.maxSteer = maxSteer; // store the max steering angle allowed for wheel result.motor = motor; // store if wheel is connected to engine return(result); // return the WheelData }
void CalculateWheelRotationFromSpeed(Axle axle, WheelData data, Vector3 wsPos) { if (rb == null) { data.visualRotationRad = 0.0f; return; } Quaternion localWheelRot = Quaternion.Euler(new Vector3(0.0f, data.yawRad * Mathf.Rad2Deg, 0.0f)); Quaternion wsWheelRot = transform.rotation * localWheelRot; Vector3 wsWheelForward = wsWheelRot * Vector3.forward; Vector3 velocityQueryPos = data.isOnGround ? data.touchPoint.point : wsPos; Vector3 wheelVelocity = rb.GetPointVelocity(velocityQueryPos); // Longitudinal speed (meters/sec) float tireLongSpeed = Vector3.Dot(wheelVelocity, wsWheelForward); // Circle length = 2 * PI * R float wheelLengthMeters = 2 * Mathf.PI * axle.radius; // Wheel "Revolutions per second"; float rps = tireLongSpeed / wheelLengthMeters; float deltaRot = Mathf.PI * 2.0f * rps * Time.deltaTime; data.visualRotationRad += deltaRot; }
public void UpdateWheels(CarInputManager input, WheelData wheelData) { foreach (BaseWheel wheel in _wheelColliders) { wheel.UpdateWheels(input, wheelData); } }
void HandleMotorTorque(CarInputManager inputManager, WheelData wheelData) { if (!isThrottleWheel) { return; } _wheelCollider.motorTorque = inputManager.Throttle * wheelData.motorToruqe; }
private WheelData SetupUpperWheels(Transform wheel) { WheelData result = new WheelData(); result.wheelTransform = wheel; result.wheelRotationAngles = wheel.localEulerAngles; return(result); }
void Start() { rb = GetComponent <Rigidbody>(); rb.centerOfMass = COM.localPosition; w = SetupWheels(wheelsT, WColForward[0]); }
private WheelData SetupWheels(Transform wheel, WheelCollider col) { WheelData result = new WheelData(); // результат для заполнения массива result.wheelTransform = wheel; //заполнить трансформ result.col = col; //заполнить колайдер result.wheelStartPos = wheel.transform.localPosition; //заполнить стартовую позицию return(result); //вернуть результат }
void Start() { GetComponent <Rigidbody>().centerOfMass = CenterOfMass.localPosition; wheels = new WheelData[2]; wheels[0] = new WheelData(wheelF, WColForward); wheels[1] = new WheelData(wheelB, WColBack); thisTransform = GetComponent <Transform>(); }
private WheelData SetupWheels(Transform wheel, WheelCollider col) { WheelData result = new WheelData(); result.wheelTransform = wheel; result.col = col; result.wheelStartPos = wheel.transform.localPosition; return(result); }
void CalculateAxleForces(Axle axle, int totalWheelsCount, int numberOfPoweredWheels) { Vector3 wsDownDirection = transform.TransformDirection(Vector3.down); // Debug.Log(string.Format("方向在经过从本地到世界后为wsD {0}", wsDownDirection)); wsDownDirection.Normalize(); // Debug.Log(string.Format("归一化了以后wsD {0}", wsDownDirection)); Vector3 localL = new Vector3(axle.width * -0.5f, axle.offset.y, axle.offset.x); Vector3 localR = new Vector3(axle.width * 0.5f, axle.offset.y, axle.offset.x); // Debug.Log(string.Format("本地左{0}本地右{1}", localL,localR)); Vector3 wsL = transform.TransformPoint(localL); Vector3 wsR = transform.TransformPoint(localR); // For each wheel for (int wheelIndex = 0; wheelIndex < 2; wheelIndex++) { WheelData wheelData = (wheelIndex == WHEEL_LEFT_INDEX) ? axle.wheelDataL : axle.wheelDataR; Vector3 wsFrom = (wheelIndex == WHEEL_LEFT_INDEX) ? wsL : wsR; // Debug.Log(string.Format("wsDownDirection {0}", wsDownDirection)); CalculateWheelForces(axle, wsDownDirection, wheelData, wsFrom, wheelIndex, totalWheelsCount, numberOfPoweredWheels); } // http://projects.edy.es/trac/edy_vehicle-physics/wiki/TheStabilizerBars // Apply "stablizier bar" forces float travelL = 1.0f - Mathf.Clamp01(axle.wheelDataL.compression); float travelR = 1.0f - Mathf.Clamp01(axle.wheelDataR.compression); float antiRollForce = (travelL - travelR) * axle.antiRollForce; if (axle.wheelDataL.isOnGround) { // Debug.Log(string.Format("左轮这里有施加平衡力,")); AddForceAtPosition(wsDownDirection * antiRollForce, axle.wheelDataL.touchPoint.point); if (debugDraw) { Debug.DrawRay(axle.wheelDataL.touchPoint.point, wsDownDirection * antiRollForce, Color.magenta); } } if (axle.wheelDataR.isOnGround) { // Debug.Log(string.Format("右轮这里有施加平衡力,")); AddForceAtPosition(wsDownDirection * -antiRollForce, axle.wheelDataR.touchPoint.point); if (debugDraw) { // Debug.DrawRay(axle.wheelDataR.touchPoint.point, wsDownDirection * -antiRollForce, Color.magenta); } } }
private WheelData SetupWheels(Transform wheel, WheelCollider col) { //10 WheelData result = new WheelData(); result.wheelTransform = wheel; //10 result.col = col; //10 result.wheelStartPos = wheel.transform.localPosition; //10 return result; //10 }
void HandleSteering(CarInputManager inputManager, WheelData wheelData) { if (!isSteeringWheel) { return; } float curSteerAngle = inputManager.Steer * wheelData.steerAngle; _wheelCollider.steerAngle = Mathf.Lerp(_wheelCollider.steerAngle, curSteerAngle, Time.deltaTime * steerLerpSpeed); }
// Update is called once per frame public void UpdateWheels(CarInputManager inputManager, WheelData wheelData) { if (!_wheelCollider) { return; } HandleWheelTransform(); HandleSteering(inputManager, wheelData); HandleMotorTorque(inputManager, wheelData); HandleBrakeTorque(inputManager, wheelData); }
public WheelPreset(WheelData data) { if (data == null) { return; } FrontTrackWidth = data.FrontTrackWidth; FrontCamber = data.FrontCamber; RearTrackWidth = data.RearTrackWidth; RearCamber = data.RearCamber; }
void OnGUI() { if (!controllable) { return; } float speed = GetSpeed(); float speedKmH = speed * 3.6f; GUI.Label(new Rect(30.0f, 20.0f, 150, 130), string.Format("{0:F2} km/h", speedKmH), style); GUI.Label(new Rect(30.0f, 40.0f, 150, 130), string.Format("{0:F2} {1:F2} {2:F2}", afterFlightSlipperyTiresTime, brakeSlipperyTiresTime, handBrakeSlipperyTiresTime), style); float yPos = 60.0f; for (int axleIndex = 0; axleIndex < axles.Length; axleIndex++) { GUI.Label(new Rect(30.0f, yPos, 150, 130), string.Format("Axle {0}, steering angle {1:F2}", axleIndex, axles[axleIndex].steerAngle), style); yPos += 18.0f; } Camera cam = Camera.current; if (cam == null) { return; } if (debugDraw) { foreach (Axle axle in axles) { Vector3 localL = new Vector3(axle.width * -0.5f, axle.offset.y, axle.offset.x); Vector3 localR = new Vector3(axle.width * 0.5f, axle.offset.y, axle.offset.x); Vector3 wsL = transform.TransformPoint(localL); Vector3 wsR = transform.TransformPoint(localR); for (int wheelIndex = 0; wheelIndex < 2; wheelIndex++) { WheelData wheelData = (wheelIndex == WHEEL_LEFT_INDEX) ? axle.wheelDataL : axle.wheelDataR; Vector3 wsFrom = (wheelIndex == WHEEL_LEFT_INDEX) ? wsL : wsR; Vector3 screenPos = cam.WorldToScreenPoint(wsFrom); GUI.Label(new Rect(screenPos.x, Screen.height - screenPos.y, 150, 130), wheelData.debugText, style); } } } }
private void syncState() { Quaternion Q = Quaternion.Euler( ((float)syncData.rotateX) / rotateModifier, ((float)syncData.rotateY) / rotateModifier, ((float)syncData.rotateZ) / rotateModifier); transform.SetPositionAndRotation(War.Scene.StreamerManager.GetTilePosition(syncData.position), Q); //tran.localRotation = Q; //tran.position = syncData.position; WheelData wd = wheels[(int)Wheels.LeftFront]; wd = wheels[(int)Wheels.RightFront]; rpm = syncData.rpm; float r = (rpm / 60.0f) * Time.deltaTime * 360.0f; Transform lfw_wheel = gameObject.GetComponent <Transform>().Find(wheel_lf); lfw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); if (syncData.steerAngle != 0) { lfw_wheel.localRotation = Quaternion.Euler(lfw_wheel.localRotation.x, syncData.steerAngle, lfw_wheel.localRotation.z); } Transform rfw_wheel = gameObject.GetComponent <Transform>().Find(wheel_rf); rfw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); if (syncData.steerAngle != 0) { rfw_wheel.localRotation = Quaternion.Euler(rfw_wheel.localRotation.x, syncData.steerAngle, rfw_wheel.localRotation.z); } wd = wheels[(int)Wheels.LeftBack]; Transform lbw_wheel = gameObject.GetComponent <Transform>().Find(wheel_lb); r = (rpm / 60.0f) * Time.deltaTime * 360.0f; lbw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); wd = wheels[(int)Wheels.RightBack]; Transform rbw_wheel = gameObject.GetComponent <Transform>().Find(wheel_rb); r = (rpm / 60.0f) * Time.deltaTime * 360.0f; rbw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); //同步轮胎破坏?运动上不用管,只是显示隐藏轮胎皮而已,现在没有轮胎皮给你 //所以后面资源到了再说 }
void OnDrawGizmosAxle(Vector3 wsDownDirection, Axle axle) { Vector3 localL = new Vector3(axle.width * -0.5f, axle.offset.y, axle.offset.x); Vector3 localR = new Vector3(axle.width * 0.5f, axle.offset.y, axle.offset.x); Vector3 wsL = transform.TransformPoint(localL); Vector3 wsR = transform.TransformPoint(localR); Gizmos.color = axle.debugColor; //draw axle Gizmos.DrawLine(wsL, wsR); //draw line to com Gizmos.DrawLine(transform.TransformPoint(new Vector3(0.0f, axle.offset.y, axle.offset.x)), transform.TransformPoint(centerOfMass)); for (int wheelIndex = 0; wheelIndex < 2; wheelIndex++) { WheelData wheelData = (wheelIndex == WHEEL_LEFT_INDEX) ? axle.wheelDataL : axle.wheelDataR; Vector3 wsFrom = (wheelIndex == WHEEL_LEFT_INDEX) ? wsL : wsR; Gizmos.color = wheelData.isOnGround ? Color.yellow : axle.debugColor; UnityEditor.Handles.color = Gizmos.color; float suspCurrentLen = Mathf.Clamp01(1.0f - wheelData.compression) * axle.lengthRelaxed; Vector3 wsTo = wsFrom + wsDownDirection * suspCurrentLen; // Draw suspension Gizmos.DrawLine(wsFrom, wsTo); Quaternion localWheelRot = Quaternion.Euler(new Vector3(0.0f, wheelData.yawRad * Mathf.Rad2Deg, 0.0f)); Quaternion wsWheelRot = transform.rotation * localWheelRot; Vector3 localAxle = (wheelIndex == WHEEL_LEFT_INDEX) ? Vector3.left : Vector3.right; Vector3 wsAxle = wsWheelRot * localAxle; Vector3 wsForward = wsWheelRot * Vector3.forward; // Draw wheel axle Gizmos.DrawLine(wsTo, wsTo + wsAxle * 0.1f); Gizmos.DrawLine(wsTo, wsTo + wsForward * axle.radius); // Draw wheel UnityEditor.Handles.DrawWireDisc(wsTo, wsAxle, axle.radius); UnityEditor.Handles.DrawWireDisc(wsTo + wsAxle * wheelWidth, wsAxle, axle.radius); UnityEditor.Handles.DrawWireDisc(wsTo - wsAxle * wheelWidth, wsAxle, axle.radius); } }
public void StartCar() { skidmarks = (Skidmarks)FindObjectOfType(typeof(Skidmarks)); wheels = new WheelData[4]; for (int i = 0; i < 4; i++) { wheels[i] = new WheelData(); } wheels[0].graphic = wheelFL; wheels[1].graphic = wheelFR; wheels[2].graphic = wheelBL; wheels[3].graphic = wheelBR; wheels[0].maxSteerAngle = 30.0f; wheels[1].maxSteerAngle = 30.0f; wheels[2].powered = true; wheels[3].powered = true; wheels[2].handbraked = true; wheels[3].handbraked = true; foreach (WheelData w in wheels) { if (w.graphic == null) { Debug.Log("You need to assign all four wheels for the car script!"); } if (!w.graphic.transform.IsChildOf(transform)) { Debug.Log("Wheels need to be children of the Object with the car script"); } w.originalRotation = w.graphic.localRotation; GameObject colliderObject = new GameObject("WheelCollider"); colliderObject.transform.parent = transform; colliderObject.transform.position = w.graphic.position; w.coll = (WheelCollider)colliderObject.AddComponent(typeof(WheelCollider)); w.coll.suspensionDistance = suspensionDistance; JointSpring t = new JointSpring(); t.spring = springs; t.damper = dampers; w.coll.suspensionSpring = t; WheelFrictionCurve wf = new WheelFrictionCurve(); wf.stiffness = wf.extremumValue = wf.extremumSlip = wf.asymptoteSlip = wf.asymptoteValue = 6; w.coll.forwardFriction = wf; w.coll.sidewaysFriction = wf; w.coll.radius = wheelRadius; } wheelY = wheels[0].graphic.localPosition.y; gear = 1; }
void CallBackBtnStartClick() { itemID = WheelData.GetRandomItemID(); Debug.Log("item ==== " + itemID); perPrizeAngle = 360 / prizeCount; _isRuning = true; if (itemID != modeEnum.UnKnow) { StartRotate((int)itemID - 1); } }
protected WheelData[] wheels; // array with the wheel data // setup wheelcollider for given wheel data // wheel is the transform of the wheel // maxSteer is the angle in degrees the wheel can steer (0f for no steering) // motor if wheel is driven by engine or not WheelData SetWheelParams(Transform wheel, float maxSteer, JWheelType wheeltype) { if (wheel == null) { throw new System.Exception("wheel not connected to script!"); } WheelData result = new WheelData(); // the container of wheel specific data // we create a new gameobject for the collider and move, transform it to match // the position of the wheel it represents. This allows us to do transforms // on the wheel itself without disturbing the collider. GameObject go = new GameObject("WheelCollider"); go.transform.parent = transform; // the car, not the wheel is parent go.transform.position = wheel.position; // match wheel pos // create the actual wheel collider in the collider game object WheelCollider col = (WheelCollider)go.AddComponent(typeof(WheelCollider)); col.motorTorque = 0.0f; // store some useful references in the wheeldata object result.transform = wheel; // access to wheel transform result.go = go; // store the collider game object result.col = col; // store the collider self result.startPos = go.transform.localPosition; // store the current local pos of wheel result.maxSteer = maxSteer; // store the max steering angle allowed for wheel result.wheeltype = wheeltype; // store if wheel is connected to engine // see docs, haven't really managed to get this work // like i would but just try out a fiddle with it. WheelFrictionCurve fc = col.forwardFriction; // fc.asymptoteValue = 5000.0f; // fc.extremumSlip = 2.0f; // fc.asymptoteSlip = 20.0f; fc.stiffness = (wheeltype == JWheelType.Front)?fwdStiffnessFront:fwdStiffnessBack; col.forwardFriction = fc; fc = col.sidewaysFriction; // fc.asymptoteValue = 7500.0f; // fc.asymptoteSlip = 2.0f; fc.stiffness = (wheeltype == JWheelType.Front)?swyStiffnessFront:swyStiffnessBack; col.sidewaysFriction = fc; return(result); // return the WheelData }
protected WheelData w; //8 // Use this for initialization void Start() { rb = GetComponent <Rigidbody>(); rb.centerOfMass = COM.localPosition; w = SetupWheels(wheelsT, WColForward[0]); //for (int i = 0; i < WColForward.Length; i++) //{ //9 // wheels[i] = SetupWheels(wheelsF[i], WColForward[i]); //9 //} //for (int i = 0; i < WColBack.Length; i++) //{ //9 // wheels[i + WColForward.Length] = SetupWheels(wheelsB[i], WColBack[i]); //9 //} }
Vector3 WheelPosition(Axle axle, WheelData wheel, bool accountForSuspension = true) { bool isLeftWheel = IsLeftWheel(axle, wheel); // Start with Local Space Vector3 wheelPos = Vector3.zero; // Apply axle offset and axle width wheelPos.Set(wheelPos.x + (axle.width / 2 * (isLeftWheel ? -1f : 1f)), wheelPos.y + axle.offset.y, wheelPos.z + axle.offset.x); // Apply suspension if (accountForSuspension) { wheelPos.Set(wheelPos.x, wheelPos.y - (axle.suspensionHeight * (1f - wheel.compression)), wheelPos.z); } return(transform.TransformPoint(wheelPos)); }
WheelData[] wheels; // array with the wheel data // setup wheelcollider for given wheel data // wheel is the transform of the wheel // maxSteer is the angle in degrees the wheel can steer (0f for no steering) // motor if wheel is driven by engine or not WheelData SetWheelParams(Transform wheel, float maxSteer, bool motor, float curY) { if (wheel == null) { throw new System.Exception("wheel not connected to script!"); } WheelData result = new WheelData(); // the container of wheel specific data // we create a new gameobject for the collider and move, transform it to match // the position of the wheel it represents. This allows us to do transforms // on the wheel itself without disturbing the collider. GameObject go = new GameObject("WheelCollider"); go.transform.parent = transform; // the car, not the wheel is parent go.transform.position = wheel.position; // match wheel pos go.transform.eulerAngles = transform.eulerAngles; curY = wheel.transform.localPosition.y; // create the actual wheel collider in the collider game object wheel.transform.gameObject.AddComponent <WheelCollider>(); WheelCollider col = (WheelCollider)go.AddComponent(typeof(WheelCollider)); col.transform.localScale = wheel.transform.localScale; col.radius = wheel.transform.GetComponent <WheelCollider>().radius; Destroy(wheel.transform.GetComponent <WheelCollider>()); col.motorTorque = 0.0f; // store some useful references in the wheeldata object result.transform = wheel; // access to wheel transform result.curY = curY; result.go = go; // store the collider game object result.col = col; // store the collider self result.startPos = wheel.localPosition; // store the current local pos of wheel result.maxSteer = maxSteer; // store the max steering angle allowed for wheel result.motor = motor; // store if wheel is connected to engine if (AutomaticWheelRadius) { wheelRadius = wheel.FindChild("wheel").GetComponent <Renderer>().bounds.size.y / 2; } col.radius = wheelRadius; return(result); // return the WheelData }
public void StartCar() { skidmarks = (Skidmarks)FindObjectOfType(typeof(Skidmarks)); wheels = new WheelData[4]; for (int i = 0; i < 4; i++) wheels[i] = new WheelData(); wheels[0].graphic = wheelFL; wheels[1].graphic = wheelFR; wheels[2].graphic = wheelBL; wheels[3].graphic = wheelBR; wheels[0].maxSteerAngle = 30.0f; wheels[1].maxSteerAngle = 30.0f; wheels[2].powered = true; wheels[3].powered = true; wheels[2].handbraked = true; wheels[3].handbraked = true; foreach (WheelData w in wheels) { if (w.graphic == null) Debug.Log("You need to assign all four wheels for the car script!"); if (!w.graphic.transform.IsChildOf(transform)) Debug.Log("Wheels need to be children of the Object with the car script"); w.originalRotation = w.graphic.localRotation; GameObject colliderObject = new GameObject("WheelCollider"); colliderObject.transform.parent = transform; colliderObject.transform.position = w.graphic.position; w.coll = (WheelCollider)colliderObject.AddComponent(typeof(WheelCollider)); w.coll.suspensionDistance = suspensionDistance; JointSpring t = new JointSpring(); t.spring = springs; t.damper = dampers; w.coll.suspensionSpring = t; WheelFrictionCurve wf = new WheelFrictionCurve(); wf.stiffness = wf.extremumValue = wf.extremumSlip = wf.asymptoteSlip = wf.asymptoteValue = 6; w.coll.forwardFriction = wf; w.coll.sidewaysFriction = wf; w.coll.radius = wheelRadius; } wheelY = wheels[0].graphic.localPosition.y; gear = 1; }
//Hier worden de eigenschappen aan de wiel gegeven en collider aangemaakt WheelData SetWheelParams(Transform wheel, float maxSteer, bool motor) { WheelData result = new WheelData(); // the container of wheel specific data result.startRot = wheel.localRotation.eulerAngles; GameObject go = new GameObject("WheelCollider"); go.transform.parent = transform; // the car, not the wheel is parent go.transform.position = wheel.position; // match wheel pos WheelCollider col = (WheelCollider)go.AddComponent(typeof(WheelCollider)); col.motorTorque = 0.0f; // Nu wordt alles in Wheeldata gezet result.transform = wheel; result.go = go; result.col = col; result.startPos = go.transform.localPosition; // store the current local pos of wheel result.maxSteer = maxSteer; result.motor = motor; return(result); }
static bool IsLeftWheel(Axle axle, WheelData wheel) { // Determin if left or right wheel bool leftWheel = true; if (axle.leftWheel == wheel) { leftWheel = true; } else { if (axle.rightWheel == wheel) { leftWheel = false; } else { Debug.LogError("Wheel not appart of axle"); } } return(leftWheel); }
//awake sai läbi WheelData SetupWheels(Transform wheel, Transform bone) { //2 WheelData result = new WheelData(); GameObject go = new GameObject("Collider_"+wheel.name); //4 go.transform.parent = transform; //5 go.transform.position = wheel.position; //6 go.transform.localRotation = Quaternion.Euler(0,wheel.localRotation.y,0); //7 WheelCollider col = (WheelCollider) go.AddComponent(typeof(WheelCollider));//8 WheelCollider colPref = wheelCollider.GetComponent<WheelCollider>();//9 col.mass = colPref.mass;//10 col.center = colPref.center;//10 col.radius = colPref.radius;//10 col.suspensionDistance = colPref.suspensionDistance;//10 col.suspensionSpring = colPref.suspensionSpring;//10 col.forwardFriction = colPref.forwardFriction;//10 col.sidewaysFriction = colPref.sidewaysFriction;//10 result.wheelTransform = wheel; //11 result.boneTransform = bone; //11 result.col = col; //11 result.wheelStartPos = wheel.transform.localPosition; //11 result.boneStartPos = bone.transform.localPosition; //11 result.startWheelAngle = wheel.transform.localRotation; //11 return result; //12 }
private float CalculateSmoothRpm(WheelData[] w) { //12 float rpm = 0.0f; List<int> grWheelsInd = new List<int>(); //13 for(int i = 0;i<w.Length;i++) { //14 if(w[i].col.isGrounded) { //14 grWheelsInd.Add(i); //14 } } if(grWheelsInd.Count == 0) { //15 foreach(WheelData wd in w) { //15 rpm +=wd.col.rpm; //15 } rpm /= w.Length; //15 } else{ //16 for(int i = 0;i<grWheelsInd.Count;i++) { //16 rpm +=w[grWheelsInd[i]].col.rpm; //16 } rpm /= grWheelsInd.Count; //16 } return rpm; //17 }
private RFRD TrackUpdate(float accel,float steer,WheelDataExt[] WD, GameObject track, ref Vector2 trackTextureOffset, WheelData[] upperWheels, ref float middleRPM) { float delta = Time.fixedDeltaTime; RFRD rfrd = new RFRD(); float trackRpm = 0.0f; trackRpm = CalculateSmoothRpm(WD); middleRPM = trackRpm; float RPMtoDeg = delta * trackRpm * 360.0f / 60.0f; if(wheelsAndBonesAxisSettings.inverseWheelsRotation) RPMtoDeg *=-1.0f; foreach (WheelDataExt w in WD){ w.wheelTransform.localPosition = CalculateWheelOrBonePosition(w.wheelTransform,w.col,w.wheelStartPos,true); w.boneTransform.localPosition = CalculateWheelOrBonePosition(w.boneTransform,w.col,w.boneStartPos,false); w.wheelRotationAngles[wheelsAndBonesAxisSettings.WRAxisPointer] = Mathf.Repeat(w.wheelRotationAngles[wheelsAndBonesAxisSettings.WRAxisPointer] + RPMtoDeg,360.0f); w.wheelTransform.localEulerAngles = w.wheelRotationAngles; rfrd += CalculateMotorForce(w.col,accel,steer); //Debug.Log(rfrd.rotationDamper); } if(trackTextireAnimationSettings.inverseTextureDirection) trackRpm *=-1.0f; trackTextureOffset[trackTextireAnimationSettings.TTAxisPointer] = Mathf.Repeat(trackTextureOffset[trackTextireAnimationSettings.TTAxisPointer] + delta*trackRpm*trackTextureSpeed/60.0f,1.0f); if(track.renderer.material.GetTexture("_MainTex")){ track.renderer.material.SetTextureOffset("_MainTex",trackTextureOffset); } if(track.renderer.material.GetTexture("_BumpMap")){ track.renderer.material.SetTextureOffset("_BumpMap",trackTextureOffset); } foreach (WheelData w in upperWheels){ w.wheelRotationAngles[wheelsAndBonesAxisSettings.WRAxisPointer] = Mathf.Repeat(w.wheelRotationAngles[wheelsAndBonesAxisSettings.WRAxisPointer] + RPMtoDeg,360.0f); w.wheelTransform.localEulerAngles = w.wheelRotationAngles; } return rfrd; }
void CalculateWheelForces(Axle axle, Vector3 wsDownDirection, WheelData wheelData, Vector3 wsAttachPoint, int wheelIndex, int totalWheelsCount, int numberOfPoweredWheels) { float dt = Time.fixedDeltaTime; wheelData.debugText = "--"; // Get wheel world space rotation and axes Quaternion localWheelRot = Quaternion.Euler(new Vector3(0.0f, wheelData.yawRad * Mathf.Rad2Deg, 0.0f)); Quaternion wsWheelRot = transform.rotation * localWheelRot; // Wheel axle left direction Vector3 wsAxleLeft = wsWheelRot * Vector3.left; wheelData.isOnGround = false; wheelRay.direction = wsDownDirection; // Ray cast (better to use shape cast here, but Unity does not support shape casts) float traceLen = axle.lengthRelaxed + axle.radius; wheelRay.origin = wsAttachPoint + wsAxleLeft * wheelWidth; RaycastHit s1 = new RaycastHit(); bool b1 = RayCast(wheelRay, traceLen, ref s1); wheelRay.origin = wsAttachPoint - wsAxleLeft * wheelWidth; RaycastHit s2 = new RaycastHit(); bool b2 = RayCast(wheelRay, traceLen, ref s2); wheelRay.origin = wsAttachPoint; bool isCollided = RayCast(wheelRay, traceLen, ref wheelData.touchPoint); // No wheel contant found if (!isCollided || !b1 || !b2) { // wheel do not touch the ground (relaxing spring) float relaxSpeed = 1.0f; wheelData.compressionPrev = wheelData.compression; wheelData.compression = Mathf.Clamp01(wheelData.compression - dt * relaxSpeed); return; } // Consider wheel radius float suspLenNow = wheelData.touchPoint.distance - axle.radius; Debug.AssertFormat(suspLenNow <= traceLen, "Sanity check failed."); wheelData.isOnGround = true; // // Calculate suspension force // // Spring force - want's go to position 0 // Damping force - want's go to velocity 0 // //////////////////////////////////////////////////////////////////////////////////////////////////// float suspForceMag = 0.0f; // Positive value means that the spring is compressed // Negative value means that the spring is elongated. wheelData.compression = 1.0f - Mathf.Clamp01(suspLenNow / axle.lengthRelaxed); wheelData.debugText = wheelData.compression.ToString("F2"); // Hooke's law (springs) // F = -k x // Spring force (try to reset compression from spring) float springForce = wheelData.compression * -axle.stiffness; suspForceMag += springForce; // Damping force (try to reset velocity to 0) float suspCompressionVelocity = (wheelData.compression - wheelData.compressionPrev) / dt; wheelData.compressionPrev = wheelData.compression; float damperForce = -suspCompressionVelocity * axle.damping; suspForceMag += damperForce; // Only consider component of force that is along the contact normal. float denom = Vector3.Dot(wheelData.touchPoint.normal, -wsDownDirection); suspForceMag *= denom; // Apply suspension force Vector3 suspForce = wsDownDirection * suspForceMag; AddForceAtPosition(suspForce, wheelData.touchPoint.point); // // Calculate friction forces // //////////////////////////////////////////////////////////////////////////////////////////////////// /// Vector3 wheelVelocity = rb.GetPointVelocity(wheelData.touchPoint.point); // Contact basis (can be different from wheel basis) Vector3 c_up = wheelData.touchPoint.normal; Vector3 c_left = (s1.point - s2.point).normalized; Vector3 c_fwd = Vector3.Cross(c_up, c_left); // Calculate sliding velocity (velocity without normal force) Vector3 lvel = Vector3.Dot(wheelVelocity, c_left) * c_left; Vector3 fvel = Vector3.Dot(wheelVelocity, c_fwd) * c_fwd; Vector3 slideVelocity = (lvel + fvel) * 0.5f; // Calculate current sliding force Vector3 slidingForce = (slideVelocity * rb.mass / dt) / (float)totalWheelsCount; if (debugDraw) { Debug.DrawRay(wheelData.touchPoint.point, slideVelocity, Color.red); } float laterialFriction = Mathf.Clamp01(axle.laterialFriction); float slipperyK = 1.0f; //Simulate slippery tires if (afterFlightSlipperyTiresTime > 0.0f) { float slippery = Mathf.Lerp(1.0f, axle.afterFlightSlipperyK, Mathf.Clamp01(afterFlightSlipperyTiresTime)); slipperyK = Mathf.Min(slipperyK, slippery); } if (brakeSlipperyTiresTime > 0.0f) { float slippery = Mathf.Lerp(1.0f, axle.brakeSlipperyK, Mathf.Clamp01(brakeSlipperyTiresTime)); slipperyK = Mathf.Min(slipperyK, slippery); } float handBrakeK = GetHandBrakeK(); if (handBrakeK > 0.0f) { float slippery = Mathf.Lerp(1.0f, axle.handBrakeSlipperyK, handBrakeK); slipperyK = Mathf.Min(slipperyK, slippery); } /* * if (slipperyK < 0.99f) * { * Debug.Log(string.Format("Slippery {0:F2}", slipperyK)); * } */ laterialFriction = laterialFriction * slipperyK; // Simulate perfect static friction Vector3 frictionForce = -slidingForce * laterialFriction; // Remove friction along roll-direction of wheel Vector3 longitudinalForce = Vector3.Dot(frictionForce, c_fwd) * c_fwd; // Apply braking force or rolling resistance force or nothing bool isBrakeEnabled = (wheelIndex == WHEEL_LEFT_INDEX) ? axle.brakeLeft : axle.brakeRight; bool isHandBrakeEnabled = (wheelIndex == WHEEL_LEFT_INDEX) ? axle.handBrakeLeft : axle.handBrakeRight; if (isBrakeEnabled || isHandBrakeEnabled) { float clampedMag = Mathf.Clamp(axle.brakeForceMag * rb.mass, 0.0f, longitudinalForce.magnitude); Vector3 brakeForce = longitudinalForce.normalized * clampedMag; if (isHandBrakeEnabled) { // hand brake are not powerful enough ;) brakeForce = brakeForce * 0.8f; } longitudinalForce -= brakeForce; } else { // Apply rolling-friction (automatic slow-down) only if player don't press to the accelerator if (!isAcceleration && !isReverseAcceleration) { float rollingK = 1.0f - Mathf.Clamp01(axle.rollingFriction); longitudinalForce *= rollingK; } } frictionForce -= longitudinalForce; if (debugDraw) { Debug.DrawRay(wheelData.touchPoint.point, frictionForce, Color.red); Debug.DrawRay(wheelData.touchPoint.point, longitudinalForce, Color.white); } // Apply resulting force AddForceAtPosition(frictionForce, wheelData.touchPoint.point); // Engine force if (!isBrake && axle.isPowered && Mathf.Abs(accelerationForceMagnitude) > 0.01f) { Vector3 accForcePoint = wheelData.touchPoint.point - (wsDownDirection * 0.2f); Vector3 engineForce = c_fwd * accelerationForceMagnitude / (float)numberOfPoweredWheels / dt; AddForceAtPosition(engineForce, accForcePoint); if (debugDraw) { Debug.DrawRay(accForcePoint, engineForce, Color.green); } } // }
// setup wheelcollider for given wheel data // wheel is the transform of the wheel // maxSteer is the angle in degrees the wheel can steer (0f for no steering) // motor if wheel is driven by engine or not WheelData SetWheelParams(Transform wheel, float maxSteer, JWheelType wheeltype) { if (wheel == null) { throw new System.Exception("wheel not connected to script!"); } WheelData result = new WheelData(); // the container of wheel specific data // we create a new gameobject for the collider and move, transform it to match // the position of the wheel it represents. This allows us to do transforms // on the wheel itself without disturbing the collider. GameObject go = new GameObject("WheelCollider"); go.transform.parent = transform; // the car, not the wheel is parent go.transform.position = wheel.position; // match wheel pos // create the actual wheel collider in the collider game object WheelCollider col = (WheelCollider) go.AddComponent(typeof(WheelCollider)); col.motorTorque = 0.0f; // store some useful references in the wheeldata object result.transform = wheel; // access to wheel transform result.go = go; // store the collider game object result.col = col; // store the collider self result.startPos = go.transform.localPosition; // store the current local pos of wheel result.maxSteer = maxSteer; // store the max steering angle allowed for wheel result.wheeltype = wheeltype; // store if wheel is connected to engine // see docs, haven't really managed to get this work // like i would but just try out a fiddle with it. WheelFrictionCurve fc = col.forwardFriction; // fc.asymptoteValue = 5000.0f; // fc.extremumSlip = 2.0f; // fc.asymptoteSlip = 20.0f; fc.stiffness = (wheeltype==JWheelType.Front)?fwdStiffnessFront:fwdStiffnessBack; col.forwardFriction = fc; fc = col.sidewaysFriction; // fc.asymptoteValue = 7500.0f; // fc.asymptoteSlip = 2.0f; fc.stiffness = (wheeltype==JWheelType.Front)?swyStiffnessFront:swyStiffnessBack; col.sidewaysFriction = fc; return result; // return the WheelData }
void CalculateWheelVisualTransform(Vector3 wsAttachPoint, Vector3 wsDownDirection, Axle axle, WheelData data, int wheelIndex, float visualRotationRad, out Vector3 pos, out Quaternion rot) { float suspCurrentLen = Mathf.Clamp01(1.0f - data.compression) * axle.lengthRelaxed; pos = wsAttachPoint + wsDownDirection * suspCurrentLen; float additionalYaw = 0.0f; float additionalMul = Mathf.Rad2Deg; if (wheelIndex == WHEEL_LEFT_INDEX) { additionalYaw = 180.0f; additionalMul = -Mathf.Rad2Deg; } Quaternion localWheelRot = Quaternion.Euler(new Vector3(data.visualRotationRad * additionalMul, additionalYaw + data.yawRad * Mathf.Rad2Deg, 0.0f)); rot = transform.rotation * localWheelRot; }
void interplateSyncState() { float deltaMovement = (syncData.position - War.Scene.StreamerManager.GetRealPosition(transform.position)).magnitude; float minSpeed = deltaMovement * 3.0f; float interpSpeed = Mathf.Max(minSpeed, averageSyncSpeed); float needMove = interpSpeed * 0.5f * UnityEngine.Time.deltaTime; float t = needMove / deltaMovement; t = Mathf.Clamp(t, 0.1f, 1.0f); if (deltaMovement <= 0.1f) { Quaternion Q = Quaternion.Euler( ((float)syncData.rotateX) / rotateModifier, ((float)syncData.rotateY) / rotateModifier, ((float)syncData.rotateZ) / rotateModifier); transform.SetPositionAndRotation(War.Scene.StreamerManager.GetTilePosition(syncData.position), Q); } else { Vector3 newPos = Vector3.Lerp(transform.position, War.Scene.StreamerManager.GetTilePosition(syncData.position), t); Quaternion toQ = Quaternion.Euler( ((float)syncData.rotateX) / rotateModifier, ((float)syncData.rotateY) / rotateModifier, ((float)syncData.rotateZ) / rotateModifier); Quaternion Q = Quaternion.Lerp(transform.rotation, toQ, t); transform.SetPositionAndRotation(newPos, Q); //syncT += 0.001f; //syncT = Mathf.Clamp(syncT, 0, 1.0f); } //tran.localRotation = Q; //tran.position = syncData.position; WheelData wd = wheels[(int)Wheels.LeftFront]; wd = wheels[(int)Wheels.RightFront]; rpm = syncData.rpm; float r = (rpm / 60.0f) * Time.deltaTime * 360.0f; Transform lfw_wheel = gameObject.GetComponent <Transform>().Find(wheel_lf); lfw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); if (syncData.steerAngle != 0) { lfw_wheel.localRotation = Quaternion.Euler(lfw_wheel.localRotation.x, syncData.steerAngle, lfw_wheel.localRotation.z); } Transform rfw_wheel = gameObject.GetComponent <Transform>().Find(wheel_rf); rfw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); if (syncData.steerAngle != 0) { rfw_wheel.localRotation = Quaternion.Euler(rfw_wheel.localRotation.x, syncData.steerAngle, rfw_wheel.localRotation.z); } wd = wheels[(int)Wheels.LeftBack]; Transform lbw_wheel = gameObject.GetComponent <Transform>().Find(wheel_lb); r = (rpm / 60.0f) * Time.deltaTime * 360.0f; lbw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); wd = wheels[(int)Wheels.RightBack]; Transform rbw_wheel = gameObject.GetComponent <Transform>().Find(wheel_rb); r = (rpm / 60.0f) * Time.deltaTime * 360.0f; rbw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); //同步轮胎破坏?运动上不用管,只是显示隐藏轮胎皮而已,现在没有轮胎皮给你 //所以后面资源到了再说 }
void Start() { //Destroy existing rigidbody, we don't want anyone to mess with it. if(rigidbody) Destroy(rigidbody); //setup rigidbody gameObject.AddComponent<Rigidbody>(); rigidbody.mass = mass; rigidbody.drag = drag; rigidbody.angularDrag = 0.05f; rigidbody.centerOfMass = new Vector3(rigidbody.centerOfMass.x, cogY, rigidbody.centerOfMass.z); rigidbody.interpolation = RigidbodyInterpolation.Interpolate; // rigidbody.constraints = RigidbodyConstraints.FreezeRotationZ; //start engine noise audio.loop = true; audio.Play(); SMCamera = Camera.main.GetComponent<SmoothFollow>(); //setup wheels wheels=new WheelData[4 + otherWheels.Length]; for(int i=0;i<4 + otherWheels.Length;i++) wheels[i] = new WheelData(); wheels[0].graphic = wheelFL; wheels[1].graphic = wheelFR; wheels[2].graphic = wheelBL; wheels[3].graphic = wheelBR; for(int i=0;i < otherWheels.Length;i++) { wheels[i + 4].graphic = otherWheels[i]; } wheels[0].maxSteerAngle = 30.0f; wheels[1].maxSteerAngle = 30.0f; wheels[2].powered = true; wheels[3].powered = true; wheels[2].handbraked = true; wheels[3].handbraked = true; foreach(WheelData w in wheels) { if(w.graphic == null) Debug.Log("You need to assign all four wheels for the car script!"); if(!w.graphic.transform.IsChildOf(transform)) Debug.Log("Wheels need to be children of the Object with the car script"); w.originalRotation = w.graphic.localRotation; //create collider GameObject colliderObject = new GameObject("WheelCollider"); colliderObject.transform.parent = transform; colliderObject.transform.localPosition = w.graphic.localPosition; colliderObject.transform.localRotation = w.graphic.localRotation; w.coll = colliderObject.AddComponent<WheelCollider>(); w.coll.suspensionDistance = suspensionDistance; JointSpring js = new JointSpring(); js.spring = springs; js.damper = dampers; // w.coll.suspensionSpring.spring = springs; // w.coll.suspensionSpring.damper = dampers; w.coll.suspensionSpring = js; //no grip, as we simulate handling ourselves WheelFrictionCurve forwardwfc = new WheelFrictionCurve(); forwardwfc.stiffness = 0; WheelFrictionCurve sidewaywfc = new WheelFrictionCurve(); sidewaywfc.stiffness = 0; // w.coll.forwardFriction.stiffness = 0; // w.coll.sidewaysFriction.stiffness = 0; w.coll.forwardFriction = forwardwfc; w.coll.sidewaysFriction = sidewaywfc; w.coll.radius = wheelRadius; } //get wheel height (height forces are applied on) // wheelY = wheels[0].graphic.localPosition.y; //find skidmark object skidmarks = FindObjectOfType(typeof(Skidmarks)) as Skidmarks; //shift to first gear = 1; defaultMaxRPM = maxRPM; defaultMaxTorque = maxTorque; carAI = GetComponent<CarAI>(); }
// Update is called once per frame void Update() { getSpeed(); if (enableTest == true && enablePhySimulation == true) { processInput(); } if (enablePhySimulation == false) { if (useInterplationSync == false) { syncState(); } else { interplateSyncState(); } } else { steerAngle = Mathf.Clamp(steerAngle, -maxSteerAngle, maxSteerAngle); float flameOutScale = isFlameout ? 0 : 1.0f; WheelData wd = wheels[(int)Wheels.LeftFront]; WheelCollider lfwc = wd.wc; lfwc.motorTorque = wd.motorTorque * throttle * wd.breaked * flameOutScale; lfwc.brakeTorque = brakeTorque + minBrakeTorque; wd = wheels[(int)Wheels.RightFront]; WheelCollider rfwc = wd.wc; rfwc.motorTorque = wd.motorTorque * throttle * wd.breaked * flameOutScale; rfwc.brakeTorque = brakeTorque + minBrakeTorque; rfwc.steerAngle = steerAngle; lfwc.steerAngle = steerAngle; rpm = lfwc.rpm; float r = (lfwc.rpm / 60.0f) * Time.deltaTime * 360.0f; Transform lfw_wheel = gameObject.GetComponent <Transform>().Find(wheel_lf); lfw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); if (steerAngle != 0) { lfw_wheel.localRotation = Quaternion.Euler(lfw_wheel.localRotation.x, steerAngle, lfw_wheel.localRotation.z); } r = (rfwc.rpm / 60.0f) * Time.deltaTime * 360.0f; Transform rfw_wheel = gameObject.GetComponent <Transform>().Find(wheel_rf); rfw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); if (steerAngle != 0) { rfw_wheel.localRotation = Quaternion.Euler(rfw_wheel.localRotation.x, steerAngle, rfw_wheel.localRotation.z); } wd = wheels[(int)Wheels.LeftBack]; Transform lbw_wheel = gameObject.GetComponent <Transform>().Find(wheel_lb); WheelCollider lbwc = wd.wc; lbwc.motorTorque = wd.motorTorque * throttle * wd.breaked * flameOutScale; r = (lbwc.rpm / 60.0f) * Time.deltaTime * 360.0f; lbwc.brakeTorque = brakeTorque + minBrakeTorque; lbw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); wd = wheels[(int)Wheels.RightBack]; Transform rbw_wheel = gameObject.GetComponent <Transform>().Find(wheel_rb); WheelCollider rbwc = wd.wc; rbwc.motorTorque = wd.motorTorque * throttle * wd.breaked * flameOutScale; r = (rbwc.rpm / 60.0f) * Time.deltaTime * 360.0f; rbwc.brakeTorque = brakeTorque + minBrakeTorque; rbw_wheel.GetChild(0).Rotate(r, 0, 0, Space.Self); updateSyncData(); } }
private WheelData SetupUpperWheels(Transform wheel) { WheelData result = new WheelData(); result.wheelTransform = wheel; result.wheelStartPos = wheel.transform.localPosition; result.wheelRotationAngles = wheel.localEulerAngles; return result; }