From 44846f9702736af1084276beda2f1fb56f6bdca8 Mon Sep 17 00:00:00 2001 From: Pierre Etchemaite Date: Sat, 18 Apr 2020 13:45:45 +0200 Subject: [PATCH 1/2] Do not call Resources.UnloadUnusedAssets() more than once every 3 mins Daggerfall Unity needs to explicitly call Resources.UnloadUnusedAssets() because it barely uses SceneManager.LoadScene() which is the way games usually indirectly call it. This is currently done in two places, including while closing UI windows, a path taken often enough during normal gameplay to prevent unused assets to pile up too much. However this can be a lengthy operation that blocks the whole environment as it calls GC.Collect() internally, and can make sound skip which can be pretty annoying once you noticed it (issue #1539). This patch makes sure the call to UnloadUnusedAssets() does not happen more than once every 3 minutes, a tradeoff sufficient to make that issue much less noticeable, yet should prevent unused assets to stay around forever. It should be noted that, for optimal efficiency, all code using Resources.UnloadUnusedAssets() (say mods) should call either ThrottledUnloadUnusedAssets() or ForcedUnloadUnusedAssets() instead to prevent unnecessary collections. --- .../Game/UserInterface/UserInterfaceWindow.cs | 2 +- Assets/Scripts/Internal/DaggerfallGC.cs | 40 +++++++++++++++++++ Assets/Scripts/Internal/DaggerfallGC.cs.meta | 11 +++++ Assets/Scripts/Terrain/StreamingWorld.cs | 2 +- 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 Assets/Scripts/Internal/DaggerfallGC.cs create mode 100644 Assets/Scripts/Internal/DaggerfallGC.cs.meta diff --git a/Assets/Scripts/Game/UserInterface/UserInterfaceWindow.cs b/Assets/Scripts/Game/UserInterface/UserInterfaceWindow.cs index cb09507462..834992a586 100644 --- a/Assets/Scripts/Game/UserInterface/UserInterfaceWindow.cs +++ b/Assets/Scripts/Game/UserInterface/UserInterfaceWindow.cs @@ -128,7 +128,7 @@ public void CloseWindow() { uiManager.PopWindow(); RaiseOnCloseHandler(); - Resources.UnloadUnusedAssets(); + DaggerfallGC.ThrottledUnloadUnusedAssets(); } public void PopWindow() diff --git a/Assets/Scripts/Internal/DaggerfallGC.cs b/Assets/Scripts/Internal/DaggerfallGC.cs new file mode 100644 index 0000000000..caf440541c --- /dev/null +++ b/Assets/Scripts/Internal/DaggerfallGC.cs @@ -0,0 +1,40 @@ +// Project: Daggerfall Tools For Unity +// Copyright: Copyright (C) 2009-2020 Daggerfall Workshop +// Web Site: http://www.dfworkshop.net +// License: MIT License (http://www.opensource.org/licenses/mit-license.php) +// Source Code: https://github.com/Interkarma/daggerfall-unity +// Original Author: Pango (petchema@concept-micro.com) +// Contributors: +// +// Notes: +// + +using System; +using UnityEngine; + +namespace DaggerfallWorkshop +{ + public class DaggerfallGC + { + // Min time between two unused assets collections + private const float uuaThrottleDelay = 180f; + + private static float uuaTimer = Time.realtimeSinceStartup; + + private DaggerfallGC() + { + } + + public static void ThrottledUnloadUnusedAssets() + { + if (Time.realtimeSinceStartup >= uuaTimer) + ForcedUnloadUnusedAssets(); + } + + public static void ForcedUnloadUnusedAssets() + { + Resources.UnloadUnusedAssets(); + uuaTimer = Time.realtimeSinceStartup + uuaThrottleDelay; + } + } +} diff --git a/Assets/Scripts/Internal/DaggerfallGC.cs.meta b/Assets/Scripts/Internal/DaggerfallGC.cs.meta new file mode 100644 index 0000000000..6c1fab4ddc --- /dev/null +++ b/Assets/Scripts/Internal/DaggerfallGC.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70ef55862ca84432ba15b526522f7ae3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Terrain/StreamingWorld.cs b/Assets/Scripts/Terrain/StreamingWorld.cs index 49cd7fd72b..411307f4cb 100644 --- a/Assets/Scripts/Terrain/StreamingWorld.cs +++ b/Assets/Scripts/Terrain/StreamingWorld.cs @@ -659,7 +659,7 @@ private IEnumerator UpdateTerrains() if (init) { DaggerfallUnity.Instance.MaterialReader.PruneCache(); - Resources.UnloadUnusedAssets(); + DaggerfallGC.ThrottledUnloadUnusedAssets(); } // Set terrain neighbours From 8e9d49959d90293c1ec47f31883425abfc40cbe8 Mon Sep 17 00:00:00 2001 From: Pierre Etchemaite Date: Sun, 19 Apr 2020 05:56:23 +0200 Subject: [PATCH 2/2] use static class --- Assets/Scripts/Internal/DaggerfallGC.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Assets/Scripts/Internal/DaggerfallGC.cs b/Assets/Scripts/Internal/DaggerfallGC.cs index caf440541c..5f2cf5951b 100644 --- a/Assets/Scripts/Internal/DaggerfallGC.cs +++ b/Assets/Scripts/Internal/DaggerfallGC.cs @@ -14,17 +14,13 @@ namespace DaggerfallWorkshop { - public class DaggerfallGC + public static class DaggerfallGC { // Min time between two unused assets collections private const float uuaThrottleDelay = 180f; private static float uuaTimer = Time.realtimeSinceStartup; - private DaggerfallGC() - { - } - public static void ThrottledUnloadUnusedAssets() { if (Time.realtimeSinceStartup >= uuaTimer)