Rozdzielczość

Pixel jaki jest, każdy widzi. Można go opisać jednym słowem – uniwersalny.
Oczywiście to w jaki sposób są one wyświetlane zależy od rozdzielczości ekranu,
ale to jest akurat proste – im jest ona większa, tym więcej px zobaczymy.

Jednostka. Hmmm… także prosta sprawa. Opisuje nam wielkość/objętość/inne.
Centymetr, kilogram, metr na sekundę, pixel…

Uwaga, zagadka na dziś:
Jeżeli 1 metr to 100 centymetrów, to ile pixeli to 1 jednostka?

Magia liczb

Problem: gracz może wyjechać poza ekran (kamerę).

Rozwiązanie: ograniczenie ruchu gracza do wnętrza ekranu/kamery.
Można to osiągnąć metodą Mathf.Clamp(aktualna pozycja, min, max).

I wszystko jest spoko i działa.

Dopóki operujemy na tych samych jednostkach…

Jednak rozmiary kamery oraz gracza podawane są w jakiś magicznych liczbach (np. Camera size = 5), a gdy chcemy wprowadzić element UI (np. sidebary) wyrażane w px to pojawia się duży problem. Bo ile pixeli to 8.89 jednostki poziomej kamery? Mam nadzieję że mój biedny rysunek rzuci trochę światła na sprawę:

Ten temat męczył mnie od miesiąca, ale nie mogłem go już dłużej odwlekać.
Zapisałem sobie więc wszystkie informacje, którymi dysponowałem:

  • Rozmiar kamery – 5. Nasza Main Camera posiada właściwość Size. Z moich obserwacji – jest to połowa wysokości. Dlatego łatwiej mi rozbić kamerę na ćwiartki i z nich robić obliczenia (czerwone linie).
  • Aspect Ratio – stosunek wysokości do szerokości. To pierwsza zmienna w naszych obliczeniach. Na ekranach 16:9 wynosi 1.(7), na 4:3 to 1.(3), a jako że tworzymy grę pod wszystkie monitory – trzeba będzie uwzględniać to w obliczeniach. Unity oferuje obliczoną wartość pod Camera.main.aspect
  • Szerokość kamery to jej wysokość * aspect ratio. U nas to 5 * 1.(7) = 8.(8) jednostki. Pamiętajmy że cały czas liczymy dane dla ćwiartki.
  • Szerokości sidebarów są w pixelach – 100 lewy i 200 prawy.
  • Player boundaries – gracz powinien poruszać się w obrębie fioletowego prostokątu. No i tu jest problem bo sidebary są w pixelach a reszta nie.

Pominę w tym miejscu fakt, że możemy skorzystać z gotowych metod kamery Camera.ScreenToViewportPoint, których jest aż 6 (zamienne słowa Screen, World i Viewport). Niestety zwracane były bardzo dziwne liczby, dlatego policzyłem wszystko swoim sposobem. Dokumentacja Unity kuleje w wielu miejscach 🙁

Rozwiązanie

Potrzebujemy dowiedzieć się jednej rzeczy: jaką częścią jednostki jest pixel.
Policzymy to według najprostszej możliwej matematyki – proporcji.

Ile pixeli ma połowa ekranu?
Camera.main.pixelWidth / 2

Ile jednostek ma połowa ekeranu?
Camera.main.orthographicSize * Camera.main.aspect

Ile wynosi jedna jednostka?
Pixele z połowy ekranu / jednostki z połowy ekranu.

Ile jednostek to 100 pixeli?
100 / jedna jednostka.

Koniec. Jak zawsze – duży problem, a rozwiązanie bardzo proste.
A oto jak wyglądają poprawione Player Boundaries (cały skrypt w repo):