Jump to content

Jak optymalizować mody na S.T.A.L.K.E.R.


Recommended Posts

W temacie znajdują się porady dla twórców modów, jak optymalizować skrypty stalkera dla dowolnej części gry. Ręcznie.
Wszelkie informacje są wiarygodne, sprawdzone przez twórcę tematu na ap-pro (liner), kiedy robił CoP optimized.

 

 

GŁÓWNE:

Spoiler

PAMIĘĆ:

Spoiler
  1. Pamięć niewątpliwie odgrywa dużą rolę. Zwłaszcza na wysokich ustawieniach graficznych. Ale w skryptach są funkcje, które nie są używane. Należy je po prostu usunąć.
  2. _G. Obszar z globalą widocznością. Zwykle do tego skryptu dodawane są funkcje, które są używane wszędzie.
    Ale mogą istnieć funkcje, które są używane tylko w jednym skrypcie, na przykład utils. I już. Ta sama funkcja jest widoczna w każdym skrypcie, ponieważ jest umieszczona w _G. Po co? Po co wstawiać do _G, jeśli ta funkcja jest używana tylko w jednym pliku? Funkcję należy przenieść do tego pliku, na przykład do utils. To samo musisz zrobić ze zmiennymi globalnymi.
  3. Obiekty lokalne i globalne. Różne rzeczy. Niektóre skrypty zawierają zmienne globalne, takie jak skrypt modules. Inne skrypty podczas swojej pracy mogą odwoływać się do jakiejś globalnej zmiennej z modules. Ale wszędzie, ale... w skrypcie tworzona jest zmienna globalna, ale jest ona używana tylko w tym skrypcie. Oznacza to, że w rzeczywistości jest używana jako lokalna, ale jest globalna. Dostęp do zmiennych globalnych jest nieco wolniejszy niż dostęp do zmiennych lokalnych. W takim przypadku konieczne jest, aby wszystkie takie zmienne globalne, które są w tym skrypcie, były lokalne.
  4. Funkcje i lokalne funkcje (local function ()). Pierwsza to te funkcje, które można wywoływać z innych skryptów, czyli funkcje globalne. Absolutnie każdy skrypt ma funkcję globalną i to jest w porządku. Ale są takie funkcje, które podobnie jak zmienne (tautologia) są używane tylko w tym pliku, ale są zadeklarowane jako globalne. Dostęp do zmiennych globalnych jest nieco wolniejszy niż dostęp do zmiennych lokalnych. Dotyczy to również funkcji, więc te funkcje muszą być zadeklarowane jako lokalne.
  5. Każdy znak w łańcuchu to 1 bajt. Na przykład pusty łańcuch "" waży 1 bajt (na końcu zawsze jest znak końca linii, \0). Nie zaleca się tworzenia długich nazw dla czegoś (ich nazwy to ciągi znaków), ponieważ zajmie to dużo pamięci, zwłaszcza jeśli jest to jakaś klasa, która jest używana przez kilka obiektów.

 

ZBĘDNE DZIAŁANIA:

Spoiler
  1. Pętla dla i = 0, 65535 do. Jest to pętla, która iteruje po wszystkich obiektach odradzania w grze. Stosowana w wielu miejscach.
    Pierwsza uwaga, to koniec pętli - iteracja nr 65535. Jest to maksymalna dozwolona liczba typu unsigned short (int) i jest to maksimum spawn-obiektów, jakie może być w grze. W grze domyślnie obiekt z ID 65535 to "Invalid". Nie można od niego uzyskać żadnych danych. To tylko sygnalizuje, że nie może być dalszych obiektów, ten jest ostatni. Dlatego konieczne jest wykonanie nie 65535 iteracji, ale 65534.
    Druga uwaga, identyfikator, od którego rozpoczyna się iteracja, wynosi zero. Zero jest zawsze ID gracza, absolutnie zawsze, ponieważ to gracz jest tworzony i wczytywany jako pierwszy na poziomie. W niektórych przypadkach np. wyszukiwanie i usuwanie niektórych przedmiotów za pomocą takiej pętli. W takim przypadku, aktor nie jest przedmiotem, więc w ogóle go nie potrzebujemy i iterację należy rozpoczynać od jedynki. Tutaj jest całkiem prawdopodobne, że ID 1 jest przedmiotem.
  2. Bolączka stalkerskich skryptów polega na przekazaniu argumentu jako obiektu, z którego zostanie wzięty tylko jeden parametr. Po co przekazywać cały obiekt, jeśli używany jest tylko jeden z jego parametrów, można przekazać ten sam parametr.
    Przykładowy kod:
    Spoiler
    --JAK NIE NALEŻY ROBIĆ!!!
    local function IsActor(obj)
    	return obj:id() == 0
    end
    --załóżmy, że wzięliśmy skądś NPC, CGameObject* (dokładnie wskaźnik na niego!)
    print(IsActor(who)) --efekt nie jest znany
    
    --JAK NALEŻY ROBIĆ
    local function IsActor(obj_id)
    	return obj_id == 0
    end
    --załóżmy, że wzięliśmy skądś NPC, CGameObject* (dokładnie wskaźnik na niego!)
    print(IsActor(who:id())) --efekt nie jest znany
  3. Usuń wszystkie funkcje, które zostały wywołane, ale ostatecznie nic nie robią. Na przykład funkcja printf i jej analogie (print_table, store_table). Są to niepotrzebne działania, które marnują zasoby komputera w wyniku niczego. Każdy program zdecydowanie wymaga testowania i debugowania; printf jest tą funkcją.
    Ale chodzi o to, że po prostu nie jest potrzebna. Jeśli dostępna jest silnikowa funkcja log, to printf dodaje garść informacji do loga. Która modmakerowi, z pewnością, nie jest potrzebna. Jeśli twórca modów musi coś zdebugować, naprawić jakiś błąd, to wtedy ON SAM może umieścić dane wyjściowe we właściwym miejscu w logu, a następnie zakomentować. Czasami ludzie zapominają to zrobić, w wyniku czego w logu moda, który został udostępniony, znajduje się wiele niepotrzebnych informacji. A w niektórych przypadkach to tylko utrudnia znalezienie przyczyny wylotu.
  4. Tworzenie tablicy i po jej utworzeniu natychmiastowe wprowadzanie danych. Wygląda ładnie, ale bardzo spowalnia kod. Takie tablice nie powinny być w ogóle dozwolone. Lua ułatwia zapisywanie wszystkich informacji w tablicy na etapie jej tworzenia niż po jej utworzeniu.
    --TAK BYĆ NIE POWINNO!!!!
    local t = {}
    t[1] = false
    t[2] = true
    t[3] = false
    
    --TAK POWINNO BYĆ. Odpowiednik poprzedniego przykładu, ale szybszy.
    local t =
    {
    	[1] = false,
      	[2] = true,
      	[3] = false
    }
  5. Ciągłe sprawdzanie nierówności wartości. To jest zbędne! W rzeczywistości nic się nie zmieni, jeśli jest taki kod:
    --Powiedzmy, że ta funkcja jest wywoływana z bind_stalker.actor_binder:update(dt)
    local lst = 10
    function update(dt)
    	--zjada FPS
    	if dt ~= lst then
    		lst = dt
    	end
    end
    można przekonwertować na kod podobny do
    --Powiedzmy, że ta funkcja jest wywoływana z bind_stalker.actor_binder:update(dt)
    local lst = 10
    function update(dt)
    	--około 3,5-krotne przyspieszenie poprzez usunięcie JEDNEJ nierówności
    	lst = dt
    end
    który będzie szybszy.

 

O LINIJKACH:

Spoiler
  1. Konkatenacja łańcuchów. W Lua możesz połączyć liczbę z ciągiem znaków bez użycia funkcji tostring. Kod, który działa szybciej bez użycia tostring.
    local c = "math"..tostring(7) --wolniej
    --Równoważne
    local c = "math"..7 --szybciej
  2. Matematyczne operacje z ciągami znaków. Tak, to prawda, ale jest jedna rzecz:
    --TAKI KOD BĘDZIE DZIAŁAĆ
    local c = "70"
    c = c - 5
    c = c + 2
    c = c * 2
    c = c / 4
    print(c) --wynik 33.5
    
    --TAKI KOD NIE BĘDZIE DZIAŁAĆ
    local c = "70f"
    c = c - 5 --wyświetli błąd
    c = c + 2
    c = c * 2
    c = c / 4
    print(c)
    --[[
    lua: main.lua:2: attempt to perform arithmetic on a string value (local 'c')
    stack traceback:
    	main.lua:2: in main chunk
    	[C]: in ?
    ]]
    Jeśli ciąg znaków zawiera znaki, które nie są zdefiniowane jako liczba (na przykład litery), wystąpi błąd w kodzie. Wtedy linia powinna zawierać tylko liczby (kropka, minus).
    Działa również z systemem szesnastkowym (0xff).
    Nawet jeśli w łańcuchu jest liczba całkowita, to w wyniku pracy z dowolnymi operatorami matematycznymi wbudowanymi w Lua, zostanie ona zamieniona na float (liczbę zmiennoprzecinkową).

 

 

 

INNE:

Spoiler

Małe rzeczy, które również dają wzrost FPS.

  1. Staraj się unikać dzielenia. Tak, dokładnie. Proces dzielenia jest nieco wolniejszy niż proces mnożenia. Na przykład:
    Przykładowy kod:
    Spoiler
    local test = 150
    test = test * 0.1 --W danym przypadku równoważne test = test / 10
    print(test) --Wyświetli 15

    Lista zamienników:
    /10 = * 0,1
    /100 = * 0,01
    /1000 = * 0,001 itd.
    /2 = * 0,5
    /4 = * 0,25
    /5 = * 0,2
    /8 = * 0,125


     
  2. Nie używaj potęgowania. W ogóle. Na przykład, jeśli liczba zostanie pomnożona przez samą siebie dwukrotnie, będzie to półtora raza szybsze niż podnoszenie do kwadratu.
  3. Usuń dodatkowe argumenty z funkcji, które nie są używane, ale są przekazywane. Na przykład:
    local function test(param) -- param nie jest wykorzystywany!!! ale jest przekazywany
      print("Test?")
    end
    test(true)
    W takim przypadku musisz usunąć argument param w funkcji i usunąć go podczas przekazywania. Po co znowu przekazywać "nic”?
  4. Usuń puste bloki kodu. Nawet w oryginalnych skryptach one są.
    function test()
       return math.random(3)
    end
    --PUSTY BLOK KODU!!!
    if test() == 2 then
      --print(true)
    end
    
    --TRZEBA ZAMIENIĆ NA
    --if test() == 2 then
      --print(true)
    --end
    
    --LUB CAŁKIEM USUNĄĆ!
  5. Jeśli nagle jakiś plik nie będzie używany po wykonaniu pewnych czynności, lepiej usunąć go z pamięci, ponieważ nie przyda się w przyszłości. Możesz to zrobić w ten sposób:
    _G["nazwa skryptu"] = nil
    --lub (równoważne)
    _G.nazwa_skryptu = nil
    Lub, jeśli jest podobna sytuacja z funkcją (na przykład callback na starcie gry)
    nazwa_skryptu["nazwa_funkcji"] = nil
    --lub (równoważne)
    nazwa_skryptu.nazwa_funkcji = nil
  6. Mnożenie, dzielenie, dodawanie i odejmowanie wszystkich znanych liczb
    local a = 12*12
    --Zrobić tak. Pomnożyć znane liczby
    local a = 144

 

 

ŹRÓDŁO:

https://ap-pro.ru/forums/topic/3557-kak-optimizirovat-mody-na-stalker/

 

Link to comment
Share on other sites

  • Wojownik changed the title to Jak optymalizować mody na S.T.A.L.K.E.R.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.

Comunity