Witaj nieznajomy
Użytkownik:

Hasło:

Pamiętaj mnie

Zarajestruj się TUTAJ.
Main
News
Linki
Galeria
Polityka prywatności
Artykuły
Różne
O UnrealED
Unreal Script
Unreal Engine 1
Unreal Engine 3
Gotowce
Mody
W produkcji
Skończone
Nigdy nie ukończone
Download
Mapy
Assault
Capture The Flag
Domination
Death Match
Mappacki
Single Player
Archiwum
Inne
Mutatory
Tutoriale
Programy
UnrealED
Brushe
Muzyka
Programy
Prefabs
Tekstury
Skrypty
Przykłady
Losowy obrazek

Nali Castle
Nazwa: Nali Castle
Dodał: Raven

Inne



Hostowanie







O Unreal Script
Unreal Engine 1 Unreal Script 1 Wstęp


     Na samym wstępie, chciałbym zaznaczyć, że nie jestem jakiś wielkim masterem z tej dziedziny. Opanowałem w mniejszym lub większym stopniu Unreal Script i to właśnie zamierzam omówić. Jeśli znasz już jakiś język programowania, to równie dobrze możesz pominąć część lekcji, gdyż będą to podstawy.

Edytory

     UnrealED posiada swój własny edytor skryptów, jednakże z wielu powodów jest on nieporęczny i bezużyteczny na dłuższą metę. Jeśli mamy zamiar napisać jeden króciutki skrypcik będzie w sam raz, jeśli jednak piszemy moda, w którego skład wchodzi kilka(naście/dziesiąt/set) skryptów radzę zastanowić się nad przesiadką na coś lepszego w obsłudze. Ja używam ConText, którego głównym atutem, jest możliwość dodania definicji (podświetlenie) dla dowolnego języka programowania - w tym Unreal Script (na stronie projektu), a oprócz tego posiada możliwość edycji wielu plików naraz. Do pełni szczęścia możemy ściągnąć program o nazwie UnCodeX. Pozwoli on na wgląd w strukturę całej gry jak z menu Actor Classes z UnrealED 2.0. Do tego, jeśli chcemy, możemy dołączyć program UMake, który zastąpi nam częściowo polecenie UCC make. Jeśli jednak chcemy w pełni zautomatyzować proces kompilacji sugeruję 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 językach a np. taki C++ jest tylko jednym z wielu. Koncepcje OOP można najkrócej ująć w słowach: "Wszystko jest obiektem". Może śmiesznie to brzmi, ale taka jest prawda. Rakietnica, Skaarj, ASMD i cała reszta to obiekty. Obiekty te są kontrolowane przez kod (który to jest zawarty w klasie). Sama z siebie rakietnica nie będzie strzelać, będzie tylko statycznym modelem, to kod sprawia, że możesz strzelać, że rakieta wybucha, granat się odbija kilka razy, itp.
     Teraz przyjrzyj się klasom widocznym w "Actor Class Browser" w UED. Jak zatem widzisz wszystko co napiszesz na początku będzie należało do klasy Actor albo do klas potomnych. W istocie nie widzisz wszystkiego. Odznacz "Actor Classes Only", wtedy zobaczysz podstawę wszystkich klas – Object. Cała idea polega na tym, że KAŻDA klasa potomna dziedziczy kod klasy macierzystej. Dlatego tworząc nową broń lub NPC, nie musisz pisać wszystkiego od początku, wystarczy, że rozszerzysz o nowe funkcje istniejące klasy. A jak to wygląda w praktyce? przyjrzyjmy się bliżej czemuś takiemu:

Unreal Script:
  1. class MyClass extends Actor;


     Odczytujemy to tak: klasa MyClass należy do klasy Actor i dziedziczy wszystkie jej zmienne i funkcje. Co jednak dzięki temu zyskujemy? Ułatwienie i możliwość skrócenia kodu. Otóż możemy zrobić nową klasę Maga Nalich. W nim zadeklarujemy podstawowe funkcje (np. rzucanie czarów zależne od poziomu maga). Wtedy jeśli chcemy lekko zmienić jego zachowanie, nie musimy pisać od nowa całego kodu, wystarczy nam tylko modyfikacja wybranej funkcji. Hierarchiczność pozwala nam np. na coś 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 klasą NewPlayerPawn i jeśli tak jest, przyporządkowuje do zmiennej NewIntVar liczbę 200 (oczywiście zamiast klasy NewPlayerPawn i zmiennej NewIntVar możemy wstawić własną). A zatem zapis: Actor InputActor oznacza, że funkcja oczekuje, że wywołamy ją z klasą Actor lub którąś z potomnych. Niestety nie możemy zrobić 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 są interpretowane (jeśli niektóre skrypty są natywne, następuje linkowanie z biblioteką .dll) i kompilowane do pliku .u. Do kompilowania można wykożystać dwa narzędzia program UMake (wspomniany we wstępie) i komendę UCC make. Jaka jest różnica? UMake jest poręczniejszy, jednakże w przypadku większych modów, polecałbym polecenie UCC make i jakiegoś batcha.

     Załóżmy, że mamy gotowy projekt, na który składa się pięć folderów ze skryptami:
  • SPMenu
  • SPDeco
  • SPSystem
  • SPWeapons
  • SPItems
     Jeśli nie chcemy edytować pliki UnrealTournament.ini możemy zrobić własny plik .ini i wywołać komendę 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 końcu sekcji Editor.EditorEngine dodajemy własny EditPackages=... za trzy kropki wstawiając nazwę katalogu ze skryptami. Plik ini najlepiej umieścić w katalogu ze skryptem i nazwać np. make.ini. Teraz wystarczy skasować istniejący package (jeśli nasza klasa była skompilowana wcześniej) i wywołać komendę ucc make ini=... albo napisać 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 jeśli tak jest skasuje go a następnie skompiluje go ponownie. Oczywiście jeśli umieścimy batcha w katalogu system należy skasować cd system i cd... W zasadzie powinienem był napisać "spróbuje skompilować" gdyż nie zawsze kompilacja się udaje. Jest to spowodowane błędami, które popełniliśmy pisząc skrypt. Oczywiście błąd nie zawsze powoduje przerwanie kompilacji. Pomniejsze takie jak niezgodność nazwy pliku i klasy spowodują jedynie drobne ostrzeżenie i skrypt będzie skompilowany.



Nigdy nie rekompiluj rdzenia gry

     Nigdy nie próbuj rekompilować, dodawać, zmieniać zawartość podstawowych plików gry, które zostały dołączone do którejkolwiek gry na silniku Unreal Engine. Nie możesz dodawać tekstur, dźwięków, meshy, klas NICZEGO! Dlaczego? Otóż przy każdej kompilacji generowana jest suma kontrolna, która to jest sprawdzana przez serwery i w razie jakichkolwiek różnic klient zostaje odłączony. Jest to mechanizm, który gwarantuje, że wszyscy grają w tę samą grę, bez żadnych modyfikacji.

Komentarze

     W Unreal Script są dwa typy komentarzy jedno i wielo linjkowe:

Unreal Script:
  1.       // taki komentarz jest tylko do końca linijki
  2.       /* ten zaś może być rozciągnięty na kilka linijek
  3.           koniecznie trzeba go zamknąć */ 


     Pamiętaj też, żeby w przeciwieństwie do przykładów z tutoriali na stronie, NIGDY nie pisać komentarzy (i zmiennych) po Polsku. Zapewne kiedyś udostępnisz część skryptów, które napisałeś i gdy komentarze i zmienne nie będą po angielsku to 99.9% mapperów z zagranicy nie będzie ich używać. To samo dotyczy ReadMe. Te jednak najlepiej dawać i po Polsku i po Angielsku.

Deklaracja Klasy

     Klasę definiuje się w następujący sposób:

Unreal Script:
  1. class MojaKlasa extends KlasaMaciezysta;


     Oznacza to, że klasa MojaKlasa należy do KlasaMacierzysta i może korzystać
z wszystkich jej funkcji i zmiennych. Do definicji klasy można dodać kilka końcówek:

Kod:
native – skrypt korzysta z c++ i szuka plików dll o nazwie danego package.
intrinsic – j.w. :)
abstract – klasy z końcówką abstract nie można umieścić na mapie. działa tylko na deklarowaną klasę, nie na pochodne.
NoUserCreate – mapper nie może umieścić na mapie tej klasy, ale można to zrobić poprzez inny skrypt, w przeciwieństwie do powyższej końcówki.
transient – klasa taka nie jest zapisywana podczas gry.
config(plik) – klasa używa pliku konfiguracyjnego.


     Czyli np. można zrobić coś takiego:

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


     Znaczy to mniej więcej tyle: klasa NewClass, należąca do klasy Actor jest natywna (można implementować w niej funkcje z C++), nie może być wstawiana na mapy przez mappera i jej zmienne mogą być zapisywane w pliku User.ini.

Extends czy Expands

     Tak naprawdę nie ma różnicy czy przy deklaracji użyjemy wyrażenia extends czy expands, jednak najlepiej jest używać tego pierwszego (extends), ponieważ w silnikach wyższych niż Unreal Engine 1.x expands nie jest używane.

Raven dnia 01 Grudzień 2007, 12:56 - Skomentuj (0)

All graphics created by InfectedFx and modified by Raven, except turniej.unreal.pl logo.
Site engine and design created by Raven 2004©. All rights reserved.

Strona korzysta z plików cookie w celu realizacji usług zgodnie z Polityką prywatności.