# Can't move along local z-axis

I’m trying to move along the local z-axis. I’ve got a linear force, then try to move “forward” like this:

``````Vector3 longitudinalForceVec = (transform.forward) * (10f*longitudinalForce);
Root.rigidbody.AddRelativeForce( longitudinalForceVec );
``````

But, what happens is it will move along the world x-axis and move forward until it reaches the actual world x-axis, then it just moves along that. I’ve tried many other ways to along the GO’s local z axis, but it always either does what I just described or moves along the world z-axis. I don’t get it! What am I doing wrong?

Try this:

``````Vector3 longitudinalForceVec = (transform.forward) * (10f*longitudinalForce);
Root.rigidbody.AddForce( longitudinalForceVec );
``````

That just made it move along the world z-axis.

Do you want to apply a force to a parent along one of it’s child’s forward? I don’t understand exactly what you want to do?

Well, It’s a car, so really, the wheel’s forward and car’s forward is almost virtually the same direction. Really, I guess transform.forward should become Root.transform.forward, but since in my testing case right now, the wheel and root forward is the same.

I think the problem is the transform.forward part. This gives you the object’s forward direction in world space but you are then applying that force relatively. I think you probably just want to change transform.forward for Vector3.forward in your original code (if I understand you correctly). This applies the force in the relative z direction.

(I have made this mistake several times, incidentally!)

That doesn’t work either! (I’ve tried all ready, and I just tried again)

It makes it moves along the world z axis. Is this a bug in Unity?

Perhaps post the entire script? Moving something forward is a pretty basic operation, and I’d be surprised if you’d found some case where Unity does it improperly.

Yeah, sure. It’s kind of messy though. I’m going going to paste the part that only applies to the problem.

(if you want to see it with syntax coloring: http://rafb.net/p/0DXppS19.html)

``````public void UpdateWheel( float torque, float steer, float brake, CarControl.DriveType driveType )
{
RaycastHit hit;
Vector3 down = Root.transform.TransformDirection(Vector3.down);
if( Physics.Raycast (transform.position, down, out hit, suspensionDistance + radius)  hit.collider.transform.root != transform.root )
{
float slipRatio = CalcSlipRatio();
float longitudinalForce = LongitudinalForce( slipRatio, Root.rigidbody.mass );
//float lateralForce = LateralForce( steer, Root.rigidbody.mass )*4;
longitudinalForce += ((torque-brake)/radius);

Vector3 longitudinalForceVec = (Root.transform.forward) * (10f*longitudinalForce);
//Vector3 lateralForceVec = graphicalWheel.right * lateralForce;

//Root.rigidbody.AddForceAtPosition( longitudinalForceVec, hit.point );
Root.rigidbody.AddForce( longitudinalForceVec );
//Root.rigidbody.AddRelativeForce( longitudinalForceVec );
//Root.rigidbody.AddTorque( Vector3.up*(-lateralForce*radius) );
}

if( wheelType == WheelType.FRONTWHEEL)
UpdateTransform( steer, driveType );
else
UpdateTransform( 0.0f, driveType );

}

/* Load is in KiloNewton */
private float LongitudinalForce( float slipRatio, float load )
{
float Fz = ((load * 9.8f) * 0.0001f)*0.25f; // Load as KiloNewtons (multiply by .25 because we assume each tire supports 1/4 of the car)
float peakFrictionCoeff = b.i1 * Fz + b.i2;

float D = peakFrictionCoeff * Fz; // Peak value of curve in Newtons
float B = ((b.i3*Fz+b.i4)*Mathf.Exp(-b.i5*Fz))/b.i0*peakFrictionCoeff;
float S = 100*slipRatio+b.i9*Fz+b.i10; // Slip percent
float E = b.i6*(Fz*Fz)+b.i7*Fz+b.i8;

float Fx = D*Mathf.Sin(b.i0*Mathf.Atan(S*B+E*(Mathf.Atan(S*B)-S*B))); // Force in Newtons

return Fx;
}

private float CalcSlipRatio()
{
// Possible way:
Vector3 localVel = Root.transform.InverseTransformDirection(Root.rigidbody.velocity);
float max_v = Mathf.Max(Mathf.Abs(Root.rigidbody.angularVelocity.magnitude*radius), Mathf.Abs(localVel.y) );
if( max_v < Mathf.Epsilon ) max_v = Mathf.Epsilon;
float slipRatio = (Root.rigidbody.angularVelocity.magnitude*radius-localVel.z)/max_v;
return slipRatio;

}
``````

It looks like you are homebrewing your own replacement for WheelColliders. To get the correct behaviour for the forces (applying them at the point where the wheel makes contact) you will have to use Rigidbody.AddForceAtPosition - there is no AddRelativeForceAtPosition method. You can specify the forward force with something like`drive = Vector3.forward * longitudinalForce;` and apply it to the car with`car.rigidbody.AddForceAtPosition(wheel.transform.TransformDirection(drive));`
Obviously, make sure your wheels are pointing forward relative to the parent object.

To make things simpler, you probably want to start without the suspension, side force, braking, etc and just slide the car across the ground to begin with (ie, remove the wheel raycast, and other code). When you are sure that’s working, do the suspension force, then the sideways friction, which will also allow you to steer by pointing the front wheels. A good approach is to create these forces as separate vectors and add them together before applying the overall force with AddForceAtPosition.

Another thing I would recommend for the time being is to set longitudinalForce to a constant or a public variable. That way, you can check your forces are in the right direction without any other complicating factors.

I’ve tried that also, it yields the same thing.

I know another alternative would to be something like this:
*Note: graphicalWheel is a child of the transform, has the same position and rotates, while the transform never rotates.

``````Vector3 crossProduct = Vector3.Cross( graphicalWheel.right, transform.up );
Vector3 longitudinalForceVec = crossProduct * (10f*longitudinalForce);
Root.rigidbody.AddForceAtPosition( longitudinalForceVec, hit.point );
``````

This works kind of better, but there is still this mysterious force acting upon it in the direction of the world z-axis.

My guess is you’re adding the mystery force somewhere else in your code or in another script you’ve forgotten about.

That’s what I thought also, so I checked for my script, disabled the constant force attached to it, and checked for any physics material, and after that nothing changed!

I’ve finally reported a bug…

If I uploaded the project folder, would someone mind just testing to see if this acts the same on their computer? This really makes me wonder if this isn’t just a bug in Unity. I’ve been looking for the problem for 3 days, and I cannot figure it out.

I’ve even boiled it down to

``````f( Input.GetKey("up") ) Root.rigidbody.AddForce( transform.forward*1000/*, ForceMode.Acceleration*/ );
Debug.DrawRay( transform.position, transform.forward*10 );
``````

And there is still a problem (except, just moving along world z-axis, there is a force acting upon it on both the local and world z-axis)!

So, would someone mind testing, please?

I’ll happily look at your project. The smaller you can get it, the better (for both file size and number of things to go through).

Thanks a lot, here it is. Free large file hosting. Send big files the easy way!

Just to try it out, open the RaceTrackScene and use up and forward (I’ve disabled turning).

bump

Sorry, I looked at it and it doesn’t make any sense to me. All the wheels should be applying the same force in the same direction, yet the car goes all over the place when you hold down the up arrow.

Thanks! At least I know it doesn’t just happen on my machine

Could I look at the project folder? It seems like the link above has run out of time.