Long loading time

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
thehazard
Posts: 27
Joined: Sun Jul 23, 2017 9:56 am

Long loading time

Post by thehazard »

Hi, I have many actor portraits in my dialogue database. The total size is around 500MB of png images for all my characters. This is making the load time rather long. Without the dialogue manager, the scene would load almost instantly, but once I added the dialogue manager to the scene, it would take one to two minutes to load. Is there any way to reduce the loading time?
User avatar
Tony Li
Posts: 22055
Joined: Thu Jul 18, 2013 1:27 pm

Re: Long loading time

Post by Tony Li »

Hi,

Can you make the images smaller? For example, if your UI Image component is 64x64 pixels and your source portrait images are 128x128, they're 4x bigger than need to be.

Ultimately, Unity needs to load those images one way or another. Here a few ideas to make it less noticeable.

1. Start your game with a splash scene. Additively load the start scene into it. Put your Dialogue Manager in the start scene. The player will be looking at the splash scene while Unity loads the images into memory.

2. If you only use certain actors in specific scenes, split off those actors and their content into a separate dialogue database. You'll need to use the Extra Databases component or call DialogueManager.AddDatabase() to load the extra database(s) when the player enters those scenes.

3. This one's more complicated: Don't assign portrait images in the dialogue database. Instead, put them in assetbundles. Before using an actor, load the assetbundle containing its portraits and call DialogueManager.RegisterAssetBundle() to tell the Dialogue System about it. Then use the SetPortrait() sequencer command to set portrait images instead of [pic=#] markup tags.

If you need more details on any of these ideas, let me know.
thehazard
Posts: 27
Joined: Sun Jul 23, 2017 9:56 am

Re: Long loading time

Post by thehazard »

Hi Tony, thank you for the detailed reply. The artwork is a very important aspect of my game and I'm willing to sacrifice in loading time in order to maintain the image quality. I have a splash screen while it's loading, but I could make it longer to hide the loading. The option 3 you provided sounds great. Is there a tutorial or sample scene where this is used? I could see it solve many of my problems because I'm still adding more artwork into the game and the dialogue portraits size keeps getting bigger. I'll do more tests with the Extra Databases component as well and see if it helps.
User avatar
Tony Li
Posts: 22055
Joined: Thu Jul 18, 2013 1:27 pm

Re: Long loading time

Post by Tony Li »

Hi,

If you're using multiple databases, remember to keep IDs unique. More info here: Working with Multiple Databases.

It occurred to me that another possible solution is to assign the portraits manually in code at runtime. This may be simpler than using assetbundles.

For example, say an actor named "Bob" isn't used until a scene named "Docks". When you create your database, leave Bob's portraits unassigned. Add a script like this to the Docks scene:
AssignActorPortraits.cs

Code: Select all

using UnityEngine;
using PixelCrushers.DialogueSystem;
public class AssignActorPortraits : MonoBehaviour
{
    [ActorPopup(true)]
    public string actorName;
    
    public Texture2D mainPortrait;
    public List<Texture2D> alternatePortraits;
    
    private void Start()
    {
        var actor = DialogueManager.masterDatabase.GetActor(actorName);
        if (actor == null) return;
        actor.portrait = mainPortrait;
        actor.alternatePortraits.Clear();
        actor.alternatePortraits.AddRange(alternatePortraits);
    }
}
In the Inspector, set the script's actorName to Bob, and assign the portrait images.
To use the idea above, you must tick the Dialogue Manager's Other Settings > Instantiate Database. This gives you a read/write version of the dialogue database that you can make changes to.

If you still want to use assetbundles, I'll include some info below.
AssetBundle Info
Using SetPortrait() with assetbundles isn't a cure-all, but it can help a lot, at the cost of some complexity to set it up. There isn't a sample scene or tutorial specifically for it. But I can help you get started.

First, you'll need to create an assetbundle. (Detailed info: Guide to AssetBundles.) This is actually the most complex step. Once you've prepared an assetbundle, the rest is pretty simple.

Before accessing a portrait image, make sure the assetbundle is loaded:

Code: Select all

var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
if (myLoadedAssetBundle == null)
{
    Debug.LogError("Failed to load AssetBundle!");
}
else
{
    DialogueManager.RegisterAssetBundle(myLoadedAssetBundle);
}
In the actor's first line, or in a sequence before the conversation, use SetPortrait():

Code: Select all

DialogueManager.PlaySequence("SetPortrait(Bob, Bob_Happy)");
When you no longer need the portrait, register and unload the assetbundle:

Code: Select all

DialogueManager.UnregisterAssetBundle(myLoadedAssetBundle);
myLoadedAssetBundle.Unload(false);
Post Reply