Jak zacząć tworzyć gry w Unity i Godot – praktyczny przewodnik dla początkujących

0
72
Rate this post

Spis Treści:

Od pomysłu do pierwszej gry – o co w ogóle chodzi?

Wejście w tworzenie gier w Unity i Godot kusi wizją spektakularnych efektów, ale na starcie chodzi o coś znacznie prostszego: zrozumienie, jak zamienić pomysł w działający, nawet bardzo skromny prototyp. Klucz leży w ograniczeniu ambicji, przynajmniej na pierwsze miesiące, i świadomym wyborze małych projektów, które da się doprowadzić do końca.

Unity i Godot uchodzą czasem za „za duże działa” dla początkujących, bo używają ich studia komercyjne i doświadczeni twórcy. W praktyce oba silniki są przyjazne na start, pod warunkiem że nie próbujesz od razu ich „opanować w całości”. Nie trzeba znać połowy edytora, żeby zrobić prostą platformówkę 2D czy grę typu „kliknij i zbierz monetę”. Wystarczy kilka pojęć: scena, obiekt, komponent/node, skrypt oraz podstawy logiki gier.

W przedziale 3–6 miesięcy regularnej nauki (np. 5–10 godzin tygodniowo) można spokojnie dojść do etapu, w którym:

  • masz 2–4 skończone, bardzo proste gry 2D (np. Pong, prosty runner, platformówka z jednym poziomem),
  • rozumiesz, jak działa scena, fizyka, kolizje i input w wybranym silniku,
  • nie boisz się pisać skryptów, modyfikować kodu i szukać błędów,
  • masz ogólny workflow: od pomysłu, przez prototyp, do małego „release’u” dla znajomych.

Największy zgrzyt pojawia się, gdy marzenie o „własnym Wiedźminie” czy multiplayerowym FPS-ie zderza się z rzeczywistością. Pełnoprawne gry AAA tworzą dziesiątki osób przez lata, z ogromnym budżetem. Debiut w gamedevie to zupełnie inny etap. Tutaj liczy się umiejętność skończenia czegoś małego, co:

  • ma początek i koniec,
  • działa bez krytycznych błędów,
  • ktoś z zewnątrz jest w stanie odpalić i zrozumieć bez instrukcji.

Zdecydowanie bezpieczniejsze i sensowniejsze jest podejście „uczę się robiąc gry”, zamiast „uczę się silnika”. Zamiast losowo klikać w kolejne funkcje Unity czy Godot, lepiej wybrać mikro-projekt i dociągnąć go do końca. Przy okazji pojawią się konkretne problemy: jak poruszać postacią, jak wykryć kolizję, jak policzyć punkty. Szukasz odpowiedzi na te konkretne pytania, a nie „wszystkiego o fizyce” naraz. To diametralnie zmienia tempo nauki.

Przykład: ktoś próbuje „poznać Unity” i ogląda 20 różnych tutoriali, każdy o czymś innym. Po miesiącu nadal nie ma żadnej własnej gry. Ktoś inny wybiera: „chcę zrobić prosty klon Flappy Bird” i szuka tylko informacji potrzebnych do lotu ptaszka, przesuwania przeszkód i liczenia punktów. Po tygodniu ma działający prototyp, a po dwóch pierwszą, skończoną grę. Ten drugi zrozumie silnik i logikę gier dużo szybciej.

Unity vs Godot – który silnik wybrać na początek?

Filozofia obu silników i ogólne różnice

Unity jest potężnym, mocno rozbudowanym narzędziem typu „wszystko w jednym”. Ma ogromny ekosystem, Asset Store, systemy dla 2D, 3D, VR, mobile, konsol. Godot jest lżejszy, modularny, nastawiony na szybkość pracy i otwartość. Najprościej: Unity przypomina duże miasto – głośne, pełne możliwości, czasem chaotyczne; Godot – mniejsze, ergonomiczne miasteczko, gdzie szybciej znajdziesz drogę na rynek.

Oba silniki rozwiązują te same problemy, ale inaczej je nazywają i organizują:

  • Scena: w Unity jest to plik .unity z hierarchią GameObjectów; w Godot – scena to drzewko node’ów w jednym pliku .tscn / .scn, które można instancjonować jak prefab.
  • Input: w Unity działa przez system Input (stary) lub Input System (nowy), w Godot – przez InputMap i metody typu Input.is_action_pressed().
  • Fizyka: Unity ma 2D (Box2D) i 3D (PhysX) z Rigidbody, Colliderami i Materialami; Godot ma własny silnik fizyki z node’ami takimi jak RigidBody2D/3D, CharacterBody2D/3D, CollisionShape.
  • UI: Unity oferuje Canvas i UI Toolkit; Godot ma drzewko node’ów Control ze skalowaniem i layoutami.

Filozofia pracy też jest inna. W Unity myślisz „mam GameObject, dodaję do niego komponenty – w tym skrypty C#”. W Godot myślisz „mam node’y połączone w sceny, do wybranych node’ów podpinam skrypty GDScript/C#”. Efekt końcowy może być podobny, ale sposób organizacji projektu różni się na tyle, że nie opłaca się uczyć obu naraz od zera.

Zalety i ograniczenia Unity na start

Największe atuty Unity dla początkujących:

  • Ogrom ekosystemu – Asset Store, pluginy, gotowe szablony, wsparcie społeczności.
  • Mnóstwo materiałów edukacyjnych – kursy, tutoriale, książki, blogi; praktycznie każdy problem ma już kilka rozwiązań w sieci.
  • Uniwersalność – ten sam silnik do gier na PC, mobile, VR, a nawet aplikacji interaktywnych spoza gamedevu.
  • Język C# – popularny, dobrze udokumentowany, przydatny także w „zwykłym” programowaniu.

Po drugiej stronie skali są wyzwania:

  • Złożony edytor – masa okien, ustawień, systemów. Łatwo się pogubić i „kliknąć za dużo”.
  • Krzywa uczenia C# – jeśli ktoś nigdy nie programował, C# bywa na początku mniej przystępny niż GDScript.
  • Większy narzut mentalny – łatwiej wpaść w pułapkę: „jeszcze tylko nauczę się tego systemu animatora, jeszcze tego, jeszcze tego…”, zamiast robić gry.

Dla wielu osób Unity wygrywa tym, że niemal wszystko, o czym pomyślą, da się znaleźć jako plugin, asset lub przykład. Z drugiej strony, właśnie ta ogromna ilość możliwości potrafi sparaliżować decyzję. Dlatego na początku dobrze się ograniczyć: 2D, prosty pipeline, zero VR, zero online, minimum pluginów.

Zalety i ograniczenia Godot na start

Godot ma inny zestaw plusów, który bardzo dobrze pasuje początkującym:

  • Lekkość i szybkość – mały rozmiar, szybkie uruchamianie, szybkie eksporty, brak zbędnych „klocków” na start.
  • Świetne 2D – prosta konfiguracja, mniej pułapek niż w Unity, sensowny domyślny workflow dla gier 2D.
  • GDScript – składnia podobna do Pythona; prostszy start dla osób, które nie programowały nigdy lub liznęły Pythona w szkole.
  • Open source – brak opłat licencyjnych, możliwość podejrzenia wnętrza silnika, prężna społeczność.

Ograniczenia Godot to głównie:

  • Mniejszy ekosystem – mniej gotowych assetów, pluginów, szablonów.
  • Mniej materiałów po polsku – choć sytuacja poprawia się z roku na rok.
  • Czasem trzeba kombinować samemu – część rozwiązań znajdziesz dopiero w dokumentacji lub na GitHubie, a nie w gotowym video-tutorialu.

Dla osób, które wolą prostotę, szybką iterację i jasny model scen/node, Godot często sprawdza się świetnie jako pierwszy silnik. Szczególnie jeśli głównym celem są gry 2D na PC lub mobile.

Scenariusze wyboru silnika dla różnych profili

Dobre pytanie nie brzmi „który silnik jest lepszy?”, tylko „który lepiej pasuje do mojego profilu i planów na najbliższy rok?”. Kilka typowych scenariuszy:

  • „Programista C#, .NET, backend” – naturalny wybór to Unity. Znajomość C# i środowisk pokroju Visual Studio znacząco przyspiesza start. Łatwiej też później przeskakiwać między projektami komercyjnymi i hobbystycznymi.
  • „Nigdy nie programowałem, chcę zrobić proste gry 2D” – Godot z GDScript będzie łagodniejszy. Mniej konfiguracji, mniej „magii”, prostsza składnia języka.
  • „Celuję w mobile/PC, chcę mieć duży ekosystem i możliwość pracy w studiu” – Unity ma tu przewagę rynkową, choć Godot też zyskuje na popularności.
  • „Interesuje mnie open source, lubię mieć wpływ na narzędzia” – Godot, ze względu na otwartość i społecznościowy charakter rozwoju.

Nie ma tragedii, jeśli po roku uznasz, że wolisz drugi silnik – wiele konceptów przechodzi 1:1: scena, obiekty, kolizje, input. Ważniejsze, żeby przez ten rok faktycznie robić gry, a nie przeskakiwać co tydzień z Unity do Godot i z powrotem.

Niezbędne podstawy przed odpaleniem silnika

Minimalna teoria: współrzędne, obiekty, komponenty, sceny

Silnik gry robi w dużej mierze to samo, co można byłoby napisać ręcznie w kodzie, tylko szybciej i wygodniej. Żeby się w nim odnaleźć, wystarczy kilka kluczowych koncepcji.

Układ współrzędnych – w grach używa się przeważnie:

  • 2D: oś X (poziom), oś Y (pion). W Unity Y rośnie w górę, w Godot 2D domyślnie w dół (górny lewy róg ekranu to 0,0). To częste źródło „magicznych” błędów ruchu postaci.
  • 3D: oś X, Y, Z. W Unity i Godot osie są podobne, ale kierunki kamery domyślnej mogą się różnić.

Obiekty – wszystko, co istnieje w grze, jest obiektem: gracz, wróg, pocisk, moneta, ściana. Obiekty mają położenie, czasem fizykę, sprite’y, animacje.

Komponenty / node’y – zamiast tworzyć tysiąc klas dziedziczących po sobie, silniki stosują kompozycję. W Unity są to komponenty dodawane do GameObjectu (np. Transform, Rigidbody2D, SpriteRenderer). W Godot są to node’y układane w drzewo (np. Node2D, Sprite2D, CollisionShape2D).

Sceny – logiczne „poziomy” lub „ekrany”. W Unity zwykle jedna scena to jeden poziom lub jeden ekran (np. menu, poziom 1, poziom 2). W Godot scena to także „prefab na sterydach” – możesz stworzyć scenę „Enemy” i instancjonować ją wielokrotnie w innych scenach.

Podstawy programowania pod gry – co naprawdę trzeba znać

Żeby ruszyć z pierwszą grą w Unity lub Godot, wystarczy bardzo skromny zestaw umiejętności programistycznych:

  • Zmienne – przechowywanie danych (np. speed, health, score).
  • Typy danych – liczby całkowite i zmiennoprzecinkowe, bool, string.
  • Instrukcje warunkoweif / else, proste porównania (prędkość większa od 0, liczba punktów powyżej progu).
  • Pętlefor, foreach – np. do iteracji po liście wrogów.
  • Funkcje/metody – wydzielanie logiki do osobnych kawałków (np. TakeDamage(), AddScore()).

To naprawdę wystarczy, by zrobić prostą platformówkę czy grę top-down. Nie potrzeba wzorców projektowych, event busów, dependency injection i innych rzeczy, którymi czasem straszy się początkujących. One przydadzą się później, ale nie są warunkiem startu.

Różnica między „umiem C#/Pythona” a „umiem pisać pod silnik”

Znajomość C# lub Pythona to świetny start, ale programowanie w silniku do gier ma swoją specyfikę. Najważniejsze różnice:

  • Cykl życia obiektów – w Unity i Godot skrypty nie działają „same z siebie”, tylko w określonym rytmie silnika: Start(), Update(), _ready(), _process(), _physics_process() itp.
  • Programowanie reaktywne – wiele rzeczy dzieje się „na zdarzenia”: kolizja, wciśnięcie przycisku, sygnał (signal) w Godot.
  • Praca z edytorem – zmienne publiczne w Unity czy eksportowane w Godot są widoczne w inspectorze i często ustawiane myszką, a nie tylko w kodzie.

Ktoś, kto „umiem trochę C#” ale nigdy nie programował w silniku, często ma problem z tym, że logika gry nie jest liniowym skryptem typu „zrób to, potem to, potem to”, tylko siecią współpracujących obiektów, które reagują na siebie wzajemnie. To normalne i po kilku tygodniach takie myślenie wchodzi w krew.

Szybkie odświeżenie C# i GDScript pod Unity i Godot

Jak patrzeć na C# i GDScript „oczami silnika”

Język to narzędzie, a silnik narzuca sposób jego używania. Ten sam C# w Unity i ten sam „pythonopodobny” GDScript w Godot służą trochę innym celom niż kod pisany do konsoli czy backendu.

Dobrym źródłem inspiracji przy wyborze podejścia i technologii może być Tworzenie Gier Komputerowych – Blog internetowy, gdzie sporo tematów jest omawianych z perspektywy praktyków – od technikaliów po biznes i marketing.

W praktyce oznacza to kilka rzeczy:

  • Krótsze skrypty, więcej obiektów – zamiast jednego ogromnego pliku z logiką gry, lepiej mieć wiele małych skryptów podpiętych do konkretnych obiektów (gracz, wróg, drzwi, przycisk UI).
  • Większe znaczenie nazw – metody typu Update(), _process(), OnCollisionEnter2D(), sygnały w Godot – są wywoływane przez silnik po nazwie. To nie „magia”, tylko kontrakt: nazwiesz inaczej, silnik nie zadzwoni.
  • Stan rozbity po scenie – część informacji trzymasz w skryptach, część w inspectorze (np. referencje do innych obiektów, prędkości, kolory). Trzeba przywyknąć do tego, że logika to nie tylko plik .cs czy .gd.

Dobry nawyk na początek: szukać odpowiedzi w dokumentacji silnika, a nie w ogólnych tutorialach do C# czy Pythona. Zamiast „jak zrobić pętlę w C#?”, lepiej „Unity how to move object every frame”. Kod wyjdzie podobny, ale użyje właściwych hooków i klas silnika.

Najprostsze różnice składniowe: C# vs GDScript

Osoba, która liznęła Pythona, zwykle odnajdzie się w GDScript w parę godzin. Dla kogoś z C# różnice mogą wyglądać tak:

// C# w Unity
public class Player : MonoBehaviour
{
    public float speed = 5f;

    void Update()
    {
        float inputX = Input.GetAxis("Horizontal");
        transform.position += new Vector3(inputX * speed * Time.deltaTime, 0, 0);
    }
}
# GDScript w Godot 4
extends CharacterBody2D

@export var speed: float = 300.0

func _physics_process(delta: float) -> void:
    var input_x: float = Input.get_axis("ui_left", "ui_right")
    velocity.x = input_x * speed
    move_and_slide()

Różnice na które dobrze zwrócić uwagę:

  • C# ma klasy, GDScript pracuje na skryptach, które rozszerzają konkretny typ node’a (extends CharacterBody2D).
  • W GDScript nie ma średników, a blok kodu wyznacza wcięcie, jak w Pythonie.
  • Unity opiera ruch często na modyfikowaniu transform.position, w Godot częściej pracuje się na velocity i metodach typu move_and_slide().

Nie chodzi o zapamiętanie wszystkiego od razu, tylko o wyłapanie „jak to się robi w tym silniku”, zamiast próbować na siłę przenosić nawyki z innego środowiska.

Pad do konsoli i kontrolery do gier na drewnianym biurku
Źródło: Pexels | Autor: Egor Komarov

Pierwszy projekt krok po kroku – od pustego ekranu do grywalnego prototypu

Wybór mikro-projektu na start

Największy błąd początkujących to rzucenie się na „RPG z otwartym światem, craftem i multiplayerem”. Lepiej zamknąć ambicje w pudełku i zacząć od czegoś, co da się skończyć w tydzień–dwa popołudniami.

Sprawdzone pomysły:

  • Prosta platformówka 2D – skakanie po platformach, zbieranie monet, jeden typ przeciwnika.
  • Top-down shooter – widok z góry, ruch w czterech kierunkach, strzelanie w stronę kursora lub w kierunku ruchu.
  • Endless runner – postać biegnie w prawo, przeszkody pojawiają się losowo, punktacja za przeżyty czas.

Jeśli to pierwszy projekt, sensowny cel to: jedna mechanika ruchu, jeden sposób zdobywania punktów, jeden sposób przegrywania. Wszystko ponad to traktuj jako „miły dodatek, jeśli starczy sił”.

Zakładanie projektu i pierwsza scena

Niezależnie od silnika, początek wygląda podobnie: nowy projekt, pierwsza scena, pierwszy obiekt.

W Unity typowy zestaw startowy dla gry 2D:

  • Nowy projekt 2D.
  • Scena Main zapisana w katalogu Scenes.
  • GameObject o nazwie Player ze sprite’em i komponentem fizyki (np. Rigidbody2D, BoxCollider2D).

W Godot (2D):

  • Nowy projekt, nowa scena z rootem typu Node2D lub CharacterBody2D.
  • Node Player z podpiętym Sprite2D i CollisionShape2D.
  • Skrypt GDScript dołączony do node’a Player.

Dobry nawyk: od razu porządkować pliki – katalog na sceny, na skrypty, na grafiki. Chaos „ogarnie się później” bardzo lubi zostać na stałe.

Ruch postaci – pierwszy kontakt z inputem i update’em

Ruch jest idealnym pierwszym zadaniem: od razu widać efekty, a przy okazji poznaje się cykl klatek i system wejścia.

W Unity podstawowy ruch w osi X w 2D może wyglądać tak:

public class PlayerMovement : MonoBehaviour
{
    public float speed = 5f;
    private Rigidbody2D rb;

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        float inputX = Input.GetAxisRaw("Horizontal");
        rb.velocity = new Vector2(inputX * speed, rb.velocity.y);
    }
}

W Godot 4 podobna logika ruchu w CharacterBody2D:

extends CharacterBody2D

@export var speed: float = 300.0

func _physics_process(delta: float) -> void:
    var input_x := Input.get_axis("ui_left", "ui_right")
    velocity.x = input_x * speed
    move_and_slide()

Przy takim zadaniu dotykasz od razu kilku ważnych elementów: wejścia (Input), fizyki (Rigidbody2D / CharacterBody2D) i metod wywoływanych co klatkę (Update / _physics_process). Potem łatwiej zrozumieć kolizje czy animacje.

Kolizje i prosta logika gry

Żeby gra „była grą”, samo bieganie nie wystarczy. Potrzebne są zasady: zbieranie punktów, przeszkody, przegrywanie.

Przykład w Unity: gracz zbiera monety.

public class Coin : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            var score = other.GetComponent<PlayerScore>();
            if (score != null)
            {
                score.Add(1);
            }
            Destroy(gameObject);
        }
    }
}

A w Godot można podejść do tego przez sygnały lub przez metodę kolizji:

extends Area2D

signal collected

func _on_body_entered(body: Node) -> void:
    if body.is_in_group("player"):
        collected.emit()
        queue_free()

Następnie inny node (np. GameManager) podpina się do sygnału collected i zwiększa wynik. Dzięki temu od początku uczysz się, że logika jest rozproszona: coś reaguje na kolizję, coś innego przechowuje punkty.

Minimalny interfejs użytkownika: wynik, komunikat „Game Over”

UI to osobny świat, ale na start wystarczy drobny overlay pokazujący wynik i prosty ekran przegranej.

W Unity:

  • Dodaj Canvas, w nim Text (TMP) z TextMeshPro do wyświetlania wyniku.
  • Skrypt ScoreUI, który ma referencję do PlayerScore i aktualizuje tekst w Update() lub na zdarzenie.

W Godot:

  • Utwórz node CanvasLayer, w nim Label na wynik.
  • Skrypt na UI, który nasłuchuje sygnału z GameManagera (np. score_changed) i ustawia label.text.

Nadmiernie rozbudowany interfejs na pierwszą grę zwykle kończy się tym, że UI działa, a sama rozgrywka leży. Lepiej najpierw mieć grywalny rdzeń, a potem dopiero ładne przyciski.

Organizacja projektu i dobre nawyki od pierwszego dnia

Struktura folderów, która nie zabije po tygodniu

Nawet najmniejszy projekt błyskawicznie się rozrasta. Kilka prostych reguł pozwala uniknąć „folderu śmierci” o nazwie New Folder (25).

  • Wydziel katalogi: Scenes, Scripts, Sprites / Art, Audio, Prefabs (Unity) / Scenes/Entities (Godot).
  • Nazwy scen z prefiksem: 01_MainMenu, 10_Level_1, dzięki temu łatwiej utrzymać porządek przy sortowaniu.
  • Skrypty nazywaj tak jak klasy/node’y, których dotyczą: PlayerMovement.cs, EnemyAI.gd, zamiast script1.cs.

Przy kolejnej grze będziesz sobie wdzięczny, że nie musisz zgadywać, który plik „PlatformaNowaFinal2.cs” to właściwa wersja.

Rozdzielanie odpowiedzialności: gracz, przeciwnik, manager

Na starcie kuszące jest wrzucenie całej logiki do jednego skryptu. Działa, ale bardzo krótko. Lepiej od początku przyjąć prostą zasadę: jeden skrypt – jeden główny obowiązek.

Przykładowy podział w prostej platformówce:

  • PlayerMovement – zajmuje się wyłącznie ruchem i skokiem.
  • PlayerHealth – trzyma punkty życia, reaguje na obrażenia.
  • EnemyPatrol – logika ruchu przeciwnika.
  • GameManager – restart poziomu, śledzenie stanu gry, pauza.

To nie są jeszcze „wzorce projektowe”, tylko zdrowy rozsądek: mniejsze kawałki kodu łatwiej zrozumieć i naprawić.

Wersjonowanie: Git nawet dla solo-hobbysty

Nawet jeśli pracujesz sam, system kontroli wersji ratuje skórę częściej, niż się wydaje. Scenariusz „wczoraj działało, dziś nie, nie wiem, co zmieniłem” jest klasykiem.

Podstawowy workflow:

  1. Zainstaluj Git i załóż repo w folderze projektu (może być lokalnie, może być GitHub/GitLab).
  2. Dodaj sensowny .gitignore dla Unity lub Godot (łatwo znaleźć gotowce, które wykluczają pliki tymczasowe i buildy).
  3. Rób commita po każdej sensownej zmianie: „dodany ruch gracza”, „działające zbieranie monet”.

W razie katastrofy możesz cofnąć się do poprzedniej wersji bez szukania „backup_final_poprawa_kopia.zip”.

W tym miejscu przyda się jeszcze jeden praktyczny punkt odniesienia: Scripting w silnikach – C#, GDScript, Lua, Python.

Specyfika pracy w edytorze Unity i Godot

Inspector i hierarchia – twoje główne narzędzia

Większość czasu spędzisz nie w kodzie, ale skacząc między hierarchią sceny a inspektorem.

W Unity:

  • Hierarchy – lista wszystkich obiektów w scenie. Tu tworzysz, grupujesz i usuwasz obiekty.
  • Inspector – pokazuje komponenty wybranego GameObjectu. Tu podłączasz skrypty, ustawiasz wartości publicznych pól, dodajesz komponenty fizyczne czy wizualne.

W Godot:

  • Scene – drzewo node’ów w scenie. Struktura logiczna i „szkielet” gry.
  • Inspector – właściwości aktualnie wybranego node’a, w tym eksportowane zmienne skryptu.
  • Node – zakładka z sygnałami; tu łączysz eventy (np. kliknięcie przycisku, wejście w obszar) z metodami w skryptach.

Im więcej logiki przeniesiesz do inspektora (np. ustawianie prędkości, referencji do obiektów), tym mniej będziesz rekompilować kod przy drobnych zmianach balansu gry.

Prefabrykaty, sceny zagnieżdżone i ponowne użycie

Szybko pojawia się potrzeba wykorzystania tego samego obiektu wiele razy: przeciwnik, moneta, pocisk. Ręczne kopiowanie i poprawianie każdej kopii osobno to prosty sposób na ból głowy.

W Unity rozwiązaniem są prefaby:

  • Tworzysz GameObject z pełną konfiguracją (sprite, collider, skrypt).
  • Przeciągasz go z hierarchii do folderu Project – powstaje prefab.
  • Tworzysz kolejne instancje z prefabu; zmiana w prefabie propaguje się do instancji.

W Godot podobną rolę pełnią sceny instancjonowane:

  • Tworzysz scenę Enemy.tscn z całym drzewem node’ów wroga.
  • W innej scenie (np. poziomie) dodajesz instancję tej sceny jako node.
  • Zmiany w oryginalnej scenie wroga trafiają do wszystkich instancji, o ile nie zostały lokalnie nadpisane.

Na początku może się to wydawać „zaawansowane”, ale im szybciej zaczniesz z tego korzystać, tym mniej czasu stracisz na powtarzalne klikanie.

Debugowanie: logi, podgląd wartości, pauza

Praktyczne techniki debugowania w Unity i Godot

Przy pierwszych projektach sporo czasu schodzi na zgadywanie „czemu to nie działa”. Im szybciej zaprzyjaźnisz się z debugowaniem, tym mniej frustracji i desperackich restartów edytora.

W Unity podstawowy arsenał wygląda tak:

  • Debug.Log(), Debug.LogWarning(), Debug.LogError() – szybki podgląd tego, co dzieje się w kodzie. Np. w metodzie kolizji: Debug.Log($"Zderzenie z: {other.name}");
  • Okno Console – tam lądują logi i błędy. Dobrze od razu filtrować po typach (Error/Warning/Log), żeby nie utonąć w ścianie tekstu.
  • Tryb pauzy – w górnym pasku Play/Pause/Step. Możesz zatrzymać grę i sprawdzić wartości komponentów w Inspectorze w środku akcji.
  • Breakpoints w Visual Studio / Riderze – ustawiasz punkt przerwania, odpalasz grę z debuggera i kod zatrzymuje się w danym miejscu, pozwalając krokować linijka po linijce.

W Godot mechanika jest podobna, choć narzędzia są bardziej zintegrowane z samym edytorem:

  • print(), push_warning(), push_error() – odpowiedniki logów, ostrzeżeń i błędów.
  • Zakładka Debugger – tam pojawiają się błędy, ostrzeżenia i wywołania print() (w konsoli Output).
  • Przycisk Pause i Step – pozwalają zatrzymać grę i wykonywać kod krokowo.
  • Monitorowanie zmiennych – po zatrzymaniu gry można podejrzeć wartości w panelu Variables, a także dodać watches na konkretne pola.

Dobre ćwiczenie: gdy coś nie działa, zamiast „na ślepo” zmieniać parametry, spróbuj najpierw odpowiedzieć sobie logami na trzy pytania: czy metoda się wywołuje, jakie są wejściowe wartości, co wychodzi. To prosta rutyna, która oszczędza godziny.

Domowe biuro z dwoma monitorami do programowania gier
Źródło: Pexels | Autor: Paras Katwal

Rozszerzanie gry: od prototypu do czegoś, co można pokazać

Dodawanie nowych mechanik krok po kroku

Gdy ruch, kolizje i prosty UI działają, łatwo wpaść w pułapkę „dodam wszystko naraz”: przeciwników, skille, inwentarz, czat sieciowy i crafting. Bez litości: jedna mechanika na raz.

Przykładowa ścieżka rozwoju prostej platformówki:

  1. Podstawowy ruch i skok.
  2. Zbieranie monet i licznik punktów.
  3. Przeciwnik z prostym patrolem.
  4. Obrażenia od przeciwnika i system życia gracza.
  5. Prosty system poziomów (przejście do kolejnej sceny po zebraniu X monet lub dojściu do wyjścia).

W Unity każdą nową mechanikę możesz dokleić jako osobny komponent do istniejących obiektów. Przykładowo, dodając system zdrowia gracza, nie ruszasz PlayerMovement, tylko tworzysz nowy skrypt:

public class PlayerHealth : MonoBehaviour
{
    public int maxHealth = 3;
    public int currentHealth;

    void Awake()
    {
        currentHealth = maxHealth;
    }

    public void TakeDamage(int amount)
    {
        currentHealth -= amount;
        if (currentHealth <= 0)
        {
            Die();
        }
    }

    private void Die()
    {
        // wywołaj GameManager, pokaż ekran Game Over itp.
        Debug.Log("Gracz zginął");
    }
}

W Godot podobnie – nowy skrypt na node gracza, bez mieszania w istniejącej logice ruchu:

extends CharacterBody2D

@export var max_health: int = 3
var current_health: int

func _ready() -> void:
    current_health = max_health

func take_damage(amount: int) -> void:
    current_health -= amount
    if current_health <= 0:
        die()

func die() -> void:
    print("Gracz zginął")
    # tu można zawołać GameManager, zmienić scenę itp.

Taki modularny rozwój sprawia, że gdy coś się wysypie przy dodawaniu nowych rzeczy, wiesz, gdzie szukać problemu – w ostatnim, świeżo dopisanym kawałku.

Progresja poziomów: więcej niż jedna scena

Moment przejścia z jednej sceny na kolejną to pierwszy kontakt z zarządzaniem większą strukturą gry.

W Unity podstawą jest SceneManager z przestrzeni nazw UnityEngine.SceneManagement:

using UnityEngine;
using UnityEngine.SceneManagement;

public class LevelExit : MonoBehaviour
{
    [SerializeField] private string nextSceneName;

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            SceneManager.LoadScene(nextSceneName);
        }
    }
}

W edytorze do pola nextSceneName możesz wpisać nazwę kolejnego poziomu. Tyle wystarczy, żeby zbudować prostą kampanię kilku scen.

W Godot sceny zmienia się przez SceneTree:

extends Area2D

@export var next_scene: String = "res://scenes/Level2.tscn"

func _on_body_entered(body: Node) -> void:
    if body.is_in_group("player"):
        get_tree().change_scene_to_file(next_scene)

Kluczowy nawyk: trzymaj nazwy scen w jednym miejscu lub korzystaj z prostego managera poziomów, zamiast rozsiewać „magiczne stringi” po całym projekcie. Podmiana nazwy sceny nie będzie wtedy polowaniem na tekstowe miny.

Zapisywanie danych: proste save/load

Nawet w małych grach pojawia się potrzeba zapisania stanu: liczba odblokowanych poziomów, najlepszy wynik, ustawienia dźwięku.

W Unity najprostsze (choć nie idealne) rozwiązanie to PlayerPrefs:

public static class SaveSystem
{
    private const string HighScoreKey = "HighScore";

    public static void SaveHighScore(int score)
    {
        PlayerPrefs.SetInt(HighScoreKey, score);
        PlayerPrefs.Save();
    }

    public static int LoadHighScore()
    {
        return PlayerPrefs.GetInt(HighScoreKey, 0);
    }
}

Dla małych gier to wystarcza. Przy większych projektach przydaje się zapis do plików JSON lub binarnych, ale na dzień dobry nie ma co wyprzedzać potrzeb.

W Godot sensownym startem jest zapis do pliku w katalogu użytkownika:

extends Node

const SAVE_PATH := "user://save.dat"

func save_high_score(score: int) -> void:
    var file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
    if file:
        file.store_32(score)

func load_high_score() -> int:
    if not FileAccess.file_exists(SAVE_PATH):
        return 0
    var file := FileAccess.open(SAVE_PATH, FileAccess.READ)
    return file.get_32()

Potem można to rozbudować o zapis wielu wartości w słowniku i serializację do JSON, ale na start wystarczy jedna liczba. Lepiej mieć prosty save, który działa, niż rozbudowany system, który ciągle „prawie działa”.

Jeśli chcesz pójść krok dalej, pomocny może być też wpis: Wyzwania testowania VR – na co zwrócić uwagę?.

Grafika, dźwięk i animacje w pierwszych projektach

Skąd brać zasoby i jak ich nie marnować

Większość początkujących nie ma własnego grafika i kompozytora. To normalne. Internet pęka od darmowych assetów – trzeba tylko używać ich z głową.

Popularne źródła:

  • itch.io – sekcje z darmowymi paczkami 2D/3D, często zezwalającymi na użycie w projektach komercyjnych (sprawdzaj licencję).
  • OpenGameArt.org – sporo klasycznych płytek 2D, dźwięków i muzyki.
  • Oficjalne asset store’y: Unity Asset Store, Godot Asset Library – przydatne nie tylko jako grafika, ale też źródło przykładów skryptów.

Na pierwszy projekt zrób sobie „dietę artystyczną”: jedna paczka tilesetów, jeden styl postaci, kilka prostych efektów dźwiękowych. Mieszanie trzech diametralnie różnych stylów graficznych kończy się tym, że gra wygląda jak kolaż z drukarki szkolnej.

Dodawanie sprite’ów i animacji w Unity

Unity ma wygodny pipeline do sprite’ów 2D, choć kilka opcji potrafi na początku zaskoczyć.

Podstawowe kroki:

  1. Wrzuć pliki PNG do folderu Sprites w oknie Project.
  2. Zaznacz sprite w Inspectorze i ustaw Sprite Mode:
    • Single – pojedynczy obrazek.
    • Multiple – sprite sheet; wtedy otwiera się Sprite Editor do cięcia na klatki.
  3. Przeciągnij sprite na scenę – Unity automatycznie tworzy GameObject z komponentem SpriteRenderer.

Do animacji wykorzystuje się zwykle Animator i Animation:

  • Zaznacz obiekt ze SpriteRenderer, otwórz Window > Animation > Animation.
  • Utwórz nowy klip (np. Player_Run) i wklej kolejno klatki animacji (sprite’y) do timeline.
  • Unity automatycznie doda komponent Animator i utworzy kontroler, w którym możesz tworzyć stany (Idle, Run, Jump) i przejścia między nimi.

Ruchową animację łatwo potem przełączać w kodzie:

public class PlayerAnimation : MonoBehaviour
{
    private Animator anim;
    private Rigidbody2D rb;

    void Awake()
    {
        anim = GetComponent<Animator>();
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        bool isRunning = Mathf.Abs(rb.velocity.x) > 0.1f;
        anim.SetBool("IsRunning", isRunning);
    }
}

Kluczowe jest, żeby nie próbować wszystkiego upchnąć w jednym klipie. Lepiej kilka prostych animacji i logiczne przełączanie między nimi, niż jeden wielki, nieczytelny potwór.

Animacje i state machine w Godot

W Godot 4 animacje 2D ogarnia duet AnimationPlayer + opcjonalnie AnimationTree dla bardziej skomplikowanych przejść.

Podstawowy scenariusz:

  • Do gracza dodaj node AnimatedSprite2D (jeśli masz sprite sheet) lub Sprite2D plus AnimationPlayer.
  • W AnimatedSprite2D ustaw Sprite Frames – tam tworzysz animacje złożone z klatek.
  • Alternatywnie, w AnimationPlayer dodaj animacje, a w nich ścieżki zmieniające texture lub inne właściwości.

Prosty przykład sterowania animacją z kodu z użyciem AnimationPlayer:

extends CharacterBody2D

@onready var anim: AnimationPlayer = $AnimationPlayer

func _physics_process(delta: float) -> void:
    var input_x := Input.get_axis("ui_left", "ui_right")
    velocity.x = input_x * 200.0

    if input_x != 0:
        anim.play("run")
    else:
        anim.play("idle")

    move_and_slide()

Gdy projekt zacznie rosnąć, przydaje się AnimationTree z trybem State Machine. Pozwala on wizualnie definiować stany (idle, run, jump, attack) i płynne przejścia między nimi, a potem tylko przełączać stan w kodzie przez animation_tree.set("parameters/state/current", "run"). To krok w stronę bardziej profesjonalnych workflowów, ale nie trzeba się go bać – nie gryzie.

Podstawowe efekty dźwiękowe i muzyka

Dźwięk często robi większe wrażenie niż dodatkowe efekty graficzne. Nawet prosty „pling” przy zebraniu monety i krótka pętla muzyczna potrafią ożywić prosty prototyp.

W Unity większość rzeczy da się ogarnąć jednym komponentem AudioSource i statyczną klasą AudioListener (ta zwykle jest na kamerze).

public class CoinSound : MonoBehaviour
{
    [SerializeField] private AudioClip collectClip;

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            AudioSource.PlayClipAtPoint(collectClip, transform.position);
            Destroy(gameObject);
        }
    }
}

Do muzyki w tle dodajesz AudioSource na osobny obiekt (np. MusicPlayer), włączasz loop i przypinasz klip. Jeśli chcesz, by muzyka nie przerywała się przy zmianie sceny, możesz użyć DontDestroyOnLoad() w skrypcie.

W Godot dźwięk obsługują node’y AudioStreamPlayer i AudioStreamPlayer2D (z uwzględnieniem położenia w świecie).

extends Area2D

@onready var audio: AudioStreamPlayer2D = $AudioStreamPlayer2D

func _on_body_entered(body: Node) -> void:
    if body.is_in_group("player"):
        audio.play()
        queue_free()

Dla muzyki w tle najczęściej używa się AudioStreamPlayer w osobnej scenie typu „global” (autoloader), aby grała niezależnie od zmiany poziomów. Taki node można łatwo ściszyć lub wyciszyć z poziomu opcji.

Wydajność i optymalizacja w małych projektach

Kiedy przejmować się wydajnością, a kiedy odpuścić

Przy pierwszej grze kuszące jest grzebanie w każdym ustawieniu „dla wydajności”. Zazwyczaj nie ma to sensu, dopóki nie pojawi się realny problem: spadki FPS, długie czasy ładowania, przycięcia.

Zdrowa kolejność działań:

  1. Najpierw działający gameplay.
  2. Potem pomiar – wbudowany profiler lub zwykłe odczucie gry na docelowym sprzęcie.
  3. Dopiero potem konkretne zmiany, a nie „optymalizacja na wszelki wypadek”.

Najczęściej zadawane pytania (FAQ)

Od czego zacząć naukę tworzenia gier w Unity lub Godot?

Najrozsądniej zacząć od jednego, bardzo małego projektu, np. klonu Pong, Flappy Bird albo prostego runnera 2D. Na starcie celem nie jest „opanowanie silnika”, tylko doprowadzenie mini-gry od pomysłu do działającego prototypu, który ktoś z zewnątrz potrafi uruchomić.

W praktyce oznacza to: zainstaluj wybrany silnik, przejdź 1–2 krótkie tutoriale, a potem jak najszybciej zacznij robić własną wersję prostej gry. Problemy, które wyskoczą po drodze (ruch postaci, kolizje, punkty), rozwiązuj na bieżąco, szukając konkretnych odpowiedzi, zamiast oglądać losowe kursy „o wszystkim”.

Unity czy Godot – co lepsze dla początkującego?

To zależy od Twojego profilu. Jeśli znasz C# lub programujesz w .NET, Unity będzie bardziej naturalne. Daje też ogromny ekosystem, Asset Store i lepsze szanse, jeśli myślisz o pracy w studiu. Minusem jest bardziej rozbudowany edytor i większa liczba „klocków”, w których łatwo się zakopać.

Jeśli nigdy nie programowałeś i celujesz w proste gry 2D, Godot z GDScript zwykle jest łagodniejszy. Edytor jest lżejszy, start szybszy, mniej konfiguracji po drodze. Za to ekosystem jest mniejszy, więc częściej trzeba doczytać dokumentację albo pokombinować samodzielnie. Dobra wiadomość: cokolwiek wybierzesz, podstawowe pojęcia (scena, obiekty, kolizje, input) będą później przenoszalne.

Ile czasu zajmuje zrobienie pierwszej prostej gry w Unity lub Godot?

Przy regularnej nauce 5–10 godzin tygodniowo, pierwszą bardzo prostą grę 2D można mieć w ciągu 1–3 tygodni. Mowa o czymś w stylu: jeden poziom, podstawowy ruch, kilka przeszkód, licznik punktów – bez dopieszczonej grafiki i muzyki z pełną orkiestrą.

W przedziale 3–6 miesięcy takiej pracy spokojnie da się zbudować 2–4 skończone mini-gry, ogarnąć sceny, fizykę, kolizje, input i nabrać pewności w pisaniu skryptów. Warunek jest jeden: kończysz projekty, zamiast co tydzień zaczynać nowy „epicki” pomysł.

Czy muszę umieć programować, żeby zacząć w Unity lub Godot?

Nie musisz mieć doświadczenia w programowaniu, ale musisz być gotowy się go nauczyć. Gry to logika: warunki, zmienne, zdarzenia, liczenie punktów. W Unity używasz C#, w Godot najczęściej GDScript (składniowo zbliżony do Pythona), więc obywa się bez wyrafinowanej matematyki, za to bez podstaw programowania daleko nie zajedziesz.

Dobry sposób na start to przepisywanie krótkich skryptów z prostych tutoriali, a potem małe modyfikacje „pod siebie”: zmiana prędkości postaci, dodanie drugiego przeciwnika, innego warunku zwycięstwa. W ten sposób oswajasz się z kodem, zamiast wpatrywać się w dokumentację jak w hieroglify.

Jaką pierwszą grę 2D warto zrobić w Unity lub Godot?

Najlepiej wybrać coś, co ma:

  • jedną scenę (jeden poziom),
  • proste sterowanie (lewo/prawo, skok, kliknięcie),
  • jasny warunek przegranej i wygranej.

Dobrymi kandydatami są: klon Pong, prosty endless runner, platformówka z jednym poziomem, Flappy Bird. Brzmi banalnie, ale w tak małym projekcie „przerobisz” cały proces: od sceny i inputu, przez kolizje i fizykę, po prosty ekran końca gry. Potem możesz stopniowo dokładać kolejne elementy, zamiast od razu celować w „własnego Wiedźmina”.

Czy da się uczyć Unity i Godot jednocześnie?

Technicznie – tak. Sensownie – raczej nie, zwłaszcza na początku. Oba silniki rozwiązują podobne problemy, ale robią to w inny sposób (GameObject + komponenty w Unity vs drzewko node’ów i sceny w Godot). Skakanie między nimi co kilka dni zwykle kończy się chaosem w głowie i brakiem ukończonych projektów.

Lepsza strategia: wybierz jeden silnik na najbliższy rok, zrób w nim kilka małych gier, ogarnij podstawowy workflow. Dopiero potem, jeśli poczujesz taką potrzebę, przerzuć się na drugi – wtedy większość koncepcji (sceny, kolizje, input, UI) będzie już znajoma, zmieni się tylko sposób ich „klikania”.

Jak uniknąć zbyt ambitnego projektu na start?

Ustal na sztywno ograniczenia: maksymalnie jeden poziom, brak multiplayera, brak online, brak zaawansowanego UI. Następnie spisz listę funkcji absolutnie koniecznych do działania gry (MVP), a wszystko ponad to wrzuć do sekcji „może kiedyś”.

Dobry test: czy jesteś w stanie wytłumaczyć całą mechanikę gry w 2–3 zdaniach? Jeśli nie, projekt jest za duży na pierwsze podejście. Jeśli tak, jest spora szansa, że faktycznie go skończysz, a nie utkniesz na etapie „projektu życia” z jedną niedokończoną sceną.

Kluczowe Wnioski

  • Na starcie celem nie jest „arcydzieło AAA”, tylko mały, działający prototyp – lepiej zrobić prostą grę typu Pong czy klon Flappy Bird niż przez miesiąc „uczyć się silnika” bez żadnego efektu.
  • Regularna nauka przez 3–6 miesięcy (kilka godzin tygodniowo) spokojnie wystarcza, by skończyć kilka prostych gier 2D, ogarnąć sceny, fizykę, kolizje, input i przestać bać się skryptów.
  • Największą umiejętnością na początku jest dowiezienie małego projektu do końca: gra ma początek i koniec, nie wywala się błędami i ktoś z zewnątrz potrafi ją odpalić bez instrukcji.
  • Nauka „robiąc gry” jest skuteczniejsza niż nauka „silnika” – wybierasz mini-projekt i rozwiązujesz konkretne problemy (ruch postaci, kolizje, punkty), zamiast tonąć w dziesiątkach losowych tutoriali.
  • Unity i Godot rozwiązują te same problemy (sceny, obiekty/node’y, input, fizyka, UI), ale inaczej je nazywają i organizują, dlatego na początek sensownie jest skupić się na jednym silniku, zamiast żonglować dwoma naraz.
  • Unity daje ogromny ekosystem, Asset Store i C#, ale bywa przytłaczające liczbą opcji i złożonością edytora – początkujący łatwo wpadają w pułapkę „jeszcze tylko ten system, jeszcze ten…”, zamiast skończyć choć jedną grę.
  • Godot stawia na lekkość, szybkość pracy i prostsze 2D, więc dla wielu osób start jest mniej bolesny; to raczej „zwinne miasteczko” niż „rozlane megamiasto”, w którym tydzień szukasz tylko dobrego zjazdu z autostrady.