Newbie question: AddForce (set when & where & how often)

Hi guys,

I want to simulate something like a 2D swimming fish with a neuronal network. If the neuronal network says “swim”, i want to simulate a forward thrust as long as the networks keeps on saying “swim”.

Instead of manipulating the objects position & speed directly, i wanted to use unitys physics, because i want to add some other forces later as well. Physics-wise, i would expect the fish to swim with constant force, meaning that it accellerates until the drag in the water equals the forward force. If it stops swimming, i expect it to slow down over time until full stop as a body would behave in water.

My questions:

1.) Even after reading the documentation, I am still confused with the Update-, LateUpdate- and FixedUpdate-methods as well as AddForce. Right now i do something like this:

rb2D.AddRelativeForce(new Vector2(1.0f, 0.0f), ForceMode2D.Impulse); // Is "impulse" the right one?
rb2D.AddTorque(0.1f); // rotate a little (for demonstration purposes)
}```

Is that correct or does it belong into Update? 
And where do i execute the calculations of the neuronal network? Will i call them in the Update method (they are separeted in a non-monobehaviour c# script)?

2.) I want to "fast-forward" my simulation via click on a button (not in real-time then anymore). How is that possible with regards to the above requirements?

Thanks a lot for helping me!
Tom
  1. You add forces in FixedUpdate because FixedUpdate is always called immediately before the physics update. The physics update always happens on a set schedule, so FixedUpdate does as well (default to 50 times per second if I remember correctly).

Update and LateUpdate are called based on frame rate, not time. Frame rate changes with hardware and with the complexity of whatever is happening right then in your game. So between physics updates the Update and LateUpdate methods may be called many times or 0, while FixedUpdate will always be called 1 time before the physics update.

  1. You adjust Time.timeScale. You may also need to adjust Time.fixedDeltaTime (the two pages give conflicting information as to this, so just experiment to see if needed or not).

Use ForceMode2D.Force when calling it inside FixedUpdate. Use Impulse when adding a force when a certain event occurs, like a timer going off for an explosion. This actually may be useful for swimming fish because they do tend to dart around like that.

Attach this to a sprite positioned at the left side of the screen and it will demonstrate a fish swimming like motion:

public class Swim : MonoBehaviour
{
    public float speed = 1.0f;
    public float dartTime = 15.0f;
    public float delay = 5.0f;
    public float scale = 1.0f;

    private float currentTime = 0.0f;
    private Rigidbody2D rb;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        rb.gravityScale = 0;
        rb.drag = 0.3f;
        Time.timeScale = scale;
    }

    private void Update()
    {
        currentTime += Time.deltaTime * delay; //increment a simple timer
        if (currentTime > dartTime)
        {
            currentTime = 0.0f;
            rb.AddForce(Vector2.right * speed, ForceMode2D.Impulse);
        }
    }   

    private void OnGUI()
    {
        GUI.Label(new Rect(10, 10, 200, 20), "Current Velocity : " + rb.velocity.x);
        GUI.Label(new Rect(10, 30, 200, 20), "Timer : " + currentTime);
    }
}

Let me know if you have any questions.

Edit : added a delay and time scale parameter.

Thanks to both of you for your replies!!
@ : You wrote “Use ForceMode2D.Force when calling it inside FixedUpdate” but then you put it inside the Update()?
And where would i update the neural network that decides what to do (where to swim)? In the same method with AddForce, or will i calculate the network more/less often and store the output in a “nextMovementVector” and grab that when i do the addForce?

Let me explain the way I understand it from the documentation, and its kind of confusing at first, and if anyone wants to chime in feel free.

Update() gets called every frame. This means it occurs after all the computations need to be completed in order to generate a new image to be transferred to your screen.

If you have Vsync enabled in your graphics settings it will often not be called any more than 60 times a second because most monitors these days update at that rate. Back in the days of CRT monitors this could vary from 50 to 90 but with modern monitors it seems to stay at 60. If you turn off Vsync, Update() will be called as fast as your machine can process the next frame, which can be dependent on the processor speed, graphics card and available memory.

To see some interesting information press the little Stats button in the upper right of your game window, and to go even deeper check out Window->Analysis->Profiler. Note that if you look at the FPS in the Stats window, that’s the time to render graphics and not the real FPS that represents the rate which Update() gets called. To see an accurate FPS, add an empty game object and then add the first script shown here :

https://wiki.unity3d.com/index.php/FramesPerSecond

Vsync can be adjusted at Edit->Project Settings, then choose Quality. For each quality level at the top, you can choose V Sync Count, under “Other” at the bottom. A V Blank is the time at which your monitor finishes writing an image to your screen. To change the quality for your current project, choose it under the “Default” dropdown at the top.

Ok so with all that being said, Update() can get called at different time intervals on your machine depending on the Quality settings, as well as on any other machine your game runs on. For this reason, when you make changes to values inside the Update() function that get called every time, you multiply those values by Time.deltaTime to compensate. In my example above, again, sorry for the confusion, where I have

rb.AddForce(Vector2.right * speed, ForceMode2D.Impulse);

I’m not multiplying Vector2.right * speed * Time.deltaTime, because that code is not running on every call to Update(). Its only running when the timer completes. This is also the reason why I use ForceMode.Impulse, because its a single event that does not occur every frame.

FixedUpdate() gets called on a continuous fixed interval, by default every 1/50th of a second. If you’re going to add physics forces to bodies on a continual basis, do it inside FixedUpdate() and use ForceMode.Force

You don’t need to use Time.deltaTime here because FixedUpdate() gets called at a consistent time interval.

Now, all that being said, the place you would use Time.deltaTime was when you were modifying values inside the Update() function that get called every time within. (For things that are not physics) In my example above :

currentTime += Time.deltaTime * delay;

that line gets called every time and maintains the consistency of the timer. Technically I could have put everything in FixedUpdate if I wanted to and it would have been fine. I hope I didn’t confuse you more.