Dino Game
Gra polega na sterowaniu postacią (dinozaurem) w nieskończonym, bocznym biegu. Postać automatycznie biegnie w prawo (elementy sceny przesuwają się w lewo), a gracz musi naciskać przycisk (np. Spację), aby skakać i unikać losowo generowanych przeszkód (kaktusów i pterodaktyli). Głównym celem jest osiągnięcie jak najwyższego wyniku.
Written By Coder Matthew
Last updated 6 months ago
1) Grafiki użyte w Dino Game

1.
Dino_Run01Jest to pierwsza klatka z dwuelementowej sekwencji, która symuluje ruch nóg.
Wykorzystywana przez skrypt
AnimatedSpritena obiekciePlayer. Cykliczne przełączanie tej grafiki zDino_Run02tworzy iluzję ruchu.
2.
Dino_Run02Klatka ta uzupełnia sekwencję, tworząc pełny cykl ruchu.
Wykorzystywana przez skrypt
AnimatedSpritedo płynnego przełączania w ramach pętli animacyjnej. Szybkość przełączania jest skalowana przezGameManager.gameSpeed, dynamicznie przyspieszając animację wraz z grą.
3.
Cactus_LargeGrafika przedstawiająca duży, pojedynczy kaktus. Służy jako wizualny wzorzec dla jednej z podstawowych przeszkód naziemnych.
Używany jako prefab przez skrypt
Spawnerdo generowania przeszkód o większej wysokości. Obiekt z tą grafiką posiada Collider, a zderzenie z nim wywołujeGameOver().
4.
Cactus_Large_GroupGrafika przedstawiająca grupę dużych kaktusów. Tworzy przeszkodę o większej szerokości kolizji, podnosząc poziom trudności.
Generowany losowo przez
Spawnerjako trudniejszy wariant, wymagający dłuższego skoku do uniknięcia. Obiekt ten symbolizuje złożoną przeszkodę, często będąc rzadziej wybieranym przez system losujący.
5.
Cactus_SmallGrafika przedstawiająca mały, pojedynczy kaktus. Jest to najprostszy wariant przeszkody.
Używany jako prefab, jest generowany przez
Spawnerz określonym prawdopodobieństwem. Często pojawia się w szybszych sekwencjach lub jest kombinowany z innymi przeszkodami.
6.
Cactus_Small_GroupGrafika przedstawiająca grupę małych kaktusów. Wariant złożonej przeszkody naziemnej, składającej się z kilku mniejszych elementów.
Służy do zwiększania różnorodności przeszkód i testowania precyzji skoku gracza.
7.
Bird_01Pierwsza klatka animacji lecącego Pterodaktyla (przeszkoda powietrzna). Symuluje moment z wzniesionymi skrzydłami.
Skrypt
AnimatedSpriteprzełącza tę klatkę zBird_02.
8.
Bird_02Druga klatka animacji lecącego Pterodaktyla. Symuluje moment z opuszczonymi skrzydłami.
Używana do stworzenia iluzji trzepotania skrzydłami podczas ruchu w lewo.
9.
GroundJest to wizualna baza, po której porusza się dinozaur.
Używana przez skrypt
Ground, który przewija (offsetuje) jej teksturę w czasie, dając iluzję nieskończonego biegu i ruchu w świecie gry.
10.
RetryGrafika przycisku "Spróbuj ponownie". Element interfejsu użytkownika (UI) wywołujący akcję restartu. Działa podobnie jak znany nam onclick().
Jest domyślnie ukryta, a skrypt
GameManageraktywuje ją po przegranej.Kliknięcie tego elementu UI wywołuje metodę
GameManager.NewGame().
2) Hierarchia w Unity

1.
Game ManagerReprezentuje fizyczny obiekt kontrolujący globalny stan gry oraz jej dynamikę.
Do tego obiektu przypięty jest skrypt
GameManager. Jest kluczowy, ponieważ utrzymuje Singleton (GameManager.Instance), kontroluje globalną prędkość gry (gameSpeed), zarządza punktacją, inicjuje nową grę (NewGame()) oraz obsługuje jej zakończenie (GameOver()).
2.
Main CameraOdpowiada za widok gry, czyli to, co gracz faktycznie widzi.
Ustawia perspektywę i granice świata gry. W Dino Game jest statyczna i skierowana na obszar biegu dinozaura.
3.
PlayerReprezentuje postać sterowaną przez gracza (dinozaura).
Obiekt, do którego przypięty jest skrypt
Player. Zawiera również skryptAnimatedSpritedo animacji biegu. Odpowiada za całą logikę fizyki (grawitacja, skoki za pomocąCharacterController) i wykrywanie kolizji z przeszkodami. Jest aktywowany i dezaktywowany przezGameManager(wNewGame()iGameOver()).
4.
GroundReprezentuje wizualne podłoże, po którym biegnie dinozaur.
Przypięty jest do niego skrypt
Ground. Ten obiekt nie porusza się, lecz to jego tekstura jest ciągle przesuwana w lewo (metodamainTextureOffset), tworząc iluzję nieskończonego biegu i ruchu.
5.
SpawnerReprezentuje punkt i logikę generowania wszystkich przeszkód.
Do tego obiektu przypięty jest skrypt
Spawner. Znajduje się on zazwyczaj poza prawą krawędzią ekranu. Cyklicznie generuje prefabrykaty przeszkód (np. kaktusy, pterodaktyle), uwzględniając ich losowość i prawdopodobieństwo pojawienia się (strukturaSpawnableObject).
6.
CanvasJest kontenerem nadrzędnym dla wszystkich elementów interfejsu użytkownika (UI).
Zapewnia, że wszystkie elementy UI (tekst, przyciski) są wyświetlane i skalowane poprawnie na różnych rozdzielczościach ekranu.
7.
Game Over(wewnątrz Canvas)Element graficzny/tekstowy (TextMeshPro), który informuje o przegranej.
Jest ukryty podczas gry, a aktywowany (
SetActive(true)) przezGameManagerw momencie kolizji gracza.
8.
Retry(wewnątrz Canvas)Przycisk lub ikona, która pozwala rozpocząć nową grę.
Jest ukryty podczas gry. Po jego wyświetleniu, kliknięcie wywołuje metodę
GameManager.NewGame().
9.
Score(wewnątrz Canvas)Element tekstowy (TextMeshPro), który wyświetla aktualny wynik gracza.
Skrypt
GameManagerstale aktualizuje jego wartość w metodzieUpdate, formatując ją do pięciu cyfr ("D5").
3) Skrypty użyte w Dino Game

1.
GameManagerGłówna jednostka kontrolująca globalny stan gry oraz jej dynamiczne parametry. Utrzymuje wzorzec Singleton, umożliwiając innym skryptom łatwy dostęp do kluczowych funkcji.
Kontroluje prędkość gry (
gameSpeed), która z czasem przyspiesza, zwiększając trudność, a także obsługuje punktację.Wywołuje funkcje
NewGame()iGameOver(), zarządzając widocznością interfejsu (Retry/GameOver) oraz aktywnością Gracza i Spawnera.
2.
PlayerSkrypt odpowiedzialny za sterowanie i fizykę głównej postaci (dinozaura). Obsługuje kluczową mechanikę gry: skok oraz stosowanie grawitacji na postać.
Wykorzystuje komponent
CharacterControllerdo bezpiecznego przemieszczania obiektu w pionie i wykrywania, kiedy jest na ziemi (isGrounded).Wykrywa kolizje z obiektami oznaczonymi tagiem
Obstaclei natychmiast wywołujeGameManager.GameOver().
3.
SpawnerZarządza losowym i cyklicznym generowaniem wszystkich przeszkód. Odpowiada za logikę losowania, które prefabrykaty (kaktusy, pterodaktyle) mają się pojawić, bazując na ich prawdopodobieństwie (
spawnChance).Cyklicznie wywołuje funkcję
Spawn()po upływie losowego czasu (pomiędzyminSpawnRateamaxSpawnRate).Generuje nowe instancje przeszkód i umieszcza je na scenie, poza widokiem kamery.
4.
ObstacleSteruje ruchem i cyklem życia pojedynczej przeszkody po jej wygenerowaniu. Zapewnia, że przeszkoda porusza się w lewo z prędkością równą globalnej
GameManager.gameSpeedW metodzie
Updateprzesunięcie przeszkody jest bezpośrednio skalowane przez globalną prędkość, co powoduje, że przeszkody przyspieszają wraz z grą.Niszczy (
Destroy) obiekt, gdy ten przekroczy lewą krawędź ekranu, oszczędzając zasoby gry.
5.
GroundTworzy efekt nieskończonego biegu dla podłoża. Odpowiada za wizualny aspekt ruchu terenu, bez fizycznego przesuwania całego obiektu.
Modyfikuje parametr
mainTextureOffsetkomponentuMeshRenderer, przesuwając teksturę podłoża w czasie.Prędkość przewijania jest również skalowana przez
GameManager.gameSpeed, synchronizując ruch tła z resztą gry.
6.
AnimatedSpriteUniwersalny moduł do odtwarzania prostej animacji klatkowej. Zarządza sekwencją grafik (tablica
sprites), przełączając je cyklicznie.Jest używany głównie na obiekcie
Player(do animacji biegu) oraz na obiekcie pterodaktyla.Kontroluje częstotliwość przełączania klatek na podstawie globalnej prędkości gry, co sprawia, że animacja jest szybsza, gdy rośnie poziom trudności.
4) Całe skrypty
Tutaj znajdziesz całe skrypty bez owijania w bawełne 😊, każdy blok kodu jest starannie zakomentowany tak żebyś w miarę mógł ogarnąć o co chodzi nawet jak nie znasz unity i C#.
Exampleusing TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
// Gwarantuje, że ten skrypt uruchomi się pierwszy.
[DefaultExecutionOrder(-1)]
public class GameManager : MonoBehaviour
{
// --- Ustawienie Singletonu i Kontrola Prędkości ---
// [BLOK KOMENTARZY: Globalne Zmienne Stanu Gry]
// Singleton (dostępny zewsząd), początkowa prędkość,
// o ile prędkość ma się zwiększać co sekundę, oraz aktualna prędkość gry.
public static GameManager Instance { get; private set; }
public float initialGameSpeed = 5f;
public float gameSpeedIncrease = 0.1f;
public float gameSpeed { get; private set; }
// --- Odniesienia do UI i Obiektów Sceny ---
// Zmienne do ustawienia w edytorze: pola tekstowe (wynik, Game Over) i przycisk Ponów.
[SerializeField] private TextMeshProUGUI scoreText;
[SerializeField] private TextMeshProUGUI gameOverText;
[SerializeField] private Button retryButton;
// Prywatne referencje do kluczowych skryptów (Gracza i Generatora).
private Player player;
private Spawner spawner;
// Zmienna przechowująca wynik.
private float score;
public float Score => score;
// --- Inicjalizacja i Czyszczenie (Singleton) ---
// [BLOK KOMENTARZY: Zarządzanie Instancją]
// Metody zapewniające, że na scenie istnieje tylko JEDEN GameManager (Singleton).
private void Awake()
{
if (Instance != null) {
DestroyImmediate(gameObject);
} else {
Instance = this;
}
}
private void OnDestroy()
{
if (Instance == this) {
Instance = null;
}
}
private void Start()
{
// Znajdowanie i przechowanie referencji do Gracza i Spawnera.
player = FindObjectOfType<Player>();
spawner = FindObjectOfType<Spawner>();
// Rozpoczęcie nowej gry.
NewGame();
}
// --- Kontrola Stanu Gry: Nowa Gra ---
public void NewGame()
{
// [BLOK KOMENTARZY: Resetowanie Sceny]
// 1. Wyszukuje wszystkie istniejące przeszkody i niszczy je, aby przygotować scenę.
Obstacle[] obstacles = FindObjectsOfType<Obstacle>();
foreach (var obstacle in obstacles) {
Destroy(obstacle.gameObject);
}
// 2. Resetuje wynik i prędkość gry do wartości początkowej.
score = 0f;
gameSpeed = initialGameSpeed;
enabled = true; // Włącza metodę Update tego skryptu.
// 3. Aktywuje obiekty Gry (Gracz, Spawner) i ukrywa elementy interfejsu "Koniec Gry".
player.gameObject.SetActive(true);
spawner.gameObject.SetActive(true);
gameOverText.gameObject.SetActive(false);
retryButton.gameObject.SetActive(false);
}
// --- Kontrola Stanu Gry: Koniec Gry ---
public void GameOver()
{
// [BLOK KOMENTARZY: Zakończenie Gry i Zapis Wyniku]
// 1. Zatrzymuje ruch (gameSpeed = 0) i wyłącza skrypt (żeby nie naliczał punktów).
gameSpeed = 0f;
enabled = false;
// 2. Deaktywuje obiekty Gry (Gracza i Spawner), zatrzymując dalsze generowanie/ruch.
player.gameObject.SetActive(false);
spawner.gameObject.SetActive(false);
// 3. Pokazuje elementy interfejsu "Koniec Gry" i przycisk "Ponów".
gameOverText.gameObject.SetActive(true);
retryButton.gameObject.SetActive(true);
// 4. Rozpoczyna procedurę wysłania wyniku na zewnętrzny serwer.
StartCoroutine
(
SendScore(
15, // id gry
Mathf.FloorToInt(score) // wynik (zaokrąglony w dół do liczby całkowitej)
)
);
}
// --- Logika Punktacji i Przyspieszenia ---
private void Update()
{
// [BLOK KOMENTARZY: Ciągły Ruch i Punktacja]
// W każdej klatce:
// 1. Nieustannie zwiększa prędkość gry, dążąc do wyższego poziomu trudności.
gameSpeed += gameSpeedIncrease * Time.deltaTime;
// 2. Zwiększa wynik proporcjonalnie do aktualnej prędkości gry.
score += gameSpeed * Time.deltaTime;
// 3. Aktualizuje tekst wyniku (wynik jest zaokrąglany w dół i formatowany na 5 cyfr).
scoreText.text = Mathf.FloorToInt(score).ToString("D5");
}
// --- Komunikacja Sieciowa (Wysyłanie Wyniku) ---
// [BLOK KOMENTARZY: Procedura HTTP]
// Korutyna wysyłająca wynik do serwisu internetowego, używając stałego ID gry
// i prostego tokenu zabezpieczającego opartego na bieżącej minucie.
public IEnumerator SendScore(int gameId, int score)
{
string url = "https://bit.elita.fun/execs/api/set_score.php?game_id=" + gameId + "&score=" + score;
WWWForm f = new WWWForm();
f.AddField("pass", System.DateTime.Now.ToString("mm") + "E-----K");
using (UnityWebRequest r = UnityWebRequest.Post(url, f))
{
yield return r.SendWebRequest();
Debug.Log(r.result == UnityWebRequest.Result.Success
? r.downloadHandler.text
: "ERR: " + r.error);
}
}
}