Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Need serious help with Pixel Perfect for different 16:9 Resolutions.

Discussion in '2D' started by swingecko, Apr 26, 2023.

  1. swingecko

    swingecko

    Joined:
    Apr 24, 2020
    Posts:
    3
    I'm making a Pixel art 2D Game and I need help with the Pixel Perfect Camera component.
    Here's my problem: my camera orthographic size is working correctly in both 1280x720 and 2560x1440 resolutions, the latter being my monitor's resolution, but not in 1920x1080.
    My game's pixel art has a native resolution of 640x360, and sprites have a value of 32 Pixels Per Unit.
    I choose this native resolution because it should scale correctly with the most commonly used 16:9 resolutions (720, 1080, 1440...), and I decided on a PPU of 32 because it seemed convenient to me, at the time: my Tilemap is divided in a 32x32 grid, after all.


    My Pixel Perfect Camera Settings (Experimental because i'm using 2D URP in 2019.4.28f)

    But here's the problem: my camera orthograpic size is consistent in 720 and 1440, but is noticeably zoomed-in in 1080. This is a big problem for me, because I believe that's the resolution that most players use, and I can't just ignore it.


    Game view with 2560x1440 resolution (orthographic size set to 11,25 by component)


    Game view with 1920x1080 resolution orthographic size set to 8,4375 by component)

    I followed this guide (https://blog.unity.com/games/pixel-perfect-2d) -and many, many others, including other threads here- and used the following formula to understand how the Pixel Perfect Component was working.

    Orthographic size = ((Vert Resolution)/(PPUScale * PPU)) * 0.5

    So, with a PPUScale of 1 (PPU = 32) for a vertical resolution of 720, and a PPUScale of 2 (PPU = 64) for 1440, I get a consistent orthographic size of 11,25, a size that I think fits my game very well.
    But the only way to get this same size for a vertical resolution of 1080, I'd need a PPUScale of 1,5 (PPU = 48). This is obviously not a solution, since by using a PPU of 48 in my Pixel Perfect Camera component, pixels become inconsistent, even if the camera size is the correct one.


    Screen from the Pixel Perfect 2D Guide.

    I understand why this problem is happening, I just don't really know what to do to fix it.

    I tried to set my sprites' PPU at 16, and that does ""fix"" the problem, as in 1920x1080 is now consistent with 720 and 1440. But that fixes the problem only for a specific orthographic size, that is now too small for my game (since all sprites are now bigger, because of the PPU).
    Having separate sets of sprites based on resolutions also seems like a bad fix for me, because I would also have to make another set of values for movement, collisions, etc.

    Is there a way to fix this problem by keeping my PPU at 32? Should I just slightly sacrifice the visual fidelity of 1080p?

    I feel like I've tried everything at this point, and finding this out after having worked on my game for almost 2 years feels very defeating... please help! Is there something I'm not seeing or don't understand?
     
  2. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    595
    Something is very wrong with what you described. Either you didn't configure something like you described or the "Experimental" pixel perfect camera in that old Unity version is very broken. At least in later versions of unity (verified it using 2023.1 and I am quite sure that it works exactly the same in 2020.3 and 2021.3) it works just fine with reference resolution of 640x360 and 32PPU. Didn't test with URP but that shouldn't matter.

    Reference resolution of 640x360 should be perfectly scalable to following resolutions:

    1 * (640x360) = 640x360
    2 * (640x360) = 1280x720
    3 * (640x360) = 1920x1080
    4 * (640x360) = 2560x1440
    6 * (640x360) = 3840x2160

    With those numbers what that article calls "PPU scale" should be 2 at 1280x720, and 3 at 1920x1080 and 4 at 2560x1440. Not 1, 1.5 and 2. And the orthographic resolution exactly 5.625. I think you messed up something when doing calculations.

    When doing initial calculations for pixelart game, PPU doesn't matter. What matters is screen resolution and reference resolution in pixels. PPU only controls how many asset pixels map to single world unit, but as long as camera has the same PPU as sprites it's value doesn't matter. Remember that when you modify PPU in camera settings you also need to modify all your texture assets and possibly scene content to be consistent with camera PPU.


    The actual calculations done by Unity pixel perfect component should be more like this:


    stretched_scaling_factor = (screen_height / reference_height)
    actual_scaling_factor = floor(stretched_scaling_factor) // how many screen pixels wide will one sprite pixel displayed assuming PPU are consistent
    ortho_camera_height = 0.5 * screen_height / (actual_scaling_factor * PPU)

    Actual calculations are a bit more complicated because you need to take into account width and height not just height.

    With 1280x720 and 640x360 as reference resolution that should give

    stretched_scaling_factor = (720/360) = 2
    actual_scaling_factor = floor(2) = 2
    ortho_camera_height= 0.5 * 720/(2 * 32) = 5.625

    With 1920x1080 that gives:

    stretched_scaling_factor = (1080/360) = 3
    actual_scaling_factor = floor(3) = 3
    ortho_camera_height= 0.5 * 1080/(3 * 32) = 5.625

    With a resolution that doesn't scale perfectly you would get something like:
    Screen resolution 1600x900
    stretched_scaling_factor = (900/360) = 2.5
    actual_scaling_factor = floor(2.5) = 2
    ortho_camera_height = 0.5 * 900 / (2 * 32) = 7.03125 // still displaying single sprite pixel as 2x2 screen pixels thus pixel perfect, but the view is slightly wider than at resolutions which are perfect multiple of reference resolution


    If you use cropping mode things are somewhat similar but instead of seeing wider area you see black bars.
     
    swingecko and MaxwellTan like this.
  3. swingecko

    swingecko

    Joined:
    Apr 24, 2020
    Posts:
    3
    Thanks for your reply, this was very helpful in realizing my initial mistake that kind of doomed this set-up from the start: I misinterpreted some things from the pixel perfect Guide, and thought that I could easily scale my orthographic size without too many issues, I didn't know that my native resolution would dictate my camera size.
    I read the Vertical Resolutions table above and balanced my game around 11.25 orthographic size, which is a size that works for 720 and 1440, but not 1080 (obviously).

    So yeah... 5.625 works perfectly with the three resolutions, but sadly the camera is way too zoomed-in for my liking.
    I didn't really know how pixel scaling worked at the start of my project, so I balanced my camera size pretty without too much thought. With an ideal orthographic size of 11.25, you could say that my native resolution is 1280x720, and not 640x360... oh well, my bad.
    I tried a workaround using a RenderTexture but that didn't seem to work either.

    I think that the only practical solution here is to re-make pretty much all my sprites, this time with an actual 640x360 resolution. I'll be careful from now on, but man was it hard to get how all of this works in-engine :(

    Thank you very much for your explanation, I mean it <3
     
  4. MaxwellTan

    MaxwellTan

    Unity Technologies

    Joined:
    Mar 3, 2022
    Posts:
    75
    Hi swingecko, may I know which are the screen resolution, you are interested?
     
    swingecko likes this.
  5. karderos

    karderos

    Joined:
    Mar 28, 2023
    Posts:
    376
    from his posts it seems he wants the same zoom level for 720p and 1080p while staying pixel perfect, basically that the game looks exactly the same no matter the current resolution
     
    swingecko likes this.
  6. swingecko

    swingecko

    Joined:
    Apr 24, 2020
    Posts:
    3
    I'm interested mainly in 720p, 1080p and 1440p!
    For anyone interested, I THINK I fixed this problem "for good". It's not an easy solution, but It'll do.

    Keeping my native resolution of 640x360 and using a PPU of 16 instead of 32, with different, smaller sprites, I get a nice solution, here's a mockup in Aseprite with a grid of 16x16:
    upload_2023-5-2_16-37-1.png

    And here are some in-game tests, orthographic size of 11,25 / resolution 720p:
    upload_2023-5-2_16-37-56.png

    Same orthographic size, resolution 1080p:
    upload_2023-5-2_16-38-22.png

    As you can see, this solution is working and should be pixel perfect, by zooming in very close to my game's main character, there are no distorted pixels (taken in 1080p resolution):
    upload_2023-5-2_16-39-21.png

    So... I should be good to go, I think! My initial mistake was thinking that I could have a camera size bigger than my assets' native resolution. Now I get how it works :)
    I will probably have to use the crop frame feature of the component for other resolutions, but I think that is a common problem in Modern Pixel Art games, right? I just want the common 16:9 resolutions to work correctly.
     
  7. MaxwellTan

    MaxwellTan

    Unity Technologies

    Joined:
    Mar 3, 2022
    Posts:
    75
    Hi swingecko,

    yes, if you want orthographic size of 11.25 for 720p, 1080p and 1440p, 16 PPU will be a good choice