11
\$\begingroup\$

I have a car game and the idea is that the player is drunk. I want to have a delayed input from the mouse, where you move the mouse side to side to turn.

How can I setup a constant delay between the input the user gives and the turn amount of the car?

Right now I have this:

h = Mathf.Lerp(h, (((Input.mousePosition.x / Screen.width) * 2) - 1), Time.deltaTime * 2);

What happens is the turn is delayed, but is very slow, in other words, if I move the mouse very fast, the car turns very slowly, but if I crank up the multiplier for Time.deltaTime, the car turns faster, but delay effect is minimized.

How else could I do this?

\$\endgroup\$

2 Answers 2

31
\$\begingroup\$

To simulate a time lag, use a circular buffer to store the last N frames' mouse positions. Store the current mouse position each frame. In your control calculations, use the oldest mouse position from the buffer instead of the current mouse position.

\$\endgroup\$
6
  • 1
    \$\begingroup\$ I solved it actually, I just used a coroutine with a waitforseconds. I would be concerned about performance with this technique, if you have a really fast device, it would have a much lower delay time than something like a mobile. \$\endgroup\$
    – mr-matt
    May 21, 2017 at 17:41
  • 2
    \$\begingroup\$ Note that delaying input like this will change the result depending on the polling rate. \$\endgroup\$
    – Joey
    May 21, 2017 at 18:45
  • 6
    \$\begingroup\$ Matthew, I'm a bit bewildered ... do you really mean performance? The performance penalty of writing a few bytes to memory per frame is perfectly negligible, and you get the mouse position free with every message (on Windows at least). How do you think your coroutine solution works exactly? Who keeps track of how many timers exist, when they expire and which code to execute? It sounds pretty heavyweight. \$\endgroup\$
    – Buster
    May 21, 2017 at 23:03
  • \$\begingroup\$ Oh no, I don't mean the performance of the actual task of the delay, I mean the overall performance. For example, if I take the mouse position of the last 10 frames and run this on a phone and get 20 fps, then the delay would be for 0.5 seconds. However, if I run this on my desktop and get 200 fps, then the delay would only be for 0.05 seconds. Do you see what I mean? \$\endgroup\$
    – mr-matt
    May 21, 2017 at 23:50
  • \$\begingroup\$ You would choose N to avoid that, but the bigger problem is that polling once per frame like this is throwing away a lot of data. Better to handle every mouse event (looks like that's what your answer does). \$\endgroup\$
    – Buster
    May 21, 2017 at 23:56
3
\$\begingroup\$

I ended up using a coroutine, because (from what I understand) the delay will be constant regardless of the performance of the device running the game.

This is my code:

private IEnumerator DelayedInput()
{
    Vector3 a = Input.acceleration;
    Vector2 m = Input.mousePosition;

    yield return new WaitForSeconds(delay);

    accelerometer = Vector3.Lerp(accelerometer, a, Time.deltaTime * turnSpeed);
    mouse = Vector2.Lerp(mouse, m, Time.deltaTime * turnSpeed);
}
\$\endgroup\$
2
  • \$\begingroup\$ This has the advantage of responding to all input (not like my idea of polling every frame). I don't know C# but it seems to me someone somewhere has a lot of bookkeeping to do for all those timers. But if it performs OK and has the feel you want then I like it. \$\endgroup\$
    – Buster
    May 21, 2017 at 23:47
  • \$\begingroup\$ I think this is the better way to do it, I don't think timers will affect your game all that much, of course you could get back to this question with the results of your experience with performance (for future reference). Anyway, you should go ahead and pick this as the answer (this is just a reminder). \$\endgroup\$ May 24, 2017 at 5:32

You must log in to answer this question.

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