- Home /
How do I prevent / deal with input lag on a touch interface?
I am working on a game where the user can draw curves by touching the screen (for Android).
At the moment, the curve lags behind the finger by 1cm even when moving only moderately fast. It always catches up with the finger when the finger slows down enough (so it is not a transformation issue).
To give you an idea of the code, here is a simplified version (that exhibits the same lagging behaviour), where the someObjectInScene follows the finger.
public void Update()
{
//for this, example, ignore all other touches
if(Input.touchCount > 0)
{
newPosition = ConvertScreenToWorld(Input.GetTouch(0).position);
someObjectInScene.transform.position = newPosition;
}
}
In another test, I have only the curve drawing functionality, without the rest of the game. There it seems responsive enough, so this makes me think the lower frame rate of the game influences the responsiveness (although it is not terribly low 25/30 FPS).
Edit: As another test, I added a simple background image on a plane to the test above. The lag becomes somewhat visible. When I add 5-layers of alpha-background (as we use in the actual game), the frame-rate drops enough and I see lag very clearly.
Am I totally off track, missing something?
If not, how can I make the player experience more enjoyable (it is damn annoying - the curve is used to steer things), i.e. how I can I "hide" the lag?
Edit: I experimented a bit with using prediction, but it gives very poor results: it is very jerky, tends to overshoot, and is totally off when the finger is moving along a curve and not just straight.
Edit: Also, there is a very similar game that runs without any visible lag on the same device. This makes it seem like it can't be the hardware (or they are using a cool trick to overcome the problem).
Edit: What we ended up doing: We could never found a good solution. What we did was to make our game run really fast, so that the lag was minimised and not very obvious. This need for very high performance was a big strain on the project, and we had to cut a lot of glitz. When we moved to iPhone, we had a whole new set of performance issues, but the input lag there was not obvious, if present at all.
By any chance, would the lag you are referring to be some sort of jittery movement? If yes, does the object following the 'touched position' have a rigidbody attached to it?
No, the lag seems quite smooth, and there is no rigid body attached to the object. (That that could be the problem in some cases is also interesting).
I see two possible situations for your lag: 1. Touch is up to date when it is called and Update is not called close enough to your render time, meaning lag between when update gets the data and when it goes to screen. This would indicate an abo$$anonymous$$able frame rate and indicates other problems. 2. Touch is not actually up to date which could well be a problem with the interface or hardware and therefore something you can't really fix. Assu$$anonymous$$g your experiment with Touch.deltaTime in Update indicates that Touch was changed right before Update, I suspect that it is a problem beyond fixing.
@skovacs1 Thanks for your insight. I have edited my question with additional information. Dropped frame-rate definitely increases the lag, although it looks like your finger wouldn't be able to move 1cm in 0.04s. [But perhaps I am wrong, the speed of things has fooled my before]. If it is the framerate, that's also means it is basically unsolvable (since we will only be able to optimise up to some point - not enough to remove it).
Has anyone else had any luck with this?
It is frustrating to not be able to have an object mimic finger movement on the screen.
Answer by KurianOfBorg · Dec 23, 2012 at 10:33 AM
There is no solution. This is an inherent problem with all existing Android hardware. The touchscreens have input lag of over 100ms in most cases which causes objects to lag behind your finger by an inch or more at high speeds. The iPhone's input lag hasn't been scientifically recorded anywhere but it feels like a fraction of this.
Answer by captaincrunch80 · May 07, 2012 at 07:35 PM
The first thing I would do is
if(Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Moved) {
// Only then do my stuff
}
This will get rid of a lot of calculations. If the camera is moving at the same time it would be another thing. Maybe then you would have to calc it every frame.
Next give the plane you want to hit a layer for it's own and do a raycast - .
public GameObject someObjectInScene;
int hitPlaneLayerBit;
void Start() {
hitPlaneLayerBit = 1 << LayerMask.NameToLayer ("MyHitPlaneLayer");
}
void Update() {
if(Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Moved) {
Ray ray = playerCam.ScreenPointToRay (Input.touches [0].position);
RaycastHit hit = new RaycastHit ();
if (Physics.Raycast (ray, out hit, 400.0f, hitPlaneLayerBit)) {
someObjectInScene.transform.position = hit.point;
}
}
}
I do not know what your ConvertScreenToWorld() function does behind the scenes, but I think this "behind the scenes" is the lag. Maybe you do a lot of fancy matrix operations there.
If you want to draw on the screen, I would consider drawing into a GUITexture or even use this approach with a hit plane very close to the near clipping plane. The PhysX calculations are really fast.
Answer by creat327 · Feb 08, 2011 at 11:03 PM
i'm having the same issue. I created a custom keyboard and the lag is ridiculous. Were you able to ever go around it?
You should not have put this as an answer :) Check my edited question for what we did.
For something complex as a keyboard, there is no orher way but rendering to a texture and showing that on screen. Otherwise you will get way too many drawcalls if every key is a seperate texture.