I think I might have a unique problem, but curious if anyone else is doing it this way, or have a solution to my problem.
I am making a 2D isometric game and have chosen to make it with 3D physics to simulate elevations and the physics more naturally. I have therefore made a “blocky” world with 3D colliders and rotated the camera to an isometric rotation (35,45,0)
Something like this (scene view, but also the camera’s view):
Now come the funky part. Everything has 2D sprites associated with them and every sprite is then rotated to match the camera angle and then offset according to the world height so we still have sorting dependent on elevation. That all works!
However, I believe the internal workings of pixel perfect camera is to snap the movement to pixels. But those pixel snappings don’t take into account a rotation, and because of pythagoras, we just don’t get correct snapping. Each object is snapping differently and it is therefor all dancing around.
Here is the problem shown here is with just the speech bubble indicator. It actually moves in 3D and at the angle to match the camera angle. Disabling the pixel perfect camera makes the bubble go smooth, but then, of course, the other pixels are not perfect (e.g. interlacing problems):
This is also a general problem with all the other sprites (everything you see in the scene), to where it is sea sickness inducing.
What can I do? I would love to not abandon pixel perfection, as I would be sad to have the e.g. interlacing issues.
Hmm I am not so much into 2D stuff, so whatever I say now may be complete BS.
However, you could try to make the camera straight without an angle and rotate the game-world + gravity instead . Maybe this could resolve the problem, I don’t know ^^.
Thanks for the suggestion. That’s actually how I had it for some time but it felt quite silly to combat the standard world Y-up physics and navmesh things, than to rotate the visuals. So I rotated the visuals with this problem instead. It the rotated 3D world, the math became cumbersome (though not impossible, just could never rely on any vectors before they were manipulated to fit the rotated world) but the navmesh was unusable rotated as the nav mesh generator relies on standard Y-up to calculate angles of slopes. (uphills were essentially flat and downhills doubly steep)
I see. Another suggestion: render into a rendertexture and draw the texter using a rawimage with a normal UI camera and apply pixel perfect to that. Don’t know if this would work as you require it but it’s an idea
I am really not so much into this 2D stuff - however you could also try rotating everything - camera and the world with the camera as origin in OnPreCull and revert it back in OnRenderImage… Just another idea^^.
Thanks for taking the time to think about this @Kreshi !
The rendertexture idea I am afraid wouldn’t work as the pixel snapping would not happen on the actual sprites and then it doesn’t matter that the final camera that is looking at the render texture image has pixel snapping. At that point the damage has happened.
Rotating the visuals and the camera in a different lifecycle function is interesting. I am wondering at what step the pixel perfect camera does the pixel snapping. Probably in the update which happens before the camera lifecycle functions.
Another option that I will try out is to disable pixel snapping and make my own pixel snapping based on the euclidian angles and then make sure the orthographic size matches the pixels of the screen (one thing the pixel perfect camera does well). I suspect this could get a performance slog. But no premature optimization, am I right?!
If anyone from Unity with knowledge into the inner workings of the pixel perfect camera and would shine some light on how it works, it would be greatly appreciated. The documentation doesn’t say much
I’m currently experiencing a very similar problem, using 3d meshes for collision/physics and everything else being pixel art overlays:
But I experience a ton of pixel jitter as camera rotation messes up a lot with the math of pixel snapping while calculating in a 3d space. Have you had any luck finding a solution?
After messing around for way longer than I wanted to on this specific problem, I did end up with a solution that seems to have worked if you’re interested:
It has one script you add to the camera, then a script you add to all your objects you need to snap and it handles the rest from there. It seems to take into account camera/object rotation as well which is where my problems were rooted.
An important thing to do when you set this up is to make sure your pivots in your sprites are set to pixel with no floating points.
Hey, I know you may not want to include the pixel perfect camera in your game now, but for anyone searching for answers to this problem, I actually got the solution after a few days thinking on this.
The pixel perfect camera works basically snapping the camera on a grid of pixels divided based on the resolution you insert there. Taking a close look on the code inside the component, this is the function that rounds a Vector3 on the grid:
But this code is not taking into account the rotation of the camera that would rotate this grid of pixels too. So what you would need to do is to rotate the unity’s coordinate system for the Vector3 position using Rotation Matrices according to your cameras’ rotation, then calculate the result vector. After this you would need to “unrotate” the result vector to the default coordinate system. Below is my code doing this:
It is a little messy but you can try to organize it by creating some kind of Matrix class idk
This code is supposed to replace the exact method on URP pixel perfect camera’s component but if you are not using URP, you could also create your own script with this method using the main logic (snap the transform position on the closest pixel on Update() or OnRenderImage()).
To avoid jittering issues with camera or objects movement you would need to use transform.position or translate logic, not rigidbody, and use RoundToPixel() when moving. Also, cinemachine damping would lead to jitter.