Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Simple Rigidbody Tank Controller

Discussion in 'Scripting' started by Decestia, May 24, 2024.

  1. Decestia

    Decestia

    Joined:
    Oct 27, 2021
    Posts:
    7
    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?
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    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. ;)
     
  3. Decestia

    Decestia

    Joined:
    Oct 27, 2021
    Posts:
    7
    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():



     
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    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.
     
  5. Decestia

    Decestia

    Joined:
    Oct 27, 2021
    Posts:
    7
    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.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,369
    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/proxi...ty_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:

    Screenshot 2024-05-25 at 10.06.52 AM.png
     
  7. Decestia

    Decestia

    Joined:
    Oct 27, 2021
    Posts:
    7
    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:



    Here is the issue im encountering with both the set velocity and addforce method:



    My end goal is to combine the wall collision behaviour of setting the velocity as well as the slope behaviour found when using MovePosition.
     
  8. Decestia

    Decestia

    Joined:
    Oct 27, 2021
    Posts:
    7
    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.
     
  9. Decestia

    Decestia

    Joined:
    Oct 27, 2021
    Posts:
    7
    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:

     
  10. Decestia

    Decestia

    Joined:
    Oct 27, 2021
    Posts:
    7
    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.