1
\$\begingroup\$

I'm moving my character controller using Euler integration like this:

Vector3 originalPos = transform.position;
Vector3 acceleration = Physics.gravity;
velocity += acceleration * Time.deltaTime;
characterController.Move(velocity * Time.deltaTime);

This works consistently on different framerates. I also implemented simple rope physics by pulling the controller back when its outside the radius. I then (on the same frame) calculate the new velocity from the new and old positions.

if (outsideOfRadius)
    Vector3 newPos = anchorPos + (transform.position - anchorPos).normalized * ropeRadius;
    Vector3 oldPosition = transform.position;
    characterController.Move(newPos - oldPosition);
    velocity = (newPos - originalPos) / Time.deltaTime;
}

This is the problematic part because it behaves significantly different on different framerates. This causes problems when my character controller lets go of the rope and tries to land on a platform. The distance covered on 30 fps is less than on say 60 fps or higher.

Is there a way I could make this work more consistently across different framerates?

\$\endgroup\$
1

2 Answers 2

1
\$\begingroup\$

Movement should never be dependent on framerate. Bob Nystrom wrote an excellent summary of how to write a game loop that is independent of framerate. Check it out here. He starts with the most basic game loop then makes incremental improvements, discussing the motivation behind each iteration.

I've added his code here but you should really check the article out because you will learn a lot.

double previous = getCurrentTime();
double lag = 0.0;
while (true)
{
  double current = getCurrentTime();
  double elapsed = current - previous;
  previous = current;
  lag += elapsed;

  processInput();

  while (lag >= MS_PER_UPDATE) {
    update();
    lag -= MS_PER_UPDATE;
  }

  render();
}

In order to benefit from higher framerates what you do is pass the lag to the render function which extrapolates the movement that has probably occurred between updates. This makes the motion smoother and allows better machines to benefit from a higher framerate while maintaining a fixed update rate. This is discussed in-depth in the same game loop article I linked to earlier.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the input, the article is very informative. I'll try and figure out how to do something like this in Unity. \$\endgroup\$
    – vision810
    Commented Nov 18, 2014 at 11:19
1
\$\begingroup\$

You need to separate your games logic from display logic.

Game logic should run at some fixed rate (e.g. 100 ms). Display should query the state of the game and display it at unconnected rate (e.g. 10-20 ms).

That way your display performance never affects the game.

\$\endgroup\$
2
  • \$\begingroup\$ From what I understand using a fixed timestep would essentially lock the framerate for movement. This mean that running the game at a higher framerate wouldn't result in smoother movement right? This has been the main reason I haven't used Unity's FixedUpdate, but perhaps there are other techniques that solve this? \$\endgroup\$
    – vision810
    Commented Nov 18, 2014 at 8:18
  • \$\begingroup\$ When you need smooth movement, you start using interpolation/extrapolation between logic steps. \$\endgroup\$
    – Kromster
    Commented Nov 18, 2014 at 8:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .