Don't Touch The Spikes
Gra polega na sterowaniu postacią (Ptakiem), która automatycznie porusza się poziomo między dwiema ścianami. Gracz musi klikać/skakać, aby utrzymać postać w powietrzu i unikać kolców pojawiających się losowo na ścianach. Każde udane odbicie od ściany to punkt i wyzwalacz do pojawienia się nowej, trudniejszej przeszkody. Śmierć następuje po kontakcie z kolcem.
Written By Coder Matthew
Last updated 6 months ago
1) Grafiki użyte w tej grze

SkyScena Sky w folderze
Assets/Scenesma jeden, bardzo specyficzny cel: służy jako wizualne tło dla głównej mechaniki gry.Zamiast umieszczać nieruchome tło (np. gradient lub obraz nieba) bezpośrednio na głównej scenie gry (
SampleScene), tworzy się je w oddzielnej scenie.Skyjest ładowana równolegle (metodą Additive) z główną sceną (SampleScene) w trakcie uruchamiania gry.Pozwala to na zachowanie czystej hierarchii w
SampleScene(gdzie znajdują się tylko Ptak, Ściany i Kolce) oraz ułatwia ponowne użycie tego samego tła w innych projektach bez konieczności jego kopiowania.
2) Hierarchia w Unity

Main CameraOdpowiada za widok gry. Ustawia perspektywę i pole widzenia na główny obszar rozgrywki 2D.
Renderuje wszystkie elementy sceny (Gracza, Przeszkody, Tło i UI).
SkyObiekt wizualny, który renderuje tło.
Używany jako statyczny kontekst wizualny, załadowany w scenie.
BirdReprezentuje postać sterowaną przez gracza. Obiekt zawiera skrypt
BirdController.cs.Jest to główny Gracz. Wykrywa kolizje ze ścianami (
Wall) dla punktacji i odbicia, oraz z kolcami (Spike) dla śmierci.
Square …Fizyczne granice boczne. Obiekty te posiadają tag "Wall".
Ptak odbija się od nich, zmieniając kierunek. Kontakt z nimi jest wyzwalaczem dla naliczenia punktu i wywołania
SpikeManager.
scoreTextElement tekstowy (
TMP_Text) wyświetlający aktualny wynik gracza.Jest na bieżąco aktualizowany przez skrypt
BirdControllerpo każdym udanym odbiciu od ściany.
tapToJumpTextElement tekstowy (
TMP_Text) wyświetlający instrukcję startową ("TAP TO JUMP").Jest aktywny na początku gry i wyłączany przez
BirdControllerw momencie, gdy gracz rozpocznie grę pierwszym kliknięciem.
resultTextElement tekstowy (
TMP_Text) wyświetlający końcowy wynik.Jest nieaktywny na starcie i aktywowany przez funkcję
Die()w skrypcieBirdControllerpo śmierci Ptaka.
… SpikesKontenery nadrzędne dla obiektów kolców, zarządzane przez skrypt
SpikeManager.cs.Umożliwiają
SpikeManagerna łatwe grupowanie, ukrywanie i losowe aktywowanie kolców na danej krawędzi, zwiększając trudność gry.
3) Skrypty użyte w tej grze

BirdControllerGłówny kontroler Ptaka (Gracza), odpowiedzialny za ruch poziomy i skoki, logikę odbicia od ścian, punktację i zarządzanie śmiercią/restartem. Realizuje mechanikę zmiany kierunku po uderzeniu w ścianę.
Uruchamia grawitację i ruch po pierwszym wejściu. Kontroluje ciągły ruch poziomy (
horizontalSpeed) oraz nadaje pionowy impuls (jumpForce) po kliknięciu myszą lub spacją.Wykrywa uderzenie w "Wall". Zmienia kierunek Ptaka, odwraca jego grafikę (skalę), nalicza punkt i wywołuje akcję generowania kolców na przeciwnej ścianie (
DelayedSwitchSpikes).Wykrywa zderzenie z obiektami otagowanymi jako "Spike" (kolce), co prowadzi do sekwencji śmierci (
Die()) i restartu sceny.
SpikeManagerOdpowiada za generowanie i losowe rozmieszczanie kolców na ścianach oraz dynamiczne zwiększanie poziomu trudności gry.
Wywołany przez
BirdControllerpo odbiciu od ściany. Najpierw usuwa wszystkie kolce, a następnie wybiera przeciwną ścianę do lotu Ptaka.Zmienna
currentSpikeCount(początkowo 2) jest zwiększana o 1 po każdej udanej rundzie (do maksymalnie 4), co powoduje, że Ptak ma coraz mniej miejsca do wylądowania.Stosuje algorytm mieszania do losowania, które z dostępnych miejsc kolców na ścianie mają zostać aktywowane.
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 UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
using UnityEngine.Networking;
using System.Collections;
public class BirdController : MonoBehaviour
{
// --- Parametry Ruchu, Fizyki i UI ---
public float horizontalSpeed = 4.5f;
public float jumpForce = 6f;
public TMP_Text scoreText;
public TMP_Text tapToJumpText;
public TMP_Text resultText;
// --- Prywatne Zmienne Stanu ---
private Rigidbody2D rb;
private int direction = 1;
private bool isDead = false;
private bool gameStarted = false;
private int score = 0;
// Stała określająca opóźnienie pojawienia się kolców po odbiciu (0.2 sekundy).
private const float spikeDelay = 0.2f;
void Start()
{
// [BLOK KOMENTARZY: Inicjalizacja Gry]
// Ustawienie fizyki (zablokowanie rotacji, wyłączenie grawitacji na start).
rb = GetComponent<Rigidbody2D>();
rb.freezeRotation = true;
rb.gravityScale = 0f;
UpdateScoreText();
// Aktywacja/Dezaktywacja elementów UI na start (widoczne "TAP TO JUMP").
if (tapToJumpText != null)
tapToJumpText.gameObject.SetActive(true);
if (resultText != null)
resultText.gameObject.SetActive(false);
// Upewnienie się, że kolce są ukryte na starcie.
if (SpikeManager.Instance != null)
SpikeManager.Instance.ResetSpikes();
}
void Update()
{
if (isDead) return;
// [BLOK KOMENTARZY: Obsługa Startu Gry]
// Czeka na pierwsze kliknięcie/spacę, aby włączyć grawitację i rozpocząć grę.
if (!gameStarted)
{
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
{
gameStarted = true;
rb.gravityScale = 1f; // Włącz grawitację
if (tapToJumpText != null)
tapToJumpText.gameObject.SetActive(false);
}
return;
}
// [BLOK KOMENTARZY: Skok (Flap)]
// W trakcie gry, każde kliknięcie/spacja nadaje Ptakowi pionową siłę.
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
{
rb.linearVelocity = new Vector2(rb.linearVelocity.x, jumpForce);
}
}
void FixedUpdate()
{
// [BLOK KOMENTARZY: Ciągły Ruch Poziomy (Fizyka)]
// Utrzymuje stałą prędkość poziomą w aktualnym kierunku (direction).
if (isDead || !gameStarted) return;
rb.linearVelocity = new Vector2(direction * horizontalSpeed, rb.linearVelocity.y);
}
void OnCollisionEnter2D(Collision2D collision)
{
if (isDead) return;
// [BLOK KOMENTARZY: Uderzenie w Ścianę (Wall) - Odbicie i Punktacja]
if (collision.gameObject.CompareTag("Wall"))
{
// 1. Odbicie i Grafika
direction *= -1; // Odwrócenie kierunku
Vector3 scale = transform.localScale;
scale.x *= -1; // Odwrócenie grafiki Ptaka
transform.localScale = scale;
// 2. Punktacja
score++;
UpdateScoreText();
// 3. Generowanie Kolców (z opóźnieniem)
if (SpikeManager.Instance != null)
{
// Anuluje poprzednie wywołanie, aby uniknąć błędów przy szybkich odbiciach.
CancelInvoke(nameof(DelayedSwitchSpikes));
// Planuje włączenie kolców po krótkim opóźnieniu (aby Ptak zdążył się odbić).
Invoke(nameof(DelayedSwitchSpikes), spikeDelay);
}
}
}
void DelayedSwitchSpikes()
{
// [BLOK KOMENTARZY: Opóźnione Generowanie Kolców]
// Właściwe wywołanie logiki generowania kolców po minięciu czasu 'spikeDelay'.
if (SpikeManager.Instance != null && !isDead)
{
SpikeManager.Instance.SwitchSpikes(direction);
}
}
void OnTriggerEnter2D(Collider2D other)
{
if (isDead) return;
// [BLOK KOMENTARZY: Kolizja z Kolcem (Spike) - Śmierć]
// Wykrywa dotknięcie Triggera otagowanego jako "Spike" (kolce).
if (other.CompareTag("Spike"))
{
Die(); // Koniec gry.
}
}
void Die()
{
// [BLOK KOMENTARZY: Sekwencja Śmierci]
isDead = true;
// Zabezpieczenie: Anuluje wszystkie oczekujące akcje.
CancelInvoke(nameof(DelayedSwitchSpikes));
// Animacja śmierci: odblokowanie rotacji, nadanie pędu i obrotu.
rb.freezeRotation = false;
rb.linearVelocity = new Vector2(0, 2f);
rb.AddTorque(500f);
// Wysyłka wyniku i wyświetlenie ekranu Game Over
StartCoroutine(
SendScore(
22, // id
score // score
)
);
if (resultText != null)
{
resultText.text = "WYNIK: " + score.ToString();
resultText.gameObject.SetActive(true);
}
Invoke("RestartLevel", 3f); // Restart sceny po 3 sekundach.
}
void RestartLevel()
{
// [BLOK KOMENTARZY: Restart]
// Ponowne załadowanie aktywnej sceny.
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
void UpdateScoreText()
{
// [BLOK KOMENTARZY: Aktualizacja UI]
// Aktualizuje wyświetlany wynik.
if (scoreText != null)
scoreText.text = score.ToString();
}
public IEnumerator SendScore(int gameId, int score)
{
// [BLOK KOMENTARZY: Procedura HTTP]
// Standardowa korutyna do wysyłania wyniku na zewnętrzny serwer.
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") + "EcS9YcvMtWNnW0N8yi1mVK");
using (UnityWebRequest r = UnityWebRequest.Post(url, f))
{
yield return r.SendWebRequest();
Debug.Log(r.result == UnityWebRequest.Result.Success
? r.downloadHandler.text
: "ERR: " + r.error);
}
}
}