I'm realitively new to Unity and have a basic understanding of how things work... at least enough to get myself in trouble! ;)
I'm working on a little Unity/Vuforia demo for iOS. I have a baisc car simulation using James Arndt's car tutorial. I have it setup properly and working using a couple of GUITexture that are TouchPhase buttons. The baisc 'drive' functions are gas, brake, left and right. When the ImageTarget is found by the Vuforia ARCamera my car and ground plane appear correctly on the target image.
The steerAngle buttons (left,right) are controlling the wheelcolliders as expected... I can see them rotating back and forth correctly. The problem that I'm having is that the motorInputTouch (gas and brake) buttons aren't working. I've confirmed using Debug.Log that the Touches are being called but they aren't transforming the car position the way they do before I added the ARCamera functions. The gas and brake are supposed to apply forces to the rigidbody to slow it down or speed it up. So the car is being trasnsformed using that method.
I've tried changing the world center mode to various states but nothing seems to fix my issue. Is there something simple that I missing? Does it have anything to do with Gravity or local space vs. world space? As I mentioned the wheel rotation (steerAngle) is working perfectly. I'm including the code for PlayerCar.js and for WheelAlignScript.js in hopes that someone will be able to spot the issue.
Thanks! Appreciate your help!!!
--cy
The PlayerCar.js script:
// These variables allow the script to power the wheels of the car. var FrontLeftWheel : WheelCollider; var FrontRightWheel : WheelCollider; var BackLeftWheel : WheelCollider; var BackRightWheel : WheelCollider; var gasButton : GUITexture; var breakButton : GUITexture; var leftTurnButton : GUITexture; var rightTurnButton : GUITexture; var motorInputTouch : int = 0; var BrakePower : float = 200; // These variables are for the gears, the array is the list of ratios. The script // uses the defined gear ratios to determine how much torque to apply to the wheels. var GearRatio : float[]; var CurrentGear : int = 0; // These variables are just for applying torque to the wheels and shifting gears. // using the defined Max and Min Engine RPM, the script can determine what gear the // car needs to be in. var EngineTorque : float = 230.0; var MaxEngineRPM : float = 3000.0; var MinEngineRPM : float = 1000.0; private var EngineRPM : float = 0.0; function Awake () { gasButton = GameObject.Find("Gas_Pedal").guiTexture; breakButton = GameObject.Find("Break_Pedal").guiTexture; leftTurnButton = GameObject.Find("L_Turn").guiTexture; rightTurnButton = GameObject.Find("R_Turn").guiTexture; } function Start () { // I usually alter the center of mass to make the car more stable. I'ts less likely to flip this way. rigidbody.centerOfMass += Vector3(0, -1, .25); } function Update () { for (var touch : Touch in Input.touches) { if (touch.phase == TouchPhase.Stationary && gasButton.HitTest (touch.position)) { motorInputTouch = 1; } else if (touch.phase == TouchPhase.Ended && gasButton.HitTest) { motorInputTouch = 0; } if (touch.phase == TouchPhase.Stationary && breakButton.HitTest (touch.position)) { BrakePower = 200; } else if (touch.phase == TouchPhase.Ended && breakButton.HitTest) { BrakePower = 0; } if (touch.phase == TouchPhase.Stationary && leftTurnButton.HitTest (touch.position)) { FrontLeftWheel.steerAngle = -15.0; FrontRightWheel.steerAngle = -15.0; } else if (touch.phase == TouchPhase.Ended && leftTurnButton.HitTest) { FrontLeftWheel.steerAngle = 0; FrontRightWheel.steerAngle = 0; } if (touch.phase == TouchPhase.Stationary && rightTurnButton.HitTest (touch.position)) { FrontLeftWheel.steerAngle = 15.0; FrontRightWheel.steerAngle = 15.0; } else if (touch.phase == TouchPhase.Ended && rightTurnButton.HitTest) { FrontLeftWheel.steerAngle = 0; FrontRightWheel.steerAngle = 0; } Debug.Log(TouchPhase); } // Compute the engine RPM based on the average RPM of the two wheels, then call the shift gear function EngineRPM = (FrontLeftWheel.rpm + FrontRightWheel.rpm)/2 * GearRatio[CurrentGear]; ShiftGears(); // set the audio pitch to the percentage of RPM to the maximum RPM plus one, this makes the sound play // up to twice it's pitch, where it will suddenly drop when it switches gears. audio.pitch = Mathf.Abs(EngineRPM / MaxEngineRPM) + 1.0 ; // this line is just to ensure that the pitch does not reach a value higher than is desired. if ( audio.pitch > 2.0 ) { audio.pitch = 2.0; } // finally, apply the values to the wheels. The torque applied is divided by the current gear, and // multiplied by the user input variable. FrontLeftWheel.motorTorque = EngineTorque / GearRatio[CurrentGear] * motorInputTouch; FrontRightWheel.motorTorque = EngineTorque / GearRatio[CurrentGear] * motorInputTouch; BackRightWheel.brakeTorque = BrakePower; BackLeftWheel.brakeTorque = BrakePower; // the steer angle is an arbitrary value multiplied by the user input. //FrontLeftWheel.steerAngle = 10 * Input.GetAxis("Horizontal"); //FrontRightWheel.steerAngle = 10 * Input.GetAxis("Horizontal"); } function ShiftGears() { // this funciton shifts the gears of the vehcile, it loops through all the gears, checking which will make // the engine RPM fall within the desired range. The gear is then set to this "appropriate" value. if ( EngineRPM >= MaxEngineRPM ) { var AppropriateGear : int = CurrentGear; for ( var i = 0; i < GearRatio.length; i ++ ) { if ( FrontLeftWheel.rpm * GearRatio[i] < MaxEngineRPM ) { AppropriateGear = i; break; } } CurrentGear = AppropriateGear; } if ( EngineRPM <= MinEngineRPM ) { AppropriateGear = CurrentGear; for ( var j = GearRatio.length-1; j >= 0; j -- ) { if ( FrontLeftWheel.rpm * GearRatio[j] > MinEngineRPM ) { AppropriateGear = j; break; } } CurrentGear = AppropriateGear; } }
The WheelAlignScript.js script:
// Define the variables used in the script, the Corresponding collider is the wheel collider at the position of // the visible wheel, the slip prefab is the prefab instantiated when the wheels slide, the rotation value is the // value used to rotate the wheel around it's axel. var CorrespondingCollider : WheelCollider; var SlipPrefab : GameObject; public var RotationValue : float = 0.0; function Update () { // define a hit point for the raycast collision var hit : RaycastHit; // Find the collider's center point, you need to do this because the center of the collider might not actually be // the real position if the transform's off. var ColliderCenterPoint : Vector3 = CorrespondingCollider.transform.TransformPoint( CorrespondingCollider.center ); // now cast a ray out from the wheel collider's center the distance of the suspension, if it hit something, then use the "hit" // variable's data to find where the wheel hit, if it didn't, then se tthe wheel to be fully extended along the suspension. if ( Physics.Raycast( ColliderCenterPoint, -CorrespondingCollider.transform.up, hit, CorrespondingCollider.suspensionDistance + CorrespondingCollider.radius ) ) { transform.position = hit.point + (CorrespondingCollider.transform.up * CorrespondingCollider.radius); }else{ transform.position = ColliderCenterPoint - (CorrespondingCollider.transform.up * CorrespondingCollider.suspensionDistance); } // now set the wheel rotation to the rotation of the collider combined with a new rotation value. This new value // is the rotation around the axle, and the rotation from steering input. transform.rotation = CorrespondingCollider.transform.rotation * Quaternion.Euler( RotationValue, CorrespondingCollider.steerAngle, 0); // increase the rotation value by the rotation speed (in degrees per second) RotationValue += CorrespondingCollider.rpm * ( 360/60 ) * Time.deltaTime; // define a wheelhit object, this stores all of the data from the wheel collider and will allow us to determine // the slip of the tire. var CorrespondingGroundHit : WheelHit; CorrespondingCollider.GetGroundHit( CorrespondingGroundHit ); // if the slip of the tire is greater than 2.0, and the slip prefab exists, create an instance of it on the ground at // a zero rotation. if ( Mathf.Abs( CorrespondingGroundHit.sidewaysSlip ) > 1.5 ) { if ( SlipPrefab ) { Instantiate( SlipPrefab, CorrespondingGroundHit.point, Quaternion.identity ); } } }
How to use local Physics in joints? In example the Hinge joint