Hello,
I’m making a physics-based tank game and am having some issues coming up with a simple rigidbody controller (without using wheel colliders) that has the behaviour i’m looking for.
My initial attempt used MovePosition() and MoveRotation() but this ended up with the tank clipping through objects when it was moving at high speeds (around 12m/s) as well as when it was rotating in smaller areas like corridoors.
My second attempt directly set the rigidbody’s velocity and angular velocity, which fixed the issues from the first attempt but prevented the tank from being affected by gravity, as well as preventing it from going up slopes properly.
I’ve tried using different combinations from both attempts but every time the same issues crop up. Does anyone have any suggestions or a fix?
Enabling continuous collision detection on the tank should fix this. This will perform collision testing between current and next position so an object at high speed won’t tunnel through collisions in cases where the current position were entirely on one side, the next position entirely on the other side of a collision object.
Side note: I checked the max speed of the fastest real world tank, and that’s 25 m/s (90 kmh) on paved road. 
Thanks for the reply, I should’ve prefaced that I already had the collision detection set to continuous, and had tried continuous dynamic as well but still encountered the same problem when MovePosition():
https://www.youtube.com/watch?v=sRBJObtB4Ek
https://www.youtube.com/watch?v=UQ79FVEzeW4
Given the videos I think MovePosition will move the tank ignoring any collision. You may want to try AddForce instead to simulate real physics behaviour. It would be similar to manipulating velocity except this considers all aspects that affect velocity, such as friction and gravity.
Could you provide an example code snippet? I’m experiencing some odd behaviour and i’m unsure how exactly to format this:
body.AddForce(currentSpeed * transform.forward) - Causes the tank to move very slowly.
body.AddForce(currentSpeed * transform.forward, ForceMode.Acceleration) - same as previous.
body.AddForce(currentSpeed * transform.forward * Time.fixedDeltaTime, ForceMode.VelocityChange) - same as previous.
body.AddForce(currentSpeed * transform.forward, ForceMode.VelocityChange) - causes the tank to move way too fast and continues accelerating faster than the currentSpeed.
All of these also seem to not be able to move up slopes.
Oh yes… moar tank games! I love tank games… did you play Battletanx for N64? Your game reminds me of that layout with the ability to look around and fire.
What is annoying about MovePosition is that in the 3D world it will let you penetrate other objects.
To do what CodeSmile suggests, use force, is the solution, but there’s a bit more complication.
One cheesy approach is use a large force along with a higher drag, such that you reach a stable speed that’s reasonable simply by applying that force, then when you remove it you stop quickly. The problem with this approach is that the tank “falls” slowly too, because of the huge drag. You could then implement your own drag that ONLY operates linearly, which isn’t too hard to do. But then it can feel weird because the tank will move faster uphill and downhill… it’s not great.
Another better approach involves using a PD control filter to compute a force that will get you from your current velocity to the target velocity. With the right filter parameters this is a quick way to make something feel pretty good. Here’s my PD filter reference:
https://github.com/kurtdekker/proximity_buttons/blob/master/proximity_buttons/Assets/DemoSpaceship3D/PDFilter.cs
That filter code is used in the DemoSpaceship3D full 3D space craft in order to control yaw/pitch/roll. NOTE: it is NOT used to control spaceship thrust or speed in that example, but the idea is the same: you have a current quantity (in your case speed) and a desired quantity (the speed you WANT to be going) and it computes you a force to make that happen. You need to consider the scales of the force and the filter values to get what you want.
Don’t use a BoxCollider: the corners will get snagged. I usually use a row of CapsuleColliders within the volume of the tank body, some number of them lying down in a row, like crayons in a box. The rounded ends go over obstacles pretty well… looks like this:

I’m not entirely sure how I would implement this approach in context for my project.
The only time I experience this is when not using body.MovePosition(), which has the slope movement that i’m looking for:
https://www.youtube.com/watch?v=_nzeb4TQCsU
Here is the issue im encountering with both the set velocity and addforce method:
https://www.youtube.com/watch?v=J6WM70gwlJ0
My end goal is to combine the wall collision behaviour of setting the velocity as well as the slope behaviour found when using MovePosition.
My main inspiration for this project is World of Tanks, I created a smaller scope project using a top down 2.5d style a while ago because I didn’t want to mess around with the issues created by this current project but since I haven’t been able to find a solution from my own testing and research as of yet i’m hoping to find one here.
I tried using:
void FixedUpdate()
{
Vector3 moveForce = acceleration * body.mass * input.y * body.transform.forward;
if (body.velocity.magnitude < forwardSpeed)
{
body.AddForce(moveForce);
}
else
{
body.velocity = body.velocity.normalized * forwardSpeed;
}
}
But im still not able to drive the tank up slopes as seen in this video:
https://www.youtube.com/watch?v=m_hxl2Fq_X0
If anyone has any suggestions or ideas for fixing these issues it’d be greatly appreciated as everything I’ve tried so far hasn’t come up successful.
I used a modified version of this script to achieve the results i was looking for.