Force based movement

i want to make force based movement like shown in the following video but in 3d space instead of 2d:

like shown in the video i dont want to apply force in a direction if i have already reached a certain velocity in that direction, but for example if i want to move in the opposite direction than i want to apply force.
how can i acheive this? i have already made some attempts but they have all failed. Here is what i have in code so far:

 private void FixedUpdate()
    {
        rb.maxAngularVelocity = float.MaxValue;
        Vector3 targetAdd = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        targetAdd = soul.transform.TransformDirection(targetAdd);
        //velocity = rb.velocity;
        targetVelocity = (targetAdd * speed) * Time.deltaTime;

        float dot = Vector3.Dot(targetVelocity, rb.velocity);
        print(dot);
        finalVel = targetVelocity;
        if (Mathf.Abs(rb.velocity.x) + Mathf.Abs(rb.velocity.y) + Mathf.Abs(rb.velocity.z) > maxVelocityChange)
        {
            if (dot > 0f)
            {
                finalVel = targetVelocity * dot;
            }
        }
        rb.AddForce(finalVel, ForceMode.VelocityChange);





    }

Maybe there is a typo in there somewhere or i’m just not understanding you correctly, but you always apply a force in the direction you want to move in. So wanting to move in the opposite direction than the one you apply a force to… makes no sense to me.

You should never get inputs inside of FIxedUpdate. Collect inputs in Update and then save them in a local variable you can use in FixedUpdate. This has two advantages. The first one is that you cant miss Inputs. FixedUpdate does not run every frame and as such you could miss player inputs, making the game feel unresponsive. The second advantage to doing this is that you want to absolutely minimize the code run in FixedUpdate. Nothing that does not absolutely have to be in there, should be in there. This is because slowing down FixedUpdate will lead to an exponential slowdown of your entire game (since Unity tries to guarantee that it runs at a fixed timestep), while slowing down Update will only linearly slow down your game. There are some good articles on this as well if you are interrested.
So mostly everything besides actual physics (AddForce and such) can be moves outside of FixedUpdate, but at the very least Inputs should be.

i changed the input to be inupdate, but this still doesnt solve my problem

bump

Yeah well, as i mentioned before, i’m not exactly sure what your problem is, sorry.

It sounds like you want to do movement with forces but you want a “speed limit”. One basic way to do that is to just clamp your velocity vector by a desired maximum at the end of FixedUpdate:

rb.velocity = Vector3.ClampMagnitude(rb.velocity, speedLimit);

This might not meet your needs if the object is allowed to move faster than the speed limit if it’s caused by other things (like getting hit by an explosion or something). So an alternative is to check the current velocity and limit the force you add to the rigidbody only in the direction of the current velocity. Here’s some code lifted from one of my projects to do this:

        Vector3 force = /* normal force calculation */
        float maxSqrThrustVelocity = MaxVelocity * MaxVelocity;
        bool maxVelocityExceeded = rb.velocity.sqrMagnitude > maxSqrThrustVelocity;

        if (maxVelocityExceeded) {
            // subtract the component of this vector that is in the forward direction of motion
            Vector3 forwardComponent = Vector3.Project(force, rb.velocity);
            force -= forwardComponent;
        }
 
        // Then go ahead and add your force
1 Like