mirror of
https://github.com/kuhyx/praca_magisterska.git
synced 2026-07-04 11:43:16 +02:00
224 lines
10 KiB
TeX
224 lines
10 KiB
TeX
\clearpage
|
|
\section{Doświadczenia z implementacji gry testowej}
|
|
|
|
W~ramach pracy zaimplementowano identyczną grę typu bullet-hell w~obu silnikach, co pozwoliło na bezpośrednie porównanie procesu tworzenia, napotkanych problemów oraz ergonomii pracy z~każdym z~narzędzi. Poniższe podrozdziały dokumentują kluczowe aspekty implementacji oraz wyciągnięte wnioski.
|
|
|
|
\subsection{Implementacja w Unity}
|
|
\label{subsec:impl-unity}
|
|
|
|
Projekt Unity został utworzony w~wersji LTS z~wykorzystaniem standardowego renderera 2D. Instalacja
|
|
silnika na systemie Linux przebiegła bezproblemowo dzięki Unity Hub
|
|
\cite{unity_hub} \cite{unity_hub_download_arch}, który zapewnia spójne
|
|
zarządzanie wersjami edytora i~projektami.
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.8\textwidth]{tex/img/unity_hub_default_screen.png}
|
|
\caption{Ekran powitalny Unity Hub.}
|
|
\label{fig:unity_hub_welcome}
|
|
\end{figure}
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.9\textwidth]{tex/img/unity_hub_editor_view.png}
|
|
\caption{Widok edytora Unity.}
|
|
\label{fig:unity_hub_editor_view}
|
|
\end{figure}
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.9\textwidth]{tex/img/unity_game.png}
|
|
\caption{Widok gry (Unity) -- fragment rozgrywki.}
|
|
\label{fig:unity_game}
|
|
\end{figure}
|
|
|
|
Implementacja Unity wykorzystuje kilka kluczowych wzorców projektowych:
|
|
|
|
Klasa \texttt{GameBootstrap} wykorzystuje atrybut \texttt{[Runtime\-Initialize\-OnLoad\-Method]}
|
|
do zapewnienia, że obiekt \texttt{GameInitializer} istnieje w~scenie przed rozpoczęciem gry.
|
|
Jest to eleganckie rozwiązanie problemu inicjalizacji singletonów w~Unity.
|
|
|
|
System \texttt{BulletPool} stanowi rdzeń optymalizacji wydajnościowej. Zamiast ciągłego tworzenia i niszczenia obiektów pocisków (co generowałoby znaczące obciążenie garbage collectora), pociski są recyklingowane z puli:
|
|
|
|
\begin{lstlisting}[language=C, caption={Fragment implementacji object poolingu w Unity}, label={lst:unity-pool}]
|
|
public Bullet Spawn(Vector2 position, Vector2 direction,
|
|
float speed, float damage)
|
|
{
|
|
Bullet bullet = _pool.Count > 0
|
|
? _pool.Dequeue()
|
|
: Bullet.Create(this, bulletColor, faction);
|
|
_liveBullets.Add(bullet);
|
|
bullet.gameObject.SetActive(true);
|
|
bullet.transform.position = position;
|
|
bullet.Configure(direction, speed, damage, faction);
|
|
return bullet;
|
|
}
|
|
\end{lstlisting}
|
|
|
|
Pula jest wstępnie rozgrzewana (\textit{warm capacity}) podczas inicjalizacji, co eliminuje alokacje podczas rozgrywki.
|
|
|
|
Klasy \texttt{GameDirector} i~\texttt{EnemySpawner} wykorzystują wzorzec Singleton z~właściwością \texttt{Instance},
|
|
zapewniając globalny punkt dostępu do kluczowych systemów gry.
|
|
|
|
|
|
\texttt{EnemySpawner} implementuje system eskalującej trudności poprzez interpolację czasu między spawnami:
|
|
|
|
\begin{lstlisting}[language=C, caption={Interpolacja trudności w Unity}, label={lst:unity-difficulty}]
|
|
float t = _elapsed / totalDuration;
|
|
float delay = Mathf.Lerp(spawnDelayStart, spawnDelayEnd, t);
|
|
\end{lstlisting}
|
|
|
|
Przeciwnicy są definiowani przez strukturę \texttt{EnemyBlueprint}, która zawiera parametry takie jak prędkość, zdrowie, wzorce strzelania i zachowania. To podejście data-driven pozwala na łatwe tworzenie różnorodnych typów wrogów.
|
|
|
|
|
|
Podczas implementacji napotkano następujące wyzwania:
|
|
|
|
\begin{enumerate}
|
|
\item \textbf{Garbage Collection} -- początkowa implementacja bez object poolingu powodowała zauważalne spadki klatek przy dużej liczbie pocisków.
|
|
\item \textbf{Kolejność inicjalizacji} -- konieczność użycia wzorca Bootstrap wynikała z~nieprzewidywalnej kolejności wywoływania metod \texttt{Awake()} i~\texttt{Start()}.
|
|
\item \textbf{Serializacja} -- atrybuty \texttt{[SerializeField]} wymagały starannego rozplanowania, które pola powinny być edytowalne w~inspektorze.
|
|
\item Interfejs użytkownika nie jest odświeżany po otwarciu menu \cite{linux_editor_does_not_redraw} -- wymagało to ręcznego wymuszenia odświeżenia inspektora.
|
|
\end{enumerate}
|
|
|
|
|
|
\begin{itemize}
|
|
\item Natywne wsparcie dla 2D -- dedykowany tryb 2D z odpowiednimi komponentami fizyki (\texttt{Rigidbody2D}, \texttt{Collider2D}).
|
|
\item Hot reload -- możliwość edycji kodu i natychmiastowego testowania zmian.
|
|
\item Intuicyjny inspektor -- łatwa konfiguracja parametrów gry bez rekompilacji.
|
|
\item Bogata dokumentacja C\# i społeczność.
|
|
\item Skupienie się na kodzie -- większość logiki gry zaimplementowana została w kodzie źródłowym co przyśpieszyło proces tworzenia gry.
|
|
\item Dobre wsparcie dla LLM -- unity posiada narzędzie mcp oferującą prostą integrację edytora i narzędzi AI \cite{unity_mcp}.
|
|
\end{itemize}
|
|
\newpage
|
|
\subsection{Implementacja w Unreal Engine}
|
|
\label{subsec:impl-unreal}
|
|
|
|
|
|
Instalacja Unreal Engine na systemie Linux okazała się znacznie bardziej skomplikowana niż w przypadku Unity. Dostępne są dwie ścieżki:
|
|
|
|
\begin{enumerate}
|
|
\item Uzyskanie dostępu do oficjalnego repozytorium GitHub Epic Games i samodzielna kompilacja silnika ze źródeł \cite{unreal_arch_installation_source}.
|
|
\item Pobranie prekompilowanej wersji binarnej \cite{unreal_arch_installation_binary}.
|
|
\end{enumerate}
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.9\textwidth]{tex/img/unreal_choose_project.png}
|
|
\caption{Wybór projektu w Unreal Engine.}
|
|
\label{fig:unreal_choose_project}
|
|
\end{figure}
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.9\textwidth]{tex/img/unreal_editor_view.png}
|
|
\caption{Widok edytora Unreal Engine.}
|
|
\label{fig:unreal_editor_view}
|
|
\end{figure}
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.9\textwidth]{tex/img/unreal_game_view.png}
|
|
\caption{Widok gry (Unreal) -- fragment rozgrywki.}
|
|
\label{fig:unreal_game_view}
|
|
\end{figure}
|
|
|
|
Fundamentalna różnica między Unity a~Unreal w~kontekście gier 2D polega na tym, że Unreal traktuje 2D jako ,,fałszywe 2D'' --
|
|
w~rzeczywistości jest to scena 3D z~zablokowaną trzecią osią i~kamerą ortograficzną. Unity natomiast oferuje dedykowany
|
|
tryb 2D z~wyspecjalizowanymi komponentami.
|
|
|
|
Ta różnica ma praktyczne konsekwencje:
|
|
\begin{itemize}
|
|
\item W Unreal konieczne jest ręczne konfigurowanie kamery ortograficznej.
|
|
\item Fizyka 2D w~Unreal wykorzystuje te same komponenty co 3D, z~ograniczeniami na odpowiednich osiach.
|
|
\item Sprite'y w Unreal są renderowane jako płaskie meshe w przestrzeni 3D.
|
|
\end{itemize}
|
|
|
|
|
|
Unreal oferuje dwa podejścia do programowania logiki gry:
|
|
|
|
|
|
W praktyce korzystanie z nich dla osoby która zna tradycyjne programowanie okazazało się frustrujące ze względu na:
|
|
\begin{itemize}
|
|
\item Problemy z kontrolą wersji.
|
|
\item Trudności w debugowaniu.
|
|
\item Ograniczoną czytelność i skalowalność.
|
|
\item Ograniczenie w funkcjach z którycj można korzytsać.
|
|
\end{itemize}
|
|
|
|
użycie go ostatecznie okazało się bardziej intujcywne i prostsze dla projektu z uwagi na doświadczenie w pisaniu programów w
|
|
tradycyjny sposób
|
|
|
|
|
|
Implementacja object poolingu w~Unreal wymaga innego podejścia niż w Unity.
|
|
Zamiast prostego \texttt{SetActive(true/\allowbreak false)}, Unreal wykorzystuje:
|
|
|
|
\begin{itemize}
|
|
\item \texttt{SetActorHiddenInGame()} -- kontrola widoczności.
|
|
\item \texttt{SetActorEnableCollision()} -- kontrola kolizji.
|
|
\item \texttt{SetActorTickEnabled()} -- kontrola aktualizacji logiki.
|
|
\end{itemize}
|
|
|
|
Ta granularność daje większą kontrolę, ale wymaga więcej kodu do osiągnięcia tego samego efektu.
|
|
|
|
|
|
\begin{enumerate}
|
|
\item \textbf{Brak natywnego 2D} -- konieczność ``symulowania'' środowiska 2D w silniku 3D.
|
|
\item \textbf{Czas kompilacji} -- kompilacja projektów C++ jest znacznie wolniejsza niż kompilacja C\# w Unity.
|
|
\item \textbf{Rozmiar projektu} -- nawet prosty projekt Unreal zajmuje wielokrotnie więcej miejsca na dysku.
|
|
\item \textbf{Dokumentacja} -- dla mniej popularnych zastosowań (jak gry 2D) dokumentacja jest ograniczona.
|
|
\item \textbf{Blueprinty i kontrola wersji} -- pliki Blueprintów są binarne, co utrudnia merge'owanie i code review.
|
|
\end{enumerate}
|
|
|
|
|
|
\begin{itemize}
|
|
\item Potężny system materiałów i efektów wizualnych.
|
|
\item Wbudowane zaawansowane narzędzia profilowania.
|
|
\item Blueprinty umożliwiają szybkie prototypowanie przez osoby nietechniczne.
|
|
\item Doskonałe wsparcie dla grafiki 3D i fotorealizmu.
|
|
\end{itemize}
|
|
|
|
\subsection{Porównanie doświadczeń implementacyjnych}
|
|
|
|
\begin{table}[htbp]
|
|
\centering
|
|
\caption{Porównanie doświadczeń z implementacji gry bullet-hell}
|
|
\label{tab:impl-comparison}
|
|
\begin{tabular}{|l|c|c|}
|
|
\hline
|
|
\textbf{Aspekt} & \textbf{Unity} & \textbf{Unreal Engine} \\
|
|
\hline
|
|
Czas instalacji (Linux) & $\sim$30 min & $\sim$2-4 h \\
|
|
\hline
|
|
Wsparcie natywne 2D & Tak & Nie (symulowane) \\
|
|
\hline
|
|
Język programowania & C\# & C++ / Blueprinty \\
|
|
\hline
|
|
Próg wejścia & Niski & Średni/Wysoki \\
|
|
\hline
|
|
Czas kompilacji & Szybki & Wolny (C++) \\
|
|
\hline
|
|
Object pooling & Prosty & Bardziej złożony \\
|
|
\hline
|
|
Hot reload & Tak & Ograniczony \\
|
|
\hline
|
|
Rozmiar projektu & Mały & Duży \\
|
|
\hline
|
|
\end{tabular}
|
|
\end{table}
|
|
\newpage
|
|
\subsection{Wnioski z implementacji}
|
|
|
|
Doświadczenia z implementacji gry bullet-hell potwierdzają, że wybór silnika powinien być uzależniony od typu projektu:
|
|
|
|
\begin{enumerate}
|
|
\item \textbf{Dla gier 2D} -- Unity oferuje znacznie lepsze wsparcie natywne, niższy próg wejścia i szybszy cykl iteracji.
|
|
\item \textbf{Dla gier 3D AAA} -- Unreal Engine dysponuje lepszymi narzędziami do tworzenia fotorealistycznej grafiki.
|
|
\item \textbf{Dla prototypowania} -- Unity pozwala na szybsze testowanie koncepcji dzięki hot reloadowi i prostszej konfiguracji.
|
|
\item \textbf{Dla zespołów mieszanych} -- Blueprinty Unreal mogą być wartościowe dla współpracy
|
|
z designerami, choć problemy z kontrolą wersji stanowią wyzwanie.
|
|
\end{enumerate}
|
|
|
|
Implementacja gry bullet-hell w~Unity zajęła około 60\% czasu
|
|
potrzebnego na implementację analogicznej funkcjonalności
|
|
w~Unreal Engine, głównie ze względu na natywne wsparcie 2D
|
|
i~prostszy system object poolingu. |