Log in or register to post comments

Unity / Vuforia / iOS RigidBody Question

April 9, 2013 - 4:46pm #1

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 );
		}
	}
	
}

 

Unity / Vuforia / iOS RigidBody Question

January 14, 2018 - 2:56pm #8

How to use local Physics in joints? In example the Hinge joint

Unity / Vuforia / iOS RigidBody Question

October 27, 2017 - 12:48am #7

"Use local physics instead of world based physics." How do I use local instead of world based physics? 

Unity / Vuforia / iOS RigidBody Question

March 5, 2017 - 6:31pm #6

God, after reading a plenty of discussions and trying possible solutions,  i FINALLY find the best answer here. Thanks very much, duncanx!

Unity / Vuforia / iOS RigidBody Question

April 24, 2014 - 7:30am #5

If you only have one imagetarget ever, then it doesn't matter what you set world center to as long as it's not set to Camera....so your gravity will be as Unity would normally expect.

Anytime a rigidbody isn't doing something and AR is involved...its 99% because the AR is the thing controlling where the body is. Use an empty gameobject as the child of the imagetarget...and put everything inside of that. Use local physics instead of world based physics. So when you move the car you're moving it only within the scope of that empty gameobject.

Whatever is child'd directly under your imagetarget will be controlled by the position of the imagetarget.

Unity / Vuforia / iOS RigidBody Question

April 24, 2014 - 5:53am #4

Hi

I am facing a similar problem.

Controlling a car while using a rigid body in augmented reality is not easy the car behaves in strange mode.

I have tested the code without augmented reality  just unity and everthing goes smooth.

 

Does anyone tested David suggestions ? or Can give sugestions based on previous experiences ?

Or is just best not to use physics with vuforia ?

 

By the away I have read a lot of people suggesting to set world center mode to NONE

But it isn't listed as opinon in documentation or in the editor

https://developer.vuforia.com/resources/dev-guide/front-camera-support-0

the options available are Specific Target / First Target / Camera

 

Thanks in advance for any help

Best Regards

Ghus

Unity / Vuforia / iOS RigidBody Question

April 9, 2013 - 6:50pm #3

Thanks for the reply David.  I will give these suggestions a shot and let you know how things turn out!!! :)

Unity / Vuforia / iOS RigidBody Question

April 9, 2013 - 6:42pm #2

A  few things to try..

Set your World Center Mode to NONE and test the model by viewing it with the camera directly above the target. This should replicate 'normal' Unity physics.

Try parenting your model with an empty GameObject, and make this GameObject a child of your target, scale and position your model as desired and see if that helps to restore the expected behavior.

You can also experiment w/ the scene's gravity vector to define this for the expected direction of gravity for the model - http://docs.unity3d.com/Documentation/ScriptReference/Physics-gravity.html

The thing to keep in mind about a Vuforia scene is that you are defining the scene origin, via the WCM ( using a  target or the camera ) and the direction of gravity is aligned accordingly. So it's a bit different from a standard Unity scene. For example, you'll notice that when the WCM is define as NONE, that the direction of gravity is always away from the camera,in the direction that you are looking, which can cause unexpected physics based behavior if your are assuming that the gravity vector is independent of the camera perspective.

Log in or register to post comments