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\$
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.

| improve this answer | |
\$\endgroup\$
  • 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 '17 at 17:41
  • 2
    \$\begingroup\$ Note that delaying input like this will change the result depending on the polling rate. \$\endgroup\$ – Joey May 21 '17 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 '17 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 '17 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 '17 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);
}
| improve this answer | |
\$\endgroup\$
  • \$\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 '17 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\$ – John Hamilton May 24 '17 at 5:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.