praca_magisterska/latex/tex/implementacja-gry.tex

221 lines
10 KiB
TeX
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\clearpage
\section{Doświadczenia z implementacji gry testowej}
\subsection{Implementacja w Unity}
\label{subsec:impl-unity}
\subsubsection{Środowisko i konfiguracja projektu}
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=1.0\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=1.0\textwidth]{tex/img/unity_hub_editor_view.png}
\caption{Widok edytora Unity.}
\label{fig:unity_hub_editor_view}
\end{figure}
\subsubsection{Architektura systemu}
Implementacja Unity wykorzystuje kilka kluczowych wzorców projektowych:
\paragraph{Wzorzec Bootstrap}
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.
\paragraph{Object Pooling}
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.
\paragraph{Singleton Pattern}
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.
\subsubsection{System spawnu przeciwników}
\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.
\subsubsection{Wyzwania napotkane w Unity}
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}
\subsubsection{Pozytywne aspekty Unity}
\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}
\subsection{Implementacja w Unreal Engine}
\label{subsec:impl-unreal}
\subsubsection{Środowisko i konfiguracja projektu}
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=1.0\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=1.0\textwidth]{tex/img/unreal_editor_view.png}
\caption{Widok edytora Unreal Engine.}
\label{fig:unreal_editor_view}
\end{figure}
\subsubsection{Podejście do grafiki 2D}
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}
\subsubsection{System Blueprintów vs C++}
Unreal oferuje dwa podejścia do programowania logiki gry:
\paragraph{Blueprinty} -- wizualny system skryptowy, który w teorii pozwala na szybkie prototypowanie bez pisania kodu.
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}
\paragraph{C++} -- dla bardziej wydajnościowo krytycznych elementów (jak system object poolingu) zalecane jest użycie C++.
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
\subsubsection{Object Pooling w Unreal}
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.
\subsubsection{Wyzwania napotkane w Unreal}
\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}
\subsubsection{Pozytywne aspekty Unreal}
\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}
\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.