O Unreal Script - [UE1] [UC] 1 Wstep by Raven dnia: 01 Grudzien 2007, 12:56
     Na samym wstepie, chcialbym zaznaczyc, ze nie jestem jakis wielkim masterem z tej dziedziny. Opanowalem w mniejszym lub wiekszym stopniu Unreal Script i to wlasnie zamierzam omówic. Jesli znasz juz jakis jezyk programowania, to równie dobrze mozesz pominac czesc lekcji, gdyz beda to podstawy.

Edytory

     UnrealED posiada swój wlasny edytor skryptów, jednakze z wielu powodów jest on nieporeczny i bezuzyteczny na dluzsza mete. Jesli mamy zamiar napisac jeden króciutki skrypcik bedzie w sam raz, jesli jednak piszemy moda, w którego sklad wchodzi kilka(nascie/dziesiat/set) skryptów radze zastanowic sie nad przesiadka na cos lepszego w obsludze. Ja uzywam ConText, którego glównym atutem, jest mozliwosc dodania definicji (podswietlenie) dla dowolnego jezyka programowania - w tym Unreal Script (na stronie projektu), a oprócz tego posiada mozliwosc edycji wielu plików naraz. Do pelni szczescia mozemy sciagnac program o nazwie UnCodeX. Pozwoli on na wglad w strukture calej gry jak z menu Actor Classes z UnrealED 2.0. Do tego, jesli chcemy, mozemy dolaczyc program UMake, który zastapi nam czesciowo polecenie UCC make. Jesli jednak chcemy w pelni zautomatyzowac proces kompilacji sugeruje napisanie prostego batcha.

ConText: http://www.context.cx
UnCode: http://wiki.beyondunreal.com/wiki/UnCodeX
UMake: http://mb.link-m.de/umake

OOP i Unreal Script

     OOP - "Object Oriented Programming" - inaczej programowanie obiektowe, jest wykorzystywane w wielu jezykach a np. taki C++ jest tylko jednym z wielu. Koncepcje OOP mozna najkrócej ujac w slowach: "Wszystko jest obiektem". Moze smiesznie to brzmi, ale taka jest prawda. Rakietnica, Skaarj, ASMD i cala reszta to obiekty. Obiekty te sa kontrolowane przez kod (który to jest zawarty w klasie). Sama z siebie rakietnica nie bedzie strzelac, bedzie tylko statycznym modelem, to kod sprawia, ze mozesz strzelac, ze rakieta wybucha, granat sie odbija kilka razy, itp.
     Teraz przyjrzyj sie klasom widocznym w ”Actor Class Browser” w UED. Jak zatem widzisz wszystko co napiszesz na poczatku bedzie nalezalo do klasy Actor albo do klas potomnych. W istocie nie widzisz wszystkiego. Odznacz "Actor Classes Only", wtedy zobaczysz podstawe wszystkich klas – Object. Cala idea polega na tym, ze KAZDA klasa potomna dziedziczy kod klasy macierzystej. Dlatego tworzac nowa bron lub NPC, nie musisz pisac wszystkiego od poczatku, wystarczy, ze rozszerzysz o nowe funkcje istniejace klasy. A jak to wyglada w praktyce? przyjrzyjmy sie blizej czemus takiemu:

Unreal Script:
  1. class MyClass extends Actor;


     Odczytujemy to tak: klasa MyClass nalezy do klasy Actor i dziedziczy wszystkie jej zmienne i funkcje. Co jednak dzieki temu zyskujemy? Ulatwienie i mozliwosc skrócenia kodu. Otóz mozemy zrobic nowa klase Maga Nalich. W nim zadeklarujemy podstawowe funkcje (np. rzucanie czarów zalezne od poziomu maga). Wtedy jesli chcemy lekko zmienic jego zachowanie, nie musimy pisac od nowa calego kodu, wystarczy nam tylko modyfikacja wybranej funkcji. Hierarchicznosc pozwala nam np. na cos takiego:

Unreal Script:
  1. function CosTam(Actor InputActor)
  2. {
  3.      if(InputActor.IsA('NewPlayerPawn')
  4.         NewPlayerPawn(InputActor).NewIntVar=200;
  5. }


     Co robi ta funkcja? Sprawdza, czy wprowadzony aktor jest klasa NewPlayerPawn i jesli tak jest, przyporzadkowuje do zmiennej NewIntVar liczbe 200 (oczywiscie zamiast klasy NewPlayerPawn i zmiennej NewIntVar mozemy wstawic wlasna). A zatem zapis: Actor InputActor oznacza, ze funkcja oczekuje, ze wywolamy ja z klasa Actor lub któras z potomnych. Niestety nie mozemy zrobic tego wstecz, tzn:

Unreal Script:
  1. function CosTam(NewPlayerPawn InputActor)
  2. {
  3.     if(InputActor.IsA('Actor')
  4.      Actor(InputActor).NewIntVar=200;
  5. }


Kompilacja

     Proces w którym napisane skrypty sa interpretowane (jesli niektóre skrypty sa natywne, nastepuje linkowanie z biblioteka .dll) i kompilowane do pliku .u. Do kompilowania mozna wykozystac dwa narzedzia program UMake (wspomniany we wstepie) i komende UCC make. Jaka jest róznica? UMake jest poreczniejszy, jednakze w przypadku wiekszych modów, polecalbym polecenie UCC make i jakiegos batcha.

     Zalózmy, ze mamy gotowy projekt, na który sklada sie piec folderów ze skryptami:     Jesli nie chcemy edytowac pliki UnrealTournament.ini mozemy zrobic wlasny plik .ini i wywolac komende ucc make z parametrem ini. W tym celu najpierw stwórzmy nowy plik ini:

Kod:
[Engine.Engine]
EditorEngine=Editor.EditorEngine

[Editor.EditorEngine]
CacheSizeMegs=32
EditPackages=Core
EditPackagesEngine
EditPackages=Editor
EditPackages=UWindow
EditPackages=Fire
EditPackages=IpDrv
EditPackages=UWeb
EditPackages=UBrowser
EditPackages=UnrealShare
EditPackages=UnrealI
EditPackages=UMenu
EditPackages=IpServer
EditPackages=Botpack
EditPackages=UTServerAdmin
EditPackages=UTMenu
EditPackages=UTBrowser

[Core.System]
Paths=*.u
Paths=../Maps/*.unr
Paths=../Textures/*.utx
Paths=../Sounds/*.uax
Paths=../Music/*.umx


     I na koncu sekcji Editor.EditorEngine dodajemy wlasny EditPackages=... za trzy kropki wstawiajac nazwe katalogu ze skryptami. Plik ini najlepiej umiescic w katalogu ze skryptem i nazwac np. make.ini. Teraz wystarczy skasowac istniejacy package (jesli nasza klasa byla skompilowana wczesniej) i wywolac komende ucc make ini=... albo napisac prostego batcha który zrobi to za nas:

Kod:
@echo off
cd system
if exist MyPackage.u del MyPackage.u
ucc make ini=../MyPackage/make.ini
cd..


     Taki batch sprawdzi czy istnieje plik MyPackage.u i jesli tak jest skasuje go a nastepnie skompiluje go ponownie. Oczywiscie jesli umiescimy batcha w katalogu system nalezy skasowac cd system i cd... W zasadzie powinienem byl napisac "spróbuje skompilowac" gdyz nie zawsze kompilacja sie udaje. Jest to spowodowane bledami, które popelnilismy piszac skrypt. Oczywiscie blad nie zawsze powoduje przerwanie kompilacji. Pomniejsze takie jak niezgodnosc nazwy pliku i klasy spowoduja jedynie drobne ostrzezenie i skrypt bedzie skompilowany.



Nigdy nie rekompiluj rdzenia gry

     Nigdy nie próbuj rekompilowac, dodawac, zmieniac zawartosc podstawowych plików gry, które zostaly dolaczone do którejkolwiek gry na silniku Unreal Engine. Nie mozesz dodawac tekstur, dzwieków, meshy, klas NICZEGO! Dlaczego? Otóz przy kazdej kompilacji generowana jest suma kontrolna, która to jest sprawdzana przez serwery i w razie jakichkolwiek róznic klient zostaje odlaczony. Jest to mechanizm, który gwarantuje, ze wszyscy graja w te sama gre, bez zadnych modyfikacji.

Komentarze

     W Unreal Script sa dwa typy komentarzy jedno i wielo linjkowe:

Unreal Script:
  1.       // taki komentarz jest tylko do konca linijki
  2.       /* ten zas moze byc rozciagniety na kilka linijek
  3.           koniecznie trzeba go zamknac */ 


     Pamietaj tez, zeby w przeciwienstwie do przykladów z tutoriali na stronie, NIGDY nie pisac komentarzy (i zmiennych) po Polsku. Zapewne kiedys udostepnisz czesc skryptów, które napisales i gdy komentarze i zmienne nie beda po angielsku to 99.9% mapperów z zagranicy nie bedzie ich uzywac. To samo dotyczy ReadMe. Te jednak najlepiej dawac i po Polsku i po Angielsku.

Deklaracja Klasy

     Klase definiuje sie w nastepujacy sposób:

Unreal Script:
  1. class MojaKlasa extends KlasaMaciezysta;


     Oznacza to, ze klasa MojaKlasa nalezy do KlasaMacierzysta i moze korzystac
z wszystkich jej funkcji i zmiennych. Do definicji klasy mozna dodac kilka koncówek:

Kod:
native – skrypt korzysta z c++ i szuka plików dll o nazwie danego package.
intrinsic – j.w. :)
abstract – klasy z koncówka abstract nie mozna umiescic na mapie. dziala tylko na deklarowana klase, nie na pochodne.
NoUserCreate – mapper nie moze umiescic na mapie tej klasy, ale mozna to zrobic poprzez inny skrypt, w przeciwienstwie do powyzszej koncówki.
transient – klasa taka nie jest zapisywana podczas gry.
config(plik) – klasa uzywa pliku konfiguracyjnego.


     Czyli np. mozna zrobic cos takiego:

Unreal Script:
  1. class NewClass extends Actor native NoUserCreate config(User);


     Znaczy to mniej wiecej tyle: klasa NewClass, nalezaca do klasy Actor jest natywna (mozna implementowac w niej funkcje z C++), nie moze byc wstawiana na mapy przez mappera i jej zmienne moga byc zapisywane w pliku User.ini.

Extends czy Expands

     Tak naprawde nie ma róznicy czy przy deklaracji uzyjemy wyrazenia extends czy expands, jednak najlepiej jest uzywac tego pierwszego (extends), poniewaz w silnikach wyzszych niz Unreal Engine 1.x expands nie jest uzywane.