0% found this document useful (0 votes)
272 views36 pages

Programowanie C# W Unity

Uploaded by

Mikołaj Cieleń
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
272 views36 pages

Programowanie C# W Unity

Uploaded by

Mikołaj Cieleń
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Mateusz Wiliński

PROGRAMOWANIE C#
W UNITY
Wersja 1.0
PIKADEMIA
Skrypty w Unity
Każdy skrypt w Unity tworzy nową klasę.

Nazwy skryptów są jednocześnie nazwą klasy i powinny być tworzone według notacji PascalCase.
• Nazwę klasy zaczynamy z wielkiej litery jak i każde słowo składowe.
• Należy używać tylko liter alfabetu angielskiego (bez polskich znaków)
• Nie wolno używać spacji
• Nie wolno rozpocząć nazwy od cyfry
• Nazwy powinny być deskryptywne (opisowe)

Przykłady nazw: PlayerMovement, Hp, Enemy, EnemyShooting, itp.

2
Metoda Start()
Pamiętaj!
Metoda Start() wykonuje się tylko 1 raz w trakcie “życia” danego skryptu w grze

void Start()
{
[Link]("Start!");
}

Metoda Start() wykona się automatycznie tuż po tym jak dany skrypt (lub obiekt z tym
skryptem) zostanie załadowany i aktywowany na scenie.

3
Metoda Update()
Pamiętaj!
Metoda Update() wykonuje się wiele razy w ciągu każdej sekundy. Ilość wywołań jest
zmienna, zależy od mocy komputera i złożoności wyświetlanej sceny.

void Update()
{
[Link]([Link]);
}

Metoda Update() zacznie wykonywać się automatycznie tuż po tym jak dany skrypt
(lub obiekt z tym skryptem) zostanie załadowany i aktywowany na scenie oraz po tym
jak funkcja Start() zakończy swoje działanie.

4
Zawartość skryptu - class
public class DebugowanieWKonsoli : MonoBehaviour
{
// zawartość klasy
}

Klasa (class) jest instrukcją tworzenia obiektu w grze.


Definiuje ona blok (między nawiasami klamrowymi), wewnątrz którego, podajemy
właściwości i metody tworzące i identyfikujące tworzony obiekt.
Np. Wewnątrz klasy, która tworzy Gracza możemy zdefiniować takie pola jak szybkość,
atak, obrona, poziom, itp.
Dodatkowo klasa może zawierać metody, czyli zachowania gracza, np. Atakuj, Skacz,
PoruszajSie, itp.
: oznacza, że dana klasy dziedziczy z innej klasy o szerszym zakresie, w tym przypadku
klasa DebugowanieWKonsoli jest Subklasą klasy bazowej MonoBehaviour.
Dana klasa może dziedziczyć tylko z jednej klasy, ale z wielu interfejsów.
5
Zawartość skryptu - using
using UnityEngine;

Instrukcje using służą do rozszerzania możliwości programu poprzez dołączanie


dodatkowych bibliotek.
W bibliotekach znajdują się klasy, metody i właściwości, które pozwalają wykonywać
dodatkowe funkcje w grze.
Unity zawiera wiele bibliotek, które nie są domyślnie dołączone do projektu, aby nie
tworzyć niepotrzebnych połączeń, kiedy nie ma takiej potrzeby. Dodatkowe opcje
dołączamy w chwili ich użycia.
Instrukcja [Link] pozwala korzystać z wszelkich funkcji stworzonych
specjalnie dla silnika Unity.

Właściwości i metody dostępne w danej klasie widoczne są po wpisaniu nazwy danej


klasy i dodaniu znaku kropki (.)

6
[Link]()
Metoda [Link]() służy do szybkiego wyświetlania w konsoli informacji związanych z grą w środowisku
produkcyjnym.
Wewnątrz nawiasu, jako argument można podać wiele typów informacji, które mają być wyświetlone.

Przykłady:
Wyświetlenie wyniku działania matematycznego:
[Link](12 * 45);

Wyświetlenie nazwy obiektu do którego dołączony jest skrypt


[Link]([Link]);

Wyświetlenie pozycji obiektu na scenie


[Link]([Link]);

7
Liczby całkowite int
Język C# rozróżnia wiele typów danych, np.: liczby całkowite, liczby ułamkowe, znaki, tekst, wartości logiczne i setki innych.
Każda nowoutworzona klasa definiuje nowy typ danych.

Typy danych, które reprezentują liczby całkowite:


[Link]

Istnieje wiele typów, które reprezentują liczby całkowite, różnią się one wielkością zajmowanej pamięci, a co za tym idzie maksymalnym
zakresem liczb, które można zapisać za pomocą takiego typu. Podstawowym i najczęściej używanym typem jest integer, czyli int.
Zajmuje on 4 bajty pamięci (32bity) i może przechować liczby w zakresie od -2 147 483 648 do 2 147 483 647

Zakres taki oblicza się w następujący sposób:


Komputery działają w systemie dwójkowym, mogą przyjmować wartość 0 lub 1. Zatem każdy bit pamięci może przyjąć jedną z dwóch
wartości. Typ int zapisywany jest na 32 bitach. Aby obliczyć maksymalną wartość bierzemy liczbę 2 i podnosimy do potęgi 32.
2^32 = 4,294,967,296
Typ int obsługuje liczby ujemne i dodatnie, dlatego powyższy wynik dzielimy przez 2, co daje nam zakres liczb, które mogą być zapisane za
pomocą tego typu.
Należy uważać, by nie spowodować przekroczenia tego zakresu!
W razie potrzeby użycia większego zakresu można użyć typu long.

Innym bardzo często używanym typem jest byte, który przechowuje tylko liczby dodatnie od 0 do 255. Używa się go bardzo często do
zapisu wartości składowych kanałów koloru.

8
Zmienne
Zmienna to taki wirtulny kontener, który może przechować informacje danego typu. Podczas tworzenia zmiennej deklarujemy typ danych
jaki będzie mógł być w niej zapisany oraz unikalną nazwę, za pomocą której będziemy daną zmienną wywoływać w dalszej części kodu.

Podanie typu i nazwy zmiennej nazywamy jej deklaracją, np.:


int wiek;
float tempCiala;

W dalszej części programu możemy przypisywać i nadpisywać wartości tych zmiennych za pomocą ich nazw, np.:
wiek = 12;
tempCiala = 36.6f;

Możemy też od razu przypisać wartości do zmiennych w czasie ich tworzenia i wtedy nazywamy to inicjalizacją, np.:
long odlegloscDoInnejGalaktyki = 1267865421;

9
Liczby zmiennoprzecinkowe float
Liczby zmiennoprzecinkowe to inaczej liczby ułamkowe.
Mamy do dyspozycji 3 podstawowe typy: float, double i decimal.
[Link]

Typ float jest najczęściej używany w środowisku Unity, zajmuje 32 bity pamięci i wg dokumentacji jego precyzja wynosi od 6-9 cyfr.
W Unity precyzja ta wynosi 7 cyfr.

Typy zmiennoprzecinkowe mogą przechowywać bardzo duże liczby, ale z małą precyzją. Co to oznacza?
Np. liczba 72 678 942 będzie zaokrąglona do 7 cyfr znaczących i zapisana w postaci wykładniczej jako:
7.267894E+07
Oznacza to, że liczbę 7.267894 mnożymy przez 107 czyli przesuwamy przecinek o 7 pozycji w prawo. Ostatecznie dostajemy liczbę:
72 678 940
Jak widzisz, liczbę 72 678 942 zapisano jako 72 678 940, została ona zaokrąglona z uwzględnieniem 7 cyfrowej precyzji.

Przykładowo liczba 23 879 234 657 zostanie zapisana za pomocą typu float jako 2.387924E+10, czyli 23 879 240 000.

Za pomocą typu float możemy zapisać bardzo duże liczby, ale z ograniczoną precyzją.
W większości przypadków większa precyzja nie jest wymagana, ale jeśli zajdzie taka potrzeba należy użyć typu double lub decimal.

10
Wartości logiczne bool
Wartości logiczne boolean mogą przyjmować wartość true lub false.
Na ich podstawie działają komputery, które zbudowane są z milionów tranzystorów, które mają właśnie 2 stany 1 i 0, czyli prawda i fałsz.
Cały system opiera się na przełączaniu tych dwóch stanów na milionach mikroskopowych przekaźników.

W Unity będziemy wykorzystywać ten typ w podobny sposób.


Na tej podstawie możemy np. sprawdzać czy scena z grą została załadowana, czy gracz dotknął ziemi, czy klawisz myszy został naciśniety,
czy menu zostało aktywowane itp.
bool isMenuActive = true;
isMenuActive = false;

Wiele metod w Unity zwraca właśnie wartość typu bool i na ich podstawie będziemy mogli dokonywać odpowiednich decyzji w grze.
Zazwyczaj wartości typu bool wykorzystywane są z instrukcjami warunkowymi, które poznamy w dalszej części kursu.

11
Wartości tekstowe string
Wartości tekstowe w programowaniu zapisywane są w zmiennych typu string i zawsze powinny być zawarte wewnątrz cudzysłowu, np.:
string imie = "Angelika";

[Link]

Typ string różni się od typów prostych takich jak: int, float, bool czy char.
Wielkość pamięci zajmowanej przez zmienną typu string zależy od jej zawartości, czyli ilości znaków zapisanych wewnątrz niej.
W dużym uproszczeniu można powiedzieć, że zmienna typu string, która zawiera 5 znaków Unicode będzie zajmowała 5x2=10 bajtów
pamięci. Zmienna imie z przykładu powyżej będzie zajmowała ok. 8x2=16 bajtów pamięci.

Typ string w języku C# jest immutable, to znaczy, że nie można zmienić zawartości takiej zmiennej w taki sam sposób jak to miało miejsce
w przypadku typów prostych. Co prawda dla nas proces nadpisywania wygląda tak samo jak w przypadku typów prostych, to jednak za
kulisami proces ten wygląda zupełnie inaczej.
Stringi są obiektami, a zmienna przechowuje w sobie tylko adres do tej wartości. W przypadku nadpisania takiej zmiennej, w pamięci
komputera tworzony jest nowy obiekt z nową wartością, a w zmiennej podmieniony zostaje tylko adres do tego nowego miejsca w
pamięci komputera. Stara wartość zostanie z czasem usunięta przez specjalne narzędzie zwane Garbage Collector (GC).

12
Inkrementacja
Inkrementacja lub dekrementacja to zwiększenie lub zmniejszenie zmiennej o daną wartość.
Istnieją 3 sposoby zastosowania inkrementacji / dekrementacji:

int counter = 0;
counter = counter + 1; Istnieją 2 rodzaje inkrementacji:
counter += 1;
counter++; int counter = 0;
counter++; //postinkrementacja
Najkrótszej wersji counter++ stosuje się tylko do zmiany wartości o 1. ++counter; // preinkrementacja
W przypadku, gdy chcemy dostosować zmienną o inną wartość niż 1
lub za pomocą innej operacji niż +/-,
najczęsciej będziemy stosować formę skróconą, czyli: counter += 3;

Przykłady operacji inkrementacji: Pamiętaj o kolejności wykonywania operacji w języku C#.


int number = 0; W przykładzie poniżej, najpierw zostanie wyświetlona wartość
number += 5; // 0 + 5 (5) zmiennej, a dopiero później zostanie ona zwiększona o 1:
number -= 2; // 5 - 2 (3) int counter = 0;
number *= 4; // 3 * 4 (12) [Link](counter++);
number /= 2; // 12 / 2 (6) Ale już
number %= 5; // 6 % 5 (1) [Link](counter+=1);
Zmienna zostanie zwiększona i dopiero wyświetlona

13
Kolejność wykonywania operacji
Category Operator Associativity
Postfix () [] -> . ++ -- Left to right
Unary + - ! ~ ++ - - (type)* & sizeof Right to left
Multiplicative */% Left to right
Additive +- Left to right
Relational < <= => > Left to right
Equality == != Left to right
Logical AND && Left to right
Logical OR || Left to right
Conditional ?: Right to left
Assignment = += -= *= /= %= Right to left
Comma , Left to right
14
Tablice
Tablice służą do przechowywania stałej ilości elementów o takim samym typie danych. W celu przechowania 3
liczb całkowitych możemy stworzyć tablicę o typie int, podając liczbę elementów, które znajdą się w niej, np.:

int[] liczby = new int[3];


liczby[0] = 12;
liczby[1] = 51;
liczby[2] = 32;
Tworzenie tablicy o typie Transform, której
elementy możemy dołączyć bezpośrednio w oknie
[Link](liczby[0]); // wyśw. element o indeksie 0
Unity:
[Link]([Link]); // wyśw. ilość elementów tablicy
[SerializeField] Transform[] pozycje;
Tablica jest kolekcją której elementy są indeksowane, tzn. każdy element tablicy
przypisany jest do numeru porządkowego, który określa jego miejsce w tablicy.
Indeksowanie (jak niemal wszystko w programowaniu) zaczynamy od 0.

Możemy też stworzyć tablicę od razu ją inicjalizując wartościami, np.:

string[] imiona = new string[]{"Kasia", "Basia", "Stasia", "Asia"};

Tablice możemy sortować dodając bibliotekę System w następujący sposób:


[Link](liczby);
[Link](liczby);
15
Listy
Listy działają podobnie jak tablice, tyle, że ilość elementów tablicy można dowolnie zmieniać w
trakcie gry. List użyjemy wtedy, gdy w trakcie gry chcemy dodawać lub usuwać jej elementy.
Listy są dostępne z biblioteki using [Link];

Przykład stworzenia listy typu string i dodanie do niej kilku elementów:


Tworzenie listy o typie GameObject, której elementy
List<string> auta = new List<string>();
możemy dołączyć bezpośrednio w oknie Unity:
[Link]("maluch");
[Link]("trabant");
[SerializeField] List<GameObject> enemies;
[Link]("mustang");
[Link](auta[0]); // wyśw. elementu listy o indeksie 0

[Link]("maluch"); //usuwa element "maluch"


[Link](1); //usuwanie elementu o indeksie 1

[Link]([Link]); // wyświetlanie liczby elementów listy

Sortowanie listy
[Link]();
[Link]();

16
Pętla foreach
Pętla pozwala wykonywać powtarzalne instrukcje dopóki podany warunek jest spełniony. Mamy do dyspozycji 4 pętle: foreach, for,
while i do while. Pętla foreach jest używana wraz z kolekcjami (tablicami, listami, wartościami typu string).

Przykład: Wypisz w konsoli wszystkie elementy tablicy

string[] imiona = new string[] { "Kasia", "Basia", "Stasia", "Asia" };


foreach (string i in imiona)
{
[Link](i);
}

Przykład: Wypisz elementy listy od najmniejszej do największej

List<int> liczby = new List<int>();


[Link](21);
[Link](2);
[Link](12);
[Link](33);
[Link]();
foreach(int i in liczby){
[Link](i);
}
17
Pętla for
Pętla for daje nam większe możliwości i swobodę niż pętla foreach. Syntax pętli for:

for(zmienna_iteracyjna; warunek; skok)


{
// instrukcje do wykonania
- Zmienna iteracyjna inicjalizuje pętle,
}
- podany warunek jest wyznacznikiem tego,
Przykład: Za pomocą pętli for wypisz liczby od 1 do 10
kiedy pętla ma zakończyć działanie,
for(int i = 1; i <= 10; i++)
- skok modyfikuje wartość zmiennej iteracyjnej
{
[Link](i);
}

Przykład. Wyświetl elementy tablicy za pomocą pętli for

string[] imiona = new string[] { "Kasia", "Basia", "Stasia", "Asia" };

for (int i = 0; i < [Link]; i++)


{
[Link](imiona[i]);
}
18
Pętla while
Pętla while daje podobną swobodę co pętla for. Często używana jest podczas pobierania danych z zewnątrz (z pliku, internetu).

Przykład: Za pomocą pętli while wypisz liczby od 5 do 20 Syntax pętli while:

int i = 5; zmienna_iteracyjna;
while(i <= 20) while(warunek_wykonania_pętli)
{ {
[Link](i); //instrukcje;
i++; skok;
} }

Przykład. Wyświetl elementy tablicy za pomocą pętli while

string[] imiona = new string[] { "Kasia", "Basia", "Stasia", "Asia" };


int i = 0;
while(i < [Link])
{
[Link](imiona[i]);
i++;
}
19
Komponenty
W Unity, dodatkowe funkcjonalności do obiektów dodaje się za pomocą komponentów.
To komponenty sprawiają, że dany obiekt w grze staje się kamerą, graczem, przeciwnikiem, itp. Wszystkie komponenty widoczne są w
oknie Inspector i każdy z nich ma określone właściwości, które można modyfikować, a także funkcje, które można wyzwalać za pomocą
kodu.

W celu zmiany właściwości lub wyzwolenia funkcji dostępnych dla danego komponentu należy odnieść się do niego w skrypcie za pomocą
GetComponent<Nazwa Komponentu>().

Odniesienie do komponentu Transform:


GetComponent<Transform>();

Pobranie nazwy obiektu do którego dołączony jest skrypt:


[Link](GetComponent<Transform>().position);

Komponent Transform zawsze występuje w każdym obiekcie na scenie,


dlatego Unity umożliwia pobranie tego komponentu w łatwiejszy sposób,
za pomocą aliasu transform, który zastępuję instrukcję GetComponent<Transform>().
Np. Możemy użyć [Link]([Link]); zastępując przykład powyżej.

20
Komponenty - cache
W przypadku, gdy do danego komponentu będziemy chcieli odnosić się wielokrotnie, należy go przypisać do zmiennej (cache), aby
ustalenie tego połączenia nastąpiło tylko raz, co wpływa pozytywnie na wydajność programu.
Komponenty cache’ujemy (czyt. kaszujemy) przypisując je do zmiennej o tym samym typie, co sam komponent (ponieważ komponent
jest klasą, a klasa definiuje typy w programowaniu).

Chcąc zapisać połączenie do komponentu SpriteRenderer zrobimy to w następujący sposób:

SpriteRenderer spriteRenderer;

void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
}
void Start()
{
[Link] = [Link];
}

Dzięki takiemu podejściu w dalszej części programu możemy odnosić się do danego komponentu za pomocą zmiennej spriteRenderer.
W większości przypadków komponenty cache’ujemy w metodzie Awake() choć w niektórych przypadkach, możemy to również zrobić w
metodzie Start().

21
new Vector3(float x, float y, float z)
W Unity bardzo często korzysta się z wektorów, które są zestawem wartości x, y, z.
Wektory są obiektami, więc za każdym razem, kiedy będziemy je inicjalizować, użyjemy słowa kluczowego new.
Składowe wektorów są wartościami typu float.
Wektory mogą określać kierunek, pozycję, skalę i inne właściwości,
które wymagają 3 cech składowych.

W celu stworzenia wektora o składowych x=10f, y=0f, z=0f użyjemy instrukcji:


Vector3 newPosition = new Vector3(10f, 0f, 0f);

Chcąc teraz ustawić nową pozycję określoną powyższym wektorem możemy użyć instrukcji:
[Link] = newPosition;

Przykład jak zmienić aktualną pozycję o nowy wektor:


[Link] += new Vector3(10f, 2f, 0f);

W przykładzie poniżej zmienimy skalę obiektu, która będzie różna dla każdej z trzech wartości:
[Link] = new Vector3(2f, 3f, 4f);
Zapis powyżej zwiększy szerokość obiektu 2x, wysokość 3x i głębokość 4x.

22
Input – Kliknięcia myszy
Do sprawdzania interakcji użytkownika za pomocą myszy możemy skorzystać z wielu metod klasy Input, np:
GetMouseButton, GetButton, GetKey.

[Link](0);
Zwraca wartość bool true, kiedy określony przycisk myszy jest wciśnięty
Lista argumentów:
[Link](0);
Zwraca jednorazowo wartość true, w klatce, w której wykryto wciśnięcie przycisku 0 / Fire1 / Mouse0 – LMB (Left)
1 / Fire2 / Mouse1 – RMB (Right)
[Link](0);
Zwraca jednorazowo wartość true, w klatce, w której wykryto zwolnienie przycisku 2 / Fire3 / Mouse2 – MMB (Middle)

Zazwyczaj wykrywanie interakcji użytkownika sprawdza się w metodzie Update().

if ([Link](0)) if ([Link]("Fire1")) if ([Link](KeyCode.Mouse0))


{ { {
// instrukcje do wykonania // instrukcje do wykonania // instrukcje do wykonania
} } }

23
Input – GetAxis
Klasa Input zawiera metodę, dzięki której możemy odczytywać wartości osi joysticku lub klawiszy WSAD.
Klawisze AD i strzałki Left/Right będziemy traktować jako oś poziomą X
Klawisze WS i strzałki Up/Down będziemy traktować jako oś pionową Y
W przypadku ruchu pod kątem mamy do czynienia z dodawaniem składowych X i Y, co objawia się większą prędkością
poruszania. W celu zniwelowania tego efektu, należy taki wektor znormalizować.

float speed = 10f;


float osX, osY;

void Update()
{
osX = [Link]("Horizontal");
osY = [Link]("Vertical");
[Link](new Vector3(osX, osY, 0).normalized*speed*[Link]);
}

24
Losowa liczba
Rozgrywka byłaby nudna, gdyby zawsze wyglądała w dokładnie taki sam sposób. Za pomocą losowości można uatrakcyjnić
tworzoną grę. Język C# posiada klasę Random, która znajduje się w przestrzeni nazw – System. Biblioteka UnityEngine też
posiada osobną klasę Random i to właśnie jej będziemy używać do tego celu.
Możemy stworzyć losowe liczby typu int i float.

int/float rand = [Link](min, max);

int rand = [Link](0, 11); // Losuj liczbę int od 0 do 10 włącznie

W przypadku typu integer, wartość minimalna jest inclusive, a maksymalna exclusive. Oznacza to, że wartość maksymalna
nigdy nie zostanie wylosowana. Chcąć ustalić zakres losowania, należy wartość maksymalną zwiększyć o 1.

float rand2 = [Link](0f, 1.0f); // Losuj liczbę float od 0 do 1.0 włącznie

W przypadku typu float, zarówno min i max są wartościami inclusive, oznacza to, że wylosowana liczba będzie z pełnego
zakresu.

25
Spawnowanie

W celu stworzenia obiektów na scenie w czasie gry użyjemy metody Instantiate().


Za jej pomocą możemy dodać do sceny obiekty (prefaby) w wyznaczonym przez nas miejscu, rotacji i wielu innych parametrach.
Metoda Instantiate zawiera wiele przeciążeń, dzięki czemu możemy spawnować obiekty na wiele sposobów.

Przykład poniżej pokazuje jak utworzyć obiekt(prefab) w jego domyślnym położeniu.

[SerializeField] GameObject prefab;


void Start()
{
Instantiate(prefab);
}

Możemy utworzyć obiekt w wybranym przez nas miejscu i o określonej rotacji za pomocą odpowiedniego przeciążenia metody
Instantiate()

Instantiate(prefab, new Vector3(4f,-4f,0f), [Link]);

26
Spawnowanie

Spawnowanie prefabów w losowej pozycji i losowej rotacji po kliknięciu myszy

[SerializeField] GameObject prefab;


float GetRand(float min, float max){
return [Link](min, max);
}
void Update(){
if ([Link](0))
{
Vector3 pos = new Vector3(GetRand(-8, 8), GetRand(-4, 4), 0f);
Quaternion rot = [Link](0f, 0f, GetRand(-180, 180));
Instantiate(prefab, pos, rot);
}
}

27
Input – Pozycja myszy na ekranie
Sprawdzanie pozycji x kursora myszy na ekranie

[Link]([Link].x / [Link]);

Spawnowanie obiektu w pozycji kursora

[SerializeField] GameObject prefab;


Camera cam;
void Awake()
{
cam = [Link];
}

void Update()
{
if ([Link](0))
{
Vector3 mousePos = [Link]([Link]);
mousePos.z = 0f;
Instantiate(prefab, mousePos, [Link]);
}
}
28
Rotacja względem kursora myszy
Camera cam;
void Start()
{
cam = [Link];
}

void Update()
{
Vector3 mousePos = [Link]([Link]);
Vector3 diff = mousePos - [Link];
[Link]();
float rotZ = Mathf.Atan2(diff.y, diff.x)*Mathf.Rad2Deg;
[Link] = [Link](0f, 0f, [Link](rotZ, -6f,90f));

29
Input – OnMouseDrag
Droppable object

Moveable object void OnTriggerStay2D(Collider2D collision)


{
Camera cam; [Link] = [Link];
Vector3 offset; }
private void Awake(){
cam = [Link];
}
private void OnMouseDrag(){
[Link] = GetMousePos() + offset;
}

private void OnMouseDown(){


offset = [Link] - GetMousePos();
}

Vector3 GetMousePos(){
Vector3 mousePos = [Link]([Link]);
mousePos.z = 0f;
return mousePos;
}
30
Najpotrzebniejsze skróty w Visual Studio

Ctrl + D Duplikowanie linii kodu


Alt + Up/Dow Przesuwanie zaznaczonego kodu w górę / dół
Shift + Up/Down Zaznaczanie wielu linii kodu
(Ctrl + R) x2 Zmiana nazwy występującej w wielu miejscach
Tab Tworzenie indentacji
Shift + Tab Cofanie indentacji
Ctrl + . Menu Quick Action and Refactoring
Ctrl + Shift + Space Kliknięty wewnątrz nawiasu pokazuje dostępne przeciążenia

31
Player movement rb
public class PlayerMove : MonoBehaviour
{
float dirX;
float speedX = 10f;
Rigidbody2D rb;

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

void Update()
{
dirX = [Link]("Horizontal");
}

private void FixedUpdate()


{
[Link] = new Vector2(dirX * speedX, [Link].y);
}
}

32
Player jump rb

public class PlayerJump : MonoBehaviour


{ private void FixedUpdate()
Vector2 jumpForce = new Vector2(0f, 3000f); {
int jumpMaxNumber = 2; Jump();
int jumpNumber = 0; }
bool isJumping = false;
Rigidbody2D rb; void Jump()
{
private void Awake() if(isJumping && jumpNumber <= jumpMaxNumber)
{ {
rb = GetComponent<Rigidbody2D>(); [Link](jumpForce, [Link]);
} }
if([Link]([Link].y) < 0.001f)
void Update() {
{ jumpNumber = 0;
if ([Link]([Link])) }
{ isJumping = false;
isJumping = true; }
jumpNumber++;
} }
}

33
Pocisk

public class Bullet : MonoBehaviour


{
Rigidbody2D rb;
[SerializeField] float speed = 50f;

void Start()
{
rb = GetComponent<Rigidbody2D>();
[Link] = [Link] * speed;
Destroy(gameObject, 2f);
}
}

34
Strzelanie

public class Gun : MonoBehaviour


{
[SerializeField] GameObject prefab;
[SerializeField] Transform aim;

void Update()
{
if ([Link](0))
{
Shoot();
}
}

void Shoot()
{
GameObject bullet = Instantiate(prefab, [Link], [Link]);
}
}

35
Hp
public class Bullet : MonoBehaviour public class Hp : MonoBehaviour
{ {
Rigidbody2D rb; [SerializeField] int maxHp = 10;
[SerializeField] float speed = 50f; int hp;
[SerializeField] int attack = 1;
void Start()
void Start() {
{ hp = maxHp;
rb = GetComponent<Rigidbody2D>(); }
[Link] = [Link] * speed;
Destroy(gameObject, 2f); public void TakeDamage(int damage)
} {
hp -= damage;
private void OnCollisionEnter2D(Collision2D collision) if(hp <= 0)
{
{
Hp hp = [Link]<Hp>();
if(hp != null) Destroy(gameObject);
{ }
[Link](attack); }
} }
Destroy(gameObject);
}
}

36

You might also like