I've just had a look around, but can't seem to find anything on this (that is relevant). Basically my game is in pixel art, with the PPU of 16. And I've currently settled on a normal, smooth camera follow effect, but I just want to test out how a pixel-snapping camera would look like. So how could I for example, create a grid with each of the cells being the same size as the pixels (the unit value of which I have figured out already), and then make the camera movement snap to those cells, or by that specific unit value that matches a single pixel? And would it be easy to still have the "Vector3.Lerp" functionality in the camera's movement, so that the camera slows down and speeds up, but still moves only in per-pixel values?
If I'm getting you right, I think this should work. You wouldn't need to create a grid, just call this method right after your cam LERP. Basically this figures out what the closest snapping points are relatively to your current camera position, and then rounds to the closest. Code (CSharp): void SnapCamera (Vector3 position) { float x = 0f; //Put in your own cell size float cellSize = 0.02f; //Store the remainder after dividing the current x position by the cellsize float xRemainder = position.x % cellSize; //Figure out to which of the 2 closest points you're going to snap to //Do it by checking if the remainder of x is greater than half the cell size, just like how you normally round numbers if (xRemainder >= cellSize / 2f) { //It's greater than half, means we should round up and keep in mind if x was positive or negative x = position.x >= 0f ? position.x - xRemainder + cellSize : position.x + xRemainder - cellSize; } else { //It's smaller than half, we should round to the lower snapping point x = position.x >= 0f ? position.x - xRemainder : position.x + xRemainder; } //Do the same for y //Reassign the position with the new x and y } It's untested let me know if you run into any issues
Sorry, but I got a bit of a noob question. What arguments should I be declaring when calling the method?
The camera's position. Extend the method to modify the y value the same way and then assign the new x and y back to the camera.
It doesn't seem to be doing anything, though I'm not getting any errors or warnings either. Here's the current code (it's in a script attached to the camera): Code (CSharp): void LateUpdate () { //Setting desiredPosition to the player's position along with an offset Vector3. Vector3 desiredPosition = target.position + offset; //Smoothing between current position and desiredPosition. Vector3 smoothedPosition = Vector3.Lerp (transform.position, desiredPosition, smoothSpeed * Time.deltaTime); SnapCamera(transform.position); transform.position = smoothedPosition; } void SnapCamera (Vector3 position) { float x = 0f; //Put in your own cell size float cellSize = 0.03125f; //Store the remainder after dividing the current x position by the cellsize float xRemainder = position.x % cellSize; //Figure out to which of the 2 closest points you're going to snap to //Do it by checking if the remainder of x is greater than half the cell size, just like how you normally round numbers if (xRemainder >= cellSize / 2f) { //It's greater than half, means we should round up and keep in mind if x was positive or negative x = position.x >= 0f ? position.x - xRemainder + cellSize : position.x + xRemainder - cellSize; } else { //It's smaller than half, we should round to the lower snapping point x = position.x >= 0f ? position.x - xRemainder : position.x + xRemainder; } //Do the same for y float y = 0f; //Store the remainder after dividing the current y position by the cellsize float yRemainder = position.y % cellSize; //Figure out to which of the 2 closest points you're going to snap to //Do it by checking if the remainder of y is greater than half the cell size, just like how you normally round numbers if (yRemainder >= cellSize / 2f) { //It's greater than half, means we should round up and keep in mind if y was positive or negative y = position.y >= 0f ? position.y - yRemainder + cellSize : position.y + yRemainder - cellSize; } else { //It's smaller than half, we should round to the lower snapping point y = position.y >= 0f ? position.y - yRemainder : position.y + yRemainder; } //Reassign the position with the new x and y position.x = x; position.y = y; } I tried doing things like putting the method call after the "transform.position = smoothedPosition;" line, taking that line out, etc. But the camera still just behaves normally.
Send "smoothedPosition" into the SnapCamera method instead of transform.position. Basically what the method does is it adjusts whatever position you pass and snaps it to the closest vertex of the cell its in. At the end, of "SnapCamera", what I mean by assign the position is that you should let the camera know that the x and y you just created are its new position. Just add this line. Code (CSharp): transform.position = new Vector3 (x, y, transform.position.z); Also, make sure you delete the line "transform.postition = smoothedPosition" after you call snapcamera since it will revert the camera's position to "smoothedPosition" instead of the newly assigned vector.
It seems to be working, in that it snaps to the cell value, but it doesn't seem to at all have the properties of the "smoothedPosition". When you say "Send "smoothedPosition" into the SnapCamera method instead of transform.position", do you mean like this: Code (CSharp): SnapCamera(smoothedPosition); Or do you mean, put the whole Vector3 into the actual method? The camera has some strange behaviors right now, like when I walk a bit to the left, the smooth effect does activate, and it causes the camera to shake non-stop even when the player and camera are standing still. It doesn't happen when I walk to right. I made a new scene and removed everything aside from the player, camera, and a quad for the player to walk on, but it still happens.
Well currently all that I changed is that method call, hence why I asked wheher it's what I'm supposed to do. Where about would I put the "smoothedPosition" Vector3 within the method?
Code (CSharp): void LateUpdate () { Vector3 desiredPosition = target.position + offset; Vector3 smoothedPosition = Vector3.Lerp (transform.position, desiredPosition, smoothSpeed * Time.deltaTime); transform.position = GetSnappedPosition (smoothedPosition); } Vector3 GetSnappedPosition (Vector3 position) { float x = 0f; float cellSize = 0.03125f; float xRemainder = position.x % cellSize; if (xRemainder >= cellSize / 2f) { x = position.x >= 0f ? position.x - xRemainder + cellSize : position.x + xRemainder - cellSize; } else { x = position.x >= 0f ? position.x - xRemainder : position.x + xRemainder; } float y = 0f; float yRemainder = position.y % cellSize; if (yRemainder >= cellSize / 2f) { y = position.y >= 0f ? position.y - yRemainder + cellSize : position.y + yRemainder - cellSize; } else { y = position.y >= 0f ? position.y - yRemainder : position.y + yRemainder; } return new Vector3 (x, y, position.z); }
Thanks, it works better now. Though I noticed something about the shacking issue that still seems to be happening. What happens right now is when the camera's x or y position reaches the same value as the cellSize variable's value, the Lerp seems to try and override the snapping, and they sort of happen at the same time (resulting in a shaking).
Can you lower the cellSize to something like 0.005f and see if the camera behaves weirdly? Even if it defeats the purpose, it'd help diagnose the code.
The weird behaviour is still there after lowering the cellSize, and it still happens when the position reaches its (cellSize's) value (currently 0.005).
Try this, it should work now. Code (CSharp): Vector3 GetSnappedPosition (Vector3 position) { float x = 0f; float cellSize = 0.03125f; float xRemainder = position.x % cellSize; if (xRemainder >= cellSize / 2f) { x = position.x >= 0f ? position.x - xRemainder + cellSize : position.x - xRemainder - cellSize; } else { x = position.x - xRemainder; } float y = 0f; float yRemainder = position.y % cellSize; if (yRemainder >= cellSize / 2f) { y = position.y >= 0f ? position.y - yRemainder + cellSize : position.y - yRemainder - cellSize; } else { y = position.y - yRemainder; } return new Vector3 (x, y, position.z); }
Sure, that's a lot cleaner. Code (CSharp): Vector3 GetSnappedPosition (Vector3 position) { float cellSize = 0.03125f; float xRemainder = position.x % cellSize; float yRemainder = position.y % cellSize; float x = position.x + (Mathf.Round (xRemainder * 32f) / 32f); float y = position.y + (Mathf.Round (yRemainder * 32f) / 32f); return new Vector3 (x, y, position.z); } Edit : Fixed
or... Code (CSharp): Vector3 GetSnappedPosition (Vector3 position, float snapPPU = 1f) { float x = Mathf.Round (position.x * snapPPU) / snapPPU; float y = Mathf.Round (position.y * snapPPU) / snapPPU; return new Vector3 (x, y, position.z); }