2014-06-06 6 views
5

Naprawdę potrzebuję pomocy! Nie mogę zrozumieć, jak pracować z prefabrykatami i rozładowywaniem.Unity3d Praca z pamięcią: załaduj i wyładuj prefabrykaty

Mam następną sytuację.

Uruchamiam moją aplikację na iPadzie z Xcode. Wersja Unity 4.3.1 Pro. Watch korzystania z pamięci: Xcode debugowania Navigator Xcode Instruments Unity Profiler

zrobić kolejne kroki:

0) Unity rozpoczyna się od pustej sceny.

Używana pamięć Xcode Debug Navigator: 11 mb Instruments: 26.4 mb Unity Profiler: Używany sumie 13,2 zastrzeżone sumie 13,7

1) szkieletowe obciążenia z folderu Resources

prefab = Resources.Load("Room1"); 

Używana pamięć Xcode Debug Navigator: 30.8 mb Instruments: 49.54 mb Unity Profiler: używany łącznie 19,8 zastrzeżone łącznie 20,4

2) Utworzenie wystąpienia prefabrykatów

go = (GameObject)Instantiate(prefab); 
go.name = "Room1"; 

Xcode Debug Navigator: 31.2 mb Instruments: 50 MB Unity Profiler: Używany sumie 20 Reserved sumie 20,7

3) Zniszcz wszystkie obiekty na scenie - pamięć nie zmieniła

Transform[] tr = FindObjectsOfType<Transform>(); 
for (int i = 0; i < tr.Length; i++) 
{ 
    GameObject goo = tr.gameObject; 
    if (goo.name != "Main Camera") 
    { 
     Destroy(goo); 
     goo = null; 
    } 
} 

Xcode Debug Navigator: 31.1 Instrumenty: 49.93 mb mb Unity Profiler: używane sumie 19,8 zastrzeżone sumie 20,4

4) Zadzwoń Resources.UnloadUnusedAssets(); - pamięć nie zmieniła

5) połączeń System.GC.Collect(); - pamięć nie zmieniła

6) połączeń UnloadAsset z prefabrykatów Resources.UnloadAsset(prefab); - pamięć nie zmieniła

7) Połączenie Resources.UnloadUnusedAssets(); - pamięć częściowo oczyszczone

Xcode debugowania Navigator: 21,9 mb Instruments: 40,79 mb Unity Profiler: używany sumie 13,2 zastrzeżone sumie 13,9

w profiler widzę, że usunięte wszystkie texures, że stosowane w prefabrykatów

8) System.GC.Collect(); - pamięć nie zmieniła

9) Obciążenie pusta scena - pamięć nie zmieniła

Oto kolejny ciekawy chwila:

Kiedy aplikacja przechodzi do tła i uruchomić inną aplikację, wielkość stosowanego RAM znacznie zmniejsza się, i kiedy wzywam aplikację jedności - pamięć idzie do pierwszego rozmiaru z pustą sceną.

Mam następujące pytania:

1) Dlaczego pamięć nie czyszczone po całkowicie usunąć z prefabrykatów i UnloadUnusedAssets nazwać - widzimy go w Instruments i Xcode - ale w Profiler widzimy, że pamięć praktycznie całkowicie za darmo?

2) Czy to prawda, aby wyczyścić pamięć do rozmiaru początkowego?

3) Czy wszystkie kroki są prawidłowe, czy coś nie tak?

Można pobrać projekt testowy tutaj: http://gfile.ru/aa5on

Wielkie dzięki za odpowiedzi.

+0

* sidenote: * Spróbuj najpierw zaktualizować Unity 3D. – Raptor

Odpowiedz

7

Preambuła

To dobrze, że zdajesz sobie sprawę z użycia pamięci RAM. Ale pytanie brzmi: czy napotkaliście jakikolwiek problem z wykorzystaniem pamięci? Jeśli nie, to co robisz jest przedwczesne.

Niektóre myśli

Oto kilka myśli do rozważenia:

  1. Ważne artykuł w brzmieniu: http://docs.unity3d.com/Manual/MobileProfiling.html
  2. Istnieje Unity pamięci i pamięć mono. Mono nigdy nie odda pamięci do OS:

    Po przydzieleniu określonej ilości pamięci jest zarezerwowana dla mono i niedostępna dla systemu operacyjnego. Nawet gdy go zwolnisz, stanie się on dostępny wewnętrznie tylko dla Mono, a nie dla systemu operacyjnego. Wartość pamięci sterty w programie Profiler wzrośnie, nigdy się nie zmniejszy.

  3. Prefabrykaty i obiekty gier to po prostu cała masa linków, więc nie mają tak dużego śladu pamięci, jak zasoby.
  4. Object.Destroydoesn't destroy object instantly:

    Rzeczywisty przedmiot zniszczenie jest zawsze opóźniony aż po pętli prądowej aktualizacji, ale zawsze będą wykonane przed renderowania.

  5. Resources.UnloadUnusedAssets jest asynchroniczny. Nie rozładowuje wszystkiego od razu.
  6. Nie jest wymienione w dokumentach Unity, że Resources.UnloadAsset(Object assetToUnload) rozładuje zasoby, do których odwołuje się assetToUnload.

Wyjaśnienie

nie mogę nazwać się ekspertem w zarządzaniu pamięcią (zarówno Jedności i mono).Ale o to, jak rozumiem, co się dzieje:

  1. 1) Obciążenie prefabrykatów z folderu Resources

    Szkieletowe załadowano wszystkich zasobów przywoływanych przez nią. Zwiększono użycie pamięci. Wszystko jest teraz jasne.

  2. 2) Utwórz wystąpienie prefabrykatów

    zwiększone zużycie pamięci trochę trzymać prefabrykatów klona.

  3. 3) Zniszcz wszystkie obiekty na scenie - pamięć nie zmieniła

    Nadchodzą ciekawe rzeczy :) Faktycznie, wykorzystanie pamięci, która nastąpiła zgodnie profilera Jedności: to jest takie samo jak to było wcześniej instancji z prefabrykatów. Wygląda więc na to, że Unity wydało coś, co było bezpośrednio związane z instancją prefabrykowaną. Ale, jak to jest powiedziane, mono nie zwróci pamięci do OS (i nawet nie ma na to czasu, nawet gdyby tak było).

  4. 4) Wywoływanie zasobów.UnloadUnusedAssets(); - pamięć nie zmieniła

    Resources.UnloadUnusedAssets nie wyładować coś tutaj, ponieważ istnieją jeszcze żadne niewykorzystane aktywa: chociaż obiekty zostały oznakowane za zniszczenia, rzeczywisty wywóz śmieci nie odbyła.

  5. 5) Zadzwoń do System.GC.Collect(); - pamięć nie zmieniona.

    To dlatego, że pamięć jest zarządzana przez mono.

  6. 6) Call UnloadAsset z prefabrykatów Resources.UnloadAsset (prefabrykowany);

    Uważam, że zużycie pamięci spadło tu nieco (100 000), ale nie zauważyłeś tego. Ale, jak wspomniałem powyżej, UnloadAsset nie rozładuje zasobów, do których odwołuje się obiekt, który przekazujesz jako parametr do UnloadAsset.

  7. 7) Wywoływanie zasobów.UnloadUnusedAssets(); - pamięć częściowo oczyszczona

    W kroku 5, w którym wywołano GC.Collect(), nastąpiło inkasowanie, a teraz niektóre aktywa Unity nie mają do nich odniesienia. W ten sposób mogą zostać w końcu uwolnieni. Właśnie dlatego pamięć została uwolniona.

  8. 8) System.GC.Zebrać(); - pamięć nie zmieniła

    wyjaśniono powyżej

  9. 9) Obciążenie pustej sceny - pamięć nie zmieniła

    wszystko, co mogłoby być uwolnione zostały już uwolnione. Tak więc nie ma zmiany w użyciu pamięci.

+0

Cześć, Sergey. Wielkie dzięki za twoją odpowiedź. Mój problem z pamięcią jest następny: moja aplikacja Unity jest osadzona w natywnej aplikacji XCode jako część. Kiedy zadzwonię do aplikacji Unity po raz pierwszy z głównej aplikacji, zaczyna się, ale kiedy muszę iść do głównej aplikacji, wywołuję jedność pause(). Pamięć popularnej aplikacji zwiększa się zawsze, gdy ładuję nowe sceny lub ładuję zasoby aktywów. W rezultacie - gdy rozmiar aplikacji staje się duży - aplikacja nie działa z błędem pamięci. – madmik

+1

Rozumiem. Pierwszą rzeczą, na której należy się skupić, jest próba zmniejszenia zużycia pamięci tekstury. Czy używasz kompresji tekstur? Czy możliwe jest zmniejszenie niektórych tekstur bez utraty jakości? Następnie musisz zwolnić jak najwięcej zasobów przed wstrzymaniem odtwarzacza Unity. Możesz spróbować wywołać Resource.UnloadAsset na wszystkich zasobach (głównie teksturach), które są ładowane (nigdy tego nie próbowałem, ale powinny działać), albo załadować pustą scenę "Pause" i wywołać Resources.UnloadUnusedAssets. –

0

Cóż, może potrzebuję wyświetlić problem z innej strony - wyczyścić pamięć, gdy aplikacja Unity jest wstrzymana? Może ktoś wie, jak to zrobić? Lub uruchom ponownie, gdy próbuję uruchomić wstrzymaną aplikację.