I am currently creating a retro, pixelated-looking game. I have it set up so that 1 linear unit = 32 pixels. That would mean that 1 pixel = 1 pixel/32 units = 0.03125 units. I, therefor am altering the characters movement like this:

character.transform.position += new Vector3(0.03125f, 0, 0);

My question is, how do I mathematically use Time.deltaTime as a factor to get framerate independent movement with this setup? Since Time.deltaTime is (hopefully) usually less than 1 (or simply not an integer), the scale is messed up and my character will appear to move in between the emulated “pixels.” I want the movement to be, in essence, rounded or constrained to the “pixel” space of 0.03125 units at a time.

Note : None of this will easily work with gravity and other physics effects, so this may or may not be of much use to use.

I see two choices here.

  1. Check (on every run of Update()) if enough time has passed to allow a character move by one pixel since the last move. If not, don’t move the character. If so move to the nearest “pixel” distance (that is, the nearest multiple of 0.03125). You’ll need to store the time of the last movement for each object you have moving this way.
  2. Take the position updates out of Update, into your own co-routine, which doesn’t fire every frame, but rather only every “pixel frame”, which would be the same time interval as you would be checking for in the first option.

In either case you can make life much easier for yourself by storing the position of moving objects as integer X and Y values separately from the 3D space of Unity, where each int value is 1 pixel, and positioning them in play by multiplying by 0.03125 as you go.

I actually did something similar a while ago. The key is to use two variables, one for the “real” position that you use with Time.deltaTime as usual, then another that’s rounded off to an integer that you actually use for display. As a simple example,

private var myXPos = 0.0;

function Update () {
	myXPos += Time.deltaTime * 5.0;
	transform.position.x = parseInt(myXPos);
}