Fabryki kolekcji to komponenty używane do tworzenia grup i hierarchi obiektów gry przechowywanych w pliku danej kolekcji w trakcie działania programu.
Kolekcje są potężnym narzędziem do tworzenia szablonów, które można utylizować wielokrotnie (podobnie jak prefaby). Więcej szczegółów na temat kolekcji znajdziesz w dokumentacji podstawowych elementów Defold. Kolekcje mogą być umieszczane bezpośrednio w Edytorze lub tworzone dynamicznie.
Używając fabryki kolekcji możesz tworzyć w świecie gry zawartość pliku kolekcji. Jest to uproszczonie analogicznego procesu tworzenia wszystkich obiektów gry opisanych w danym pliku kolekcji i przypisywanie im relacji rodzic-dziecko również opisanych w takim pliku. Typowym przykładem jest tworzenie postaci wrogów składających się z wielu różnych obiektów (np. jedno z wariantów ciał + jedna z broni).
Załóżmy, że chcesz, żeby obiekt reprezentujący Twojego bohatera miał również obiekt-dziecko reprezentujący tarczę. Zbudujemy taką hierarchię w pliku kolekcji i zapiszemy jako “bean.collection”.
Komponent typu pełnomocnik kolekcji (collection proxy) różni się od fabryki i jest używany do stworzenia nowego świata gry, a co za tym idzie również osobnego świata fizyki z obiektami bazującymi na hierarchi w pliku danej kolekcji. Nowy świat ma swoje nowe gniazdo (socket), więc i nową przestrzeń adresową. Wszystkie zasoby z danej kolekcji są wczytywane przez pełnomocnika, kiedy wyślesz do niego wiadomość o rozpoczęciu wczytywania. Jest więc to przydatne przykładowo przy tworzeniu nowych poziomów w grze. Nowy świat gry wiąże się jednak z zajęciem sporej ilości nowych zasobów w pamięci, więc lepiej nie używać ich do dynamicznego wczytywania. Więcej szczegółów znajdziesz w dokumentacji pełnomocników kolekcji.
Dodajemy następnie komponent typu Collection factory (Fabryka kolekcji) do obiektu gry, który będzie odpowiedzialny za stworzenie obiektów i hierarchi z pliku kolekcji “bean.collection” podanego jako właściwość Prototype:
Tworzenie bohatera i tarczy jest teraz tylko kwestią wywołania funckji collectionfactory.create()
:
local bean_ids = collectionfactory.create("#bean_factory")
Funkcja przyjmuje 5 parameterów:
url
[position]
vector3
. Jeśli nie określisz pozycji, obiekty będą tworzone w miejscu komponentu fabryki kolekcji.[rotation]
quat
. Jeśli nie określisz orientacji, obiekty będą tworzone z orientacją komponentu fabryki kolekcji.[properties]
id
-table
używana przy tworzeniu obiektów gry. Poniżej opisano jak skonstruować taką tabelę.[scale]
number
) (większa od 0), która określa jednolitą skalę wzdłuż wszystkich osi. Możesz też podać wektor (vector3
), gdzie każdy komponent będzie odpowiadał skali wzdłuż danej osi.Funkcja collectionfactory.create()
zwraca tabelę z identyfikatorami utworzonych obiektów gry. Klucze tabeli mapują hashe kolekcji do lokalnych identyfikatorów każdego z obiektów:
Relacja rodzic-dziecko między “bean” a “shield” NIE jest odzwierciedlona w zwracanej tabeli. Ta relacja istnieje jedynie w grafie sceny w trakcie działania programu, co określa jak obiekty są ustawione w stosunku do siebie. Przypisywanie rodzica nigdy nie zmienia identyfikatora obiektu.
local bean_ids = collectionfactory.create("#bean_factory")
go.set_scale(0.5, bean_ids[hash("/bean")])
pprint(bean_ids)
-- DEBUG:SCRIPT:
-- {
-- hash: [/shield] = hash: [/collection0/shield], -- <1>
-- hash: [/bean] = hash: [/collection0/bean],
-- }
/collection[N]/
, gdzie [N]
jest licznikiem dodanym do ID, żeby zidentyfikować obiekt w sposób unikalny dla każdej instancji:Podczas tworzenia kolekcji, możesz przekazać właściwości do każdego obiektu gry konstruując tabelę, gdzie klucze odpowiadają identyfikatorom obiektów, a wartości są tabelami z właściwościami (scrip properties) dla danych obiektów.
local props = {}
props[hash("/bean")] = { shield = false }
local ids = collectionfactory.create("#bean_factory", nil, nil, props)
Załóżmy, że obiekt “bean” w kolekcji “bean.collection” ma właściwość “shield”. Instrukcja do właściwości skryptów zawiera więcej szczegółów na ten temat.
-- bean/controller.script
go.property("shield", true)
function init(self)
if not self.shield then
go.delete("shield")
end
end
Zaznaczając właściwość Load Dynamically fabryki kolekcji, silnik odłoży wczytywanie zasobów danej kolekcji aż do momentu rozpoczęcia tworzenia.
Z odznaczoną opcją, silnik wczyta prototypy zasobów kolekcji w momencie wczytywania komponentu fabryki kolekcji, więc będzie można je utworzyć w świecie gry natychmiastowo.
Z zaznaczoną opcją, możesz użyć fabryki na dwa sposoby:
collectionfactory.create()
kiedy chcesz utworzyć obiekty kolekcji. Funkcja wczyta wszystkie zasoby potrzebe do utworzenia obiektów synchronicznie (co może spowodować zwieszenie programu w zależności od wielkości zasobów), a następnie utworzy obiekty z danymi zasobami.
function init(self)
-- Żadne zasoby fabryki nie są załadowane kiedy kolekcja rodzic
-- zawierająca daną fabrykę kolekcji jest utworzona.
-- Wywołanie create spowoduje wczytanie zasobów synchronicznie.
self.go_ids = collecionfactory.create("#collectionfactory")
end
function final(self)
-- Usuwanie obiektów gry. Zwolni to zasoby.
-- W tym przypadku obiekty są usuwane, ponieważ
-- fabryka kolekcji nie ma żadnych referencji.
go.delete(self.go_ids)
-- Wywołanie unload nie zrobi nic, ponieważ
-- fabryka kolekcji nie ma żadnych referencji.
collectionfactory.unload("#factory")
end
collectionfactory.load()
, żeby jawnie załadować zasoby asynchronicznie. Kiedy zasoby będą gotowe, skrypt, w którym wywołano load() otrzyma callback.
--callback, który zostanie wywołany po wczytaniu zasobów:
function load_complete(self, url, result)
-- Wczytywanie zakończone, zasoby są gotowe do utworzenia
self.go_ids = collectionfactory.create(url)
end
function init(self)
-- Żadne zasoby nie są wczytywane przy utworzeniu kolekcji
-- która jest rodzicem komponentu fabryki kolekcji.
-- Zasoby są wczytywane po wywołaniu load():
collectionfactory.load("#factory", load_complete)
end
function final(self)
-- Usuwanie obiektu gry. Zasoby są zwalniane.
-- W tym przypadku zasoby nie są usuwane, ponieważ
-- fabryka kolekcji nadal posiada do nich referencję.
go.delete(self.go_ids)
-- Wywołanie unload zwolni zasoby utrzymywane przez farbykę i usunie je
collectionfactory.unload("#factory")
end
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB