Naninovel memory leaks after end of story

The engine is not working as expected? Documentation is wrong or out of date? Let us know here!
Forum rules
We are not providing support via this forum; it's community-driven. For official support see https://naninovel.com/support/#naninovel-support
Post Reply
zoelipg
Posts: 3
Joined: 26 Jan 2021 06:46

Naninovel memory leaks after end of story

Post by zoelipg »

I originally posted in the #support discord channel but for better transparency for my co-workers or even further follow-up from them, let me cross-post and give more issue update here.

This is the code I used to switch from naninovel mode to supergame mode.

Code: Select all

        

[CommandAlias("supergame")]
public class SwitchToSupergameMode : Command
{
    [ParameterAlias("reset")] public BooleanParameter ResetState = true;

public BooleanParameter OnlyCleanUp;

public override async UniTask ExecuteAsync(CancellationToken cancellationToken = default)
{
    // 0. Save Naninovel State -- need to resume the reward screen
    if (NaninovelSaveManager.instance.AllowSave())
    {
        NaninovelSaveManager.instance.SaveStateSync();
    }

    // 1. Disable Naninovel input.
    var inputManager = Engine.GetService<IInputManager>();
    inputManager.ProcessInput = false;

    // 2. Stop script player.
    var scriptPlayer = Engine.GetService<IScriptPlayer>();
    scriptPlayer.Stop();

    // 3. Hide text printer.
    var hidePrinter = new HidePrinter();
    hidePrinter.ExecuteAsync(cancellationToken).Forget();

    // 3.5 wait for save is done then could unload assets
    // 3.6 set isreading = false
    NaninovelDriver.instance.isReading = false;

    // 4. Reset state (if required).
    var stateManager = Engine.GetService<IStateManager>();
    if (ResetState)
    {
        await stateManager.ResetStateAsync();
    }

    SpineCharacterViewController.ClearAssetCache();

    // 5. Switch cameras.
    bool inNaniTestScene = GameManager.instance.DisableAutoReadNovel;
    if (inNaniTestScene)
    {
        var advCamera = GameObject.Find("Main Camera").GetComponent<Camera>();
        advCamera.enabled = true;
        UINaninovelStartMenu.instance.Show();
    }
    else
    {
        NaninovelDriver.instance.EndStory();
    }

    var naniCamera = Engine.GetService<ICameraManager>().Camera;
    naniCamera.enabled = false;

    await Resources.UnloadUnusedAssets();
    NaninovelUtility.Log("finish Unity UnloadUnusedAssets 1");

    NaninovelUtility.Log("finish @supergame command");
}
}

In the code, I have:
1) Await-ed for all async calls
2) Called Naninovel API

Code: Select all

await stateManager.ResetStateAsync();

to ensure unload Naninovel unused resources
3) Called Unity API

Code: Select all

await Resources.UnloadUnusedAssets();

to unload unused assets as well.

But from the memory profiler, after called this @supergame command and exit from Naninovel mode to supergame mode, the background assets are still in memory, no matter how long I wait. Due to our game designn, We will frequently switch between Naninovel mode vs Supergame mode, and have a lot of different background assets in Naninovel scenes, if the past Naninovel scenes cannot release unused background assets, and per background asset texture2D size is around 6.5MB. Then it would be a lot of memory leaks!

Here's the screenshot from the Unity memory profiler.
Image
https://drive.google.com/file/d/1TnYS8M ... sp=sharing

The first few lines in the screenshot that has 422 Reference count are all Naninovel background assets. And this is the screenshot that after I exit the Naninovel mode. I understand the Texture2D will be GC by Unity, but that assumes the texture reference count is 0 right? If the texture refernece count > 0 then it will never be released by Unity. The reference count is 300400. Some are referred by Naninovel GameStateSlot, Some are Naninovel TextProvider, some are referred by Naninovel scriptable button, Naninovel choiceHandler button, etc. Really weird.

Since I noticed if I never quit the app, then the previous naninovel mode background assets will always in memory even if I am in Supergame mode. But if I quit the app in Supergame mode, those previous background assets will be gone. So I started trying to Destroy and re-init the Naninovel engine on the fly when switching back to Naninovel mode again. But the problem is after calling Engine.Destroy() next time called scriptPlayer.Play() it will have a lot of MissingReferrence Errors, like the ModifyOrthoActor will trying to get the camera from CameraManager "cache", but the destory memory seems not destroy that cache and still refer to the destroyed cameraManager.... So I switch back to fix this memory leaks issue directly..

Overall,
Do you think am I missing anything that could cause these background assets memory leaks?
Any ideas what cause this? Can you explain why the outdated background texture still has 300-400 reference count inside Naninovel Engine?
Could you repro this? If you could, will you fix it?

Many thanks!

Elringus
admin
Posts: 521
Joined: 11 May 2020 18:03

Re: Naninovel memory leaks after end of story

Post by Elringus »

Hi, Check the integration example project, where Naninovel is used as both a drop-in dialogue system and a standalone novel mode (similar to the use case you've described). In both cases, there are no memory leaks there, all the resources (including backgrounds) are released when the script finishes playback. Make sure to use the latest v1.15 from #download for testing.

Post Reply