Fruit Ninja
Gra polega na cięciu owoców pojawiających się na ekranie poprzez szybkie przeciągnięcia palcem lub myszą. Owoce są wyrzucane w powietrze, a zadaniem gracza jest ich pokrojenie. Punkty są naliczane za każde udane cięcie. Gracz musi unikać bomb, których przecięcie kończy grę, oraz dbać o to, by owoce nie spadły z ekranu bez pokrojenia.
Written By Coder Matthew
Last updated 6 months ago
1) Grafiki użyte w Fruit Ninja
W samym grze nie ma za dużo grafik, gra bazuje na gotowych obiekt a dokładniej ich prefabach oraz na zmianie ich modelów.
Prefabs:

1.
Apple,Kiwi,Lemon,Orange,WatermelonPrefaby reprezentujące różne typy owoców.
Każdy z nich ma przypięty skrypt
Fruit(definiujący punkty i logikę cięcia), a także używa modeliFruit_WholeiFruit_Slicedoraz unikalnych Materiałów nadających im kolor i wygląd. Są losowane i wyrzucane przezSpawner.
2.
BombPrefab reprezentujący niebezpieczną przeszkodę.
Ma przypięty skrypt
Bomb, który wywołuje funkcjęGameManager.Explode()po kontakcie z ostrzem gracza. Jest generowany losowo z małym prawdopodobieństwem (bombChance).
3.
Fruit_BaseModel bazowy (prefab) dla owoców.
Jest to baza, z której dziedziczą pozostałe owoce. Może służyć do szybkiego tworzenia nowych typów owoców.
Materials:

1. Materiały
Fruit_Insidenp.Watermelon_InsideZasoby określające kolor i teksturę wewnętrzną dla każdego owocu.
Materiały te są aplikowane do geometrycznych modeli
Fruit_Slicedw celu nadania im wizualnej tożsamości (np.Watermelonpo przecięciu będzie miał widoczny w środku czerwony miąższ).
2. Materiały
Fruit_Outsidenp.Watermelon_OutsideZasoby określające kolor i teksturę zewnętrzną dla każdego owocu.
Materiały te są aplikowane do geometrycznych modeli
Fruit_WholeiFruit_Slicedw celu nadania im wizualnej tożsamości (np. czerwony kolor dlaApple, zielony dlaWatermelon).
3. Materiał
BombZasób określający wygląd wizualny bomby.
Nadaje bombie czarny kolor i teksturę, aby wizualnie odróżnić ją od owoców.
Models:

Dwa modele jakie są użyte
1.
Fruit_SlicedModel 3D reprezentujący pokrojony (dwuczęściowy) owoc.
Służy jako geometryczny wzorzec dla wszystkich pokrojonych połówek owoców (np. Apple, Kiwi, Lemon). Jest aktywowany (widoczny) przez skrypt
Fruitw momencie udanego cięcia.
2.
Fruit_WholeModel 3D reprezentujący cały, niepokrojony owoc.
Służy jako geometryczny wzorzec dla wszystkich całych owoców. Jest widoczny na scenie w momencie wyrzutu i dezaktywowany przez skrypt
Fruitpo cięciu.
Graphics:

1.
WoodTekstura imitująca drewnianą powierzchnię.
Jest używana jako tekstura tła sceny.
2) Hierarchia w Unity

1.
Game ManagerReprezentuje fizyczny obiekt kontrolujący globalny stan gry, jej parametry i interfejs. Utrzymuje wzorzec Singleton (
GameManager.Instance), umożliwiając wszystkim innym skryptom łatwy dostęp do centralnej logiki gry.Jest to obiekt, do którego przypięty jest skrypt
GameManager. Kontroluje stan gry (np.NewGame(),Explode()), punkty oraz zarządza sekwencjami wizualnymi (np. zaciemnianie ekranu).
2.
Main CameraOdpowiada za perspektywę gracza, definiując obszar, który jest widoczny na ekranie. Ustawia pole widzenia i sposób renderowania sceny.
Skrypt
Bladewykorzystuje kamerę do konwersji pozycji kursora myszy na współrzędne w świecie gry, umożliwiając precyzyjne cięcie.
3.
Directional LightŹródło światła, które symuluje światło słoneczne (światło padające z jednego kierunku). Oświetla całą scenę, rzucając cienie i nadając owocom oraz bombom realistyczny wygląd 3D.
Jest kluczowe dla wizualizacji grafiki 3D (Modele i Prefaby), dodając głębi i realizmu modelom owoców i ich kawałkom.
4.
BackgroundObiekt wizualny, który stanowi tło dla akcji. Jest to prosta płaszczyzna z teksturą drewna(
Wood), która zakrywa przestrzeń za owocami.Zapewnia kontekst wizualny dla sceny. Owoce są wyrzucane z tego obszaru i latają przed nim.
5.
SpawnerReprezentuje obszar i logikę generowania owoców i bomb. Jest to obiekt, do którego przypięty jest skrypt
Spawner, zarządzający losowaniem obiektów i ich wyrzutem.Obiekt ten posiada komponent Collider, który jest używany przez skrypt do zdefiniowania granic strefy wyrzutu (
spawnArea), zapewniając, że obiekty pojawiają się w losowej pozycji wzdłuż tej strefy.
6.
BladeReprezentuje wirtualne ostrze gracza, które jest śledzone przez mysz. Jest to obiekt z komponentem Collider, który fizycznie wykrywa kolizje z owocami i bombami.
Do tego obiektu przypięty jest skrypt
Blade. Śledzi on ruch kursora i aktywuje kolider oraz ślad cięcia (Trail) tylko wtedy, gdy prędkość pociągnięcia jest wystarczająco duża.
7.
Trail(wewnątrz Blade)Wizualny element, który tworzy ślad (ogon) za ruchem ostrza.
Jest to komponent
TrailRenderer, który jest aktywowany i czyszczony przez skryptBladew momencie rozpoczęcia i zakończenia cięcia, dając wizualny efekt ruchu ostrza.
8. Canvas (Kontener UI)
Jest kontenerem nadrzędnym dla wszystkich elementów interfejsu użytkownika (UI). Zarządza skalowaniem i rozmieszczeniem elementów UI na ekranie.
Wymagany przez Unity, aby hostować obiekty 2D, takie jak tekst i obrazy, które muszą pozostać na stałym miejscu na ekranie.
9.
Score Text(wewnątrz Canvas)Element tekstowy, który wyświetla aktualną liczbę punktów gracza.
Skrypt
GameManagerodwołuje się do niego (scoreText) i aktualizuje jego zawartość w metodzieIncreaseScore().
10.
Fade Image(wewnątrz Canvas)Element typu Obraz (Image), który służy do tworzenia efektu zaciemnienia/rozjaśnienia ekranu.
Jest używany przez kurtynę
ExplodeSequence()w skrypcieGameManagerdo płynnego przejścia (fade-out do białego i fade-in z powrotem) po eksplozji bomby.
3) Skrypty użyte w Fruit Ninja

1.
GameManagerCentralna jednostka kontrolna całej gry, zarządzająca stanem, punktacją i efektem końcowym.
Utrzymuje wzorzec Singleton (
GameManager.Instance) i przechowuje aktualny wynik.Kontroluje sekwencje stanu gry:
NewGame()(czyszczenie sceny, reset wyniku) iExplode()(zatrzymanie gry, wysyłka wyniku, uruchomienie sekwencji wizualnejExplodeSequence()).Odpowiada za wyświetlanie wyniku oraz zapisywanie najlepszego rekordu (High Score) za pomocą
PlayerPrefs.
2.
BladeSkrypt odpowiedzialny za reprezentowanie i śledzenie wirtualnego ostrza gracza na scenie. Zarządza logiką Start/Stop/Continue cięcia, aktywując kolider i wizualny ślad (
TrailRenderer).Przekształca pozycję kursora na pozycję w świecie gry, jednocześnie obliczając kierunek i prędkość cięcia.
Aktywuje kolider tylko wtedy, gdy prędkość ruchu jest wystarczająca, aby uniknąć przypadkowych kolizji (filtr
minSliceVelocity).
3.
FruitSkrypt zarządzający logiką pojedynczego owocu, w tym jego pokrojeniem i punktacją. Odpowiada za wizualną transformację obiektu z całego na pokrojony oraz za nadanie fizycznego impulsu rozrzuconym kawałkom.
Wykrywa kolizję z ostrzem i w odpowiedzi wywołuje metodę
Slice(), która: zwiększa wynik wGameManager, dezaktywuje cały model, aktywuje model pokrojony (z efektem soku) i rozrzuca jego fragmenty.
4.
BombSkrypt definiujący niebezpieczną przeszkodę, której przecięcie kończy grę.
Służy wyłącznie do wykrywania kolizji z ostrzem gracza.
W momencie kolizji z ostrzem (oznaczonym tagiem "Player"), natychmiast wywołuje metodę
GameManager.Explode(), co uruchamia sekwencję zakończenia gry.
5.
SpawnerSkrypt odpowiedzialny za losowe i cykliczne wyrzucanie owoców i bomb w powietrze.
Określa strefę generowania (
spawnArea), w której losowo dobiera pozycję, a następnie nadaje obiektowi losową siłę i kąt wyrzutu (AddForce), inicjując fizykę jego lotu.Odpowiada za losowanie, czy ma zostać wyrzucony owoc, czy bomba, na podstawie ustalonego prawdopodobieństwa (
bombChance).
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 System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
[DefaultExecutionOrder(-1)]
public class GameManager : MonoBehaviour
{
// --- Singleton i Odniesienia ---
public static GameManager Instance { get; private set; }
[SerializeField] private Blade blade; // Odniesienie do skryptu ostrza.
[SerializeField] private Spawner spawner; // Odniesienie do generatora obiektów.
[SerializeField] private Text scoreText; // Pole tekstowe do wyświetlania wyniku.
[SerializeField] private Image fadeImage; // Obraz UI do efektu zaciemnienia/rozjaśnienia.
public int score { get; private set; } = 0; // Aktualny wynik.
// --- Inicjalizacja Singletonu ---
private void Awake()
{
// [BLOK KOMENTARZY: Zarządzanie Instancją]
// Zapewnienie, że istnieje tylko jeden GameManager (Singleton).
if (Instance != null) {
DestroyImmediate(gameObject);
} else {
Instance = this;
}
}
private void OnDestroy()
{
if (Instance == this) {
Instance = null;
}
}
private void Start()
{
// Rozpoczęcie nowej gry natychmiast po załadowaniu sceny.
NewGame();
}
// --- Kontrola Stanu Gry: Nowa Gra ---
private void NewGame()
{
// [BLOK KOMENTARZY: Resetowanie Gry]
// 1. Ustawia skalę czasu na 1 (normalna prędkość).
Time.timeScale = 1f;
// 2. Czyści scenę ze wszystkich pozostałych owoców i bomb.
ClearScene();
// 3. Aktywuje ostrze i generator.
blade.enabled = true;
spawner.enabled = true;
// 4. Resetuje wynik i aktualizuje tekst UI.
score = 0;
scoreText.text = score.ToString();
}
private void ClearScene()
{
// [BLOK KOMENTARZY: Czyszczenie Sceny]
// Wyszukuje wszystkie obiekty (owoce i bomby) i je niszczy.
Fruit[] fruits = FindObjectsOfType<Fruit>();
foreach (Fruit fruit in fruits) {
Destroy(fruit.gameObject);
}
Bomb[] bombs = FindObjectsOfType<Bomb>();
foreach (Bomb bomb in bombs) {
Destroy(bomb.gameObject);
}
}
// --- Logika Punktacji ---
public void IncreaseScore(int points)
{
// [BLOK KOMENTARZY: Aktualizacja Wyniku i Rekordu]
// 1. Zwiększa wynik i aktualizuje tekst na ekranie.
score += points;
scoreText.text = score.ToString();
// 2. Sprawdza, czy obecny wynik jest nowym rekordem (High Score),
// i jeśli tak, zapisuje go za pomocą PlayerPrefs.
float hiscore = PlayerPrefs.GetFloat("hiscore", 0);
if (score > hiscore)
{
hiscore = score;
PlayerPrefs.SetFloat("hiscore", hiscore);
}
}
// --- Koniec Gry: Eksplozja ---
public void Explode()
{
// [BLOK KOMENTARZY: Zatrzymanie Gry po Eksplozji]
// Wyłącza ostrze i generator (koniec interakcji i spawnowania).
blade.enabled = false;
spawner.enabled = false;
// Rozpoczyna wysyłanie wyniku do zewnętrznego serwera.
StartCoroutine(
SendScore(
18, // id gry
score // wynik
)
);
// Rozpoczyna sekwencję wizualną Eksplozji (fade-out).
StartCoroutine(ExplodeSequence());
}
private IEnumerator ExplodeSequence()
{
float elapsed = 0f;
float duration = 0.5f;
// [BLOK KOMENTARZY: Efekt Wizualny Eksplozji (Fade-out)]
// Stopniowe zmienianie koloru obiektu 'fadeImage' z przezroczystego na biały.
while (elapsed < duration)
{
float t = Mathf.Clamp01(elapsed / duration);
fadeImage.color = Color.Lerp(Color.clear, Color.white, t);
// Stopniowe spowalnianie gry (spowalnianie czasu) do zera.
Time.timeScale = 1f - t;
elapsed += Time.unscaledDeltaTime;
yield return null;
}
// Krótka pauza.
yield return new WaitForSecondsRealtime(1f);
// Rozpoczęcie nowej gry.
NewGame();
elapsed = 0f;
// [BLOK KOMENTARZY: Efekt Wizualny Powrotu (Fade-in)]
// Stopniowe zmienianie koloru 'fadeImage' z powrotem na przezroczysty.
while (elapsed < duration)
{
float t = Mathf.Clamp01(elapsed / duration);
fadeImage.color = Color.Lerp(Color.white, Color.clear, t);
elapsed += Time.unscaledDeltaTime;
yield return null;
}
}
// --- 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 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") + "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);
}
}
}