Autor Wątek: C# - Lista wolnych obiektów  (Przeczytany 2121 razy)

Offline Rakieta

  • Użytkownik

# Sierpień 29, 2015, 11:17:40
Witajcie.

Nie mogę sobie poradzić z tym problemem, przejdę od razu do sedna, bo piszę ten post chyba 10 raz i do tej pory nie opublikowałem. Chcę ograniczyć pętle do minimum. Chciałbym uzyskać listę wolnych obiektów z możliwością losowego sortowania. Powinny być dostępne z poziomu ID: ID -> Wartość

1. List: Odpada, musiałbym przechowywać wszystkie obiekty, by były dla mnie dostępne po ID - Indexie - zgodnym z ID obiektu.

2. Dictionary: Odpada - segregacja, która nie istnieje. Gra dodaje obiekty na ogół na początek 'listy', co skutecznie obniża frajdę z gry. Próbowałem stworzyć dodatkową listę, która je posortuje - ale to kolejna pętla, a nawet dwie i tak nie da się grać (każdy spawn to jakieś 200 ms zawiechy).

3. Obiekty: Jeszcze nie próbowałem. Nie sądzę, by udało mi się stworzyć do nich Dodawanie i Usuwanie. I nim znów zacznę pisać skrypt od nowa muszę się Was poradzić.

Macie jakiś pomysł?

Działanie skryptu:
Jeśli minie odpowiednia ilość czasu, wywołanie spawnu
Rozpoczęcie spawnu
-> Pobranie listy wolnych slotów (możliwe jak najmniejszej)
-> Przeszukanie pętlą w celu znalezienia odpowiedniego (jak widać pętla jest tak czy siak, więcej pętli zmienia rozgrywkę w ruiny)
-> Zrzucenie obiektu w znaleziony

EDIT:

W tym momencie wpadłem jeszcze na pomysł, by spawnem zarządzały same sloty, a nie główny skrypt gry, na zasadzie kto pierwszy ten lepszy. Ale to chyba nie przejdzie.
« Ostatnia zmiana: Sierpień 29, 2015, 11:19:58 wysłana przez Rakieta »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline koirat

  • Użytkownik

# Sierpień 29, 2015, 11:52:53
Twój post jest nadal niezrozumiały, nawet po 10-tym razie.

Jeśli dobrze rozumiem o co ci chodzi to chcesz uzyskać listę indeksów nie zawierających żadnego obiektu.
I z tej listy chcesz pobrać losowy index. Dodatkowo nie chcesz iterować po całej tablicy w której są obiekty oraz elementy puste ?

W takim razie powinieneś mieć dwie tablice, jedna zawierająca obiekty oraz elementy puste. Druga zawierająca index-y elementów pustych.

Offline timus

  • Użytkownik

# Sierpień 29, 2015, 14:05:14
  • Przerób sobie kod Dictionary z biblioteki mono, aby spełniał twoje wymagania, lub napisz cała implementacje od zera.
  • Zrób sobie dodatkowe watki z workerami, wtedy zamienisz 200ms zawiechy gry na 200ms oczekiwania na wynik.

Offline Meic

  • Użytkownik

  • +2
# Sierpień 29, 2015, 14:30:14
każdy spawn to jakieś 200 ms zawiechy

Nie wiem co wyczyniasz w swoim kodzie ale jeśli operacje na kolekcji zajmują 200ms to są bez wątpienia skopane przez Ciebie (no chyba, że masz w niej setki tysięcy obiektów).

Tak jak pisał koirat, ciężko zrozumieć o co Ci w ogóle chodzi (coś w stylu wzorca "Object pool"?). A co do samego wybierania, to odnoszę wrażenie, że usiłujesz zrobić coś prostego, niepotrzebnie to komplikując. Niestety jak wspomniałem ciężko komuś pomóc jak się nie rozumie w czym konkretnie tkwi problem.

Offline Rakieta

  • Użytkownik

# Sierpień 29, 2015, 14:57:59
@koirat - własnie przez to, że 10 razy go pisałem, pewnie wielu rzeczy nie uwzględniłem i nawet już nie pamiętam jak to powineinem dokładnie wytłumaczyć.

Wyobraźcie sobie zwykłą tabelę mysql:

- Dajemy do niej pierwszą kolumnę int ID. ID musi zgadzać się z ID platformy (patrz mój screen na wsoc: http://forum.warsztat.gd/index.php?action=dlattach;topic=30302.0;attach=5165;image), powiedzmy, że drugiej kolumny nie ma, co by nie mieszać.

- Dodajemy obiekty, które są wolne:
- ID 10,
- ID 21,
- ID 25,
- ID 26

Teraz dwie możliwości:
a) Obiekty zawsze powinny dodawać się na koniec bazy, jak w LIST, (najlepsza opcja)
b) Wybieramy obiekty ustawiając je losowo (ale tu dochodzi dodatkowa pętla, co spowalnia działanie gry)

Chcemy aby elementy można było dodawać i usuwać, przechowywać dzieki temu tylko ID pustych obietków.

@Meic - jest duża szansa, że masz rację, ale to tylko kurczę 70 obiektów. Podsyłam kod w wersji bez checkerów, który już w tym momencie jest niewydajny. Może popełniam błędy, których nawet nie jestem świadom. Mam taką nadzieję, chciałbym. Ale te "pauzy" znam z innej gry na Unity, która zwie się Rust i boję się, nie chcę by okazało się, że kod jest w porządku.

int Get_Empty_Slot (int Block_Type) {

// DEBUG
Debug.Log ("Dictionary size BEFORE: "+Empty_Slots_Dict.Count);

int slot = 0;
int slot2 = 0;
string type = "type";

int i = 0;

foreach (int dKey in Empty_Slots_Dict.Keys) {

i++;
slot = dKey;
if (slot == 0) { slot = 1; }
///////////////////////////////////////
Debug.Log ("TRY #: "+i);
Debug.Log(dKey);
}

Debug.Log ("END of function ------------------------------");
return slot2;
}

Funkcja jest wywoływana tylko raz z Update, natomiast Empty_Slots_Dict to Dictionary z 70 elementami (mapa jest pusta gdy startujemy grę, 70 wolnych slotów). Skrypt ma za zadanie wylać wszystkie elementy w konsolę, dlatego nie ma nigdzie "Break" - to taka sama sytuacja gdybyśmy mieli 70 elementów nie pasujących do wymogów zrzucenia nowego obiektu, pętla będzie musiała sprawdzić wszystkie sloty i dopiero na końcu poddać się i zrzucić obiekt.

To wszystko działa, ale dopóki pętla się nie skończy będzie pauza. To chyba normalne. No ale gdybym chciał, by tak to wyglądało, to bym nie pisał tego wątku :P

EDIT:
A - jeszcze poprawka. 200 ms (czy 70) podczas Debugowania. Wersja wyeksportowana zatrzymuje się dosłownie na ułamek sekundy, ale jest to widoczne tak czy siak.
« Ostatnia zmiana: Sierpień 29, 2015, 15:04:10 wysłana przez Rakieta »

Offline Meic

  • Użytkownik

  • +2
# Sierpień 29, 2015, 15:15:09
Co do lagów, to prawdopodobnie jest to wina Debug.Log (szczególnie biorąc pod uwagę, że klatka jest opóźniana do momentu wypisania 70+ linii - przy czym ta uwaga dotyczy trybu debug, nie orientuję się co dokładnie robi unity z Log w release).

Co do kodu, to imo on nic (!) nie robi - a przynajmniej ten, który podałeś jest (za przeproszeniem) bezużyteczny*. Powiedz, co dokładnie chcesz osiągnąć. To jest coś w stylu pobierania wolnych bloków do budowania (jak w minecrafcie)?

Btw. w Unity 5 w wersji free można sobie zobaczyć co się dzieje w programie i co ile zajmuje, przy pomocy profilera.

Edit:
*Wybacz, nie doczytałem, on ma nic nie robic ;P.
« Ostatnia zmiana: Sierpień 29, 2015, 15:22:50 wysłana przez Meic »

Offline Rakieta

  • Użytkownik

# Sierpień 29, 2015, 15:23:44
No tak. Zabawne. Stworzyłem kod, który miał właśnie wypisywać linie w logu, a tym samym tworzyłem problem z "lagami". Geniusz. Proszę się nie śmiać.

Po usunięciu linii z Debugiem nawet z pętlą sortującą Dictionary wszystko chodzi gładko.

No dobra. Dziękuję wam za poświęcony czas, będę pamiętał o tym Logu :)