- Home /
How to load a large text asset with minimum to no lag.
So I have these large text files that are over 1mb in size, and unity pretty much crashes when I try and load them instantly.
So I tried using IEnumerator
to load it, this got rid of the lag early on, but as the Coroutine
went on, it completely slows down the application and just crashes.
IEnumerator loadInText (TextAsset textToLoad) {
txtText.text = "";
if (selectedType == "Stories") {
var arrayString = textToLoad.text.Split ('\n');
foreach (var line in arrayString) {
txtText.text += line.ToString () + "\n";
yield return new WaitForSeconds (0.0001f);
}
}
yield return null;
}
The 0.0001f
delay is there because unity crashes without it.
This has been a huge pain to deal with, and it seems unity is having lots of trouble loading text.
Is there anyway to put this function on it's own thread of some sort so it doesn't effect the main thread? If that is possible then It would work well enough for a fix, but it would be better if the text file just loads instantly in a couple of seconds at least.
I think it maybe important to mention that I am using TextMeshPro for text, and that may take text longer to render? I am also having my TextMeshPro inside a scroll view that auto sizes depending on the TextMeshPro , I do understand those also take up processing, but they are a mandatory component and are the only ones.
I am running this application on Mobile Android and it's even slower then. I am using Unity 2018.3
Answer by andrew-lukasik · Jun 05, 2020 at 02:18 PM
using System.Threading.Tasks;
static async Task<string> ReadTextFileInBackgroundThread ( string filePath )
{
if( !System.IO.File.Exists(filePath) )
{
Debug.LogWarning($"This file path is invalid tho: '{filePath}'");
return string.Empty;
}
// we're still on unity thread here
return await Task.Run(
() =>
{
// we're on worker thread, so exciting!
return System.IO.File.ReadAllText(filePath);
}
);
// back on unity thread
}
async void Start ()
{
txtText.text = await ReadTextFileInBackgroundThread( @"c:\hentai\wishlist.txt" );
}
Alternatively:
IEnumerator LoadTextJustHowHomoSapiensWould ( TextAsset textToLoad )
{
txtText.text = textToLoad.text;
// done!
yield return null;
}
Because the rest of your code has nothing to do with loading but allocating memory for no reason.
This method I tried when I first tried the solution with IEnumerator
s. But It didn't improve anything what so ever. I will try your block of code above when I get home, as it looks promising. Thank you.
That's right, Coroutines run on Unity's main thread so this is why there is lag when reading files. You need to know that in your original code the only part that reads a file from disk is this text property here: var arrayString = textToLoad.text.Split ('\n');
That's it. The rest of the code was just adding busy work allocating garbage memory in a loop (immediately destroying/splitting original text and recreating it again).
Word of friendly warning
$$anonymous$$ulti-threading is hard^3 to both comprehend and work with. So do not go crazy with it. Keep it very local, encapsulated in dedicated methods and best to use it only where it's really needed. Otherwise your program can easily become crazy-complex (race conditions etc. can be a nightmare to fix).
Also:
most unity-specific code won't work outside main thread ( forget about accessing Components, GameObjects, etc )
System.* namespace classes works fine on other threads
crashes/errors on other threads will not appear in unity console (must be sent there manually in try/catch blocks or from direct Debug.Log calls)
Debug.Log* works fine on different threads (thanks god!)
Just a question on this. most unity-specific code won't work outside main thread (forget about accessing Components, GameObjects, etc)
Let's say I find the gameobject within the thread, using FindObjectsWithTag
and get what I need from there, like change the text, or change the value in a script. All that would still work? But using global variables in the script wont?
90% of unity methods won't work inside a worker thread and will either fail totally silently or throw you exception about being on wrong thread. FindObjectsWithTag
is among them. In other words - worker threads are totally useless in dealing with scene objects.
So I implemented this function, and confirmed everything is working, but when I load my 1mb text file, it still crashes and doesn't load the text file.
Is there a way to loop over each line in the text file, and return it in the separate thread?
Ohh I totally forgot that you're trying to display 1mb of text in single Text rendering component! This probably can crash unity because it's just too much text to display at once. Two triangles (or whatever number it is) per every character in that 1mb text... is a LOT of triangles for a single mesh to handle
yea :'D Would using Unity's old Text mesh work better? since it's lower quality? I mean I loaded a 400kb file fine in a couple of seconds, but scrolling around was laggy, so ye unity is struggling with rendering. I'm sure there are optimizations to be done in terms of rendering.
Text$$anonymous$$eshPro is best text solution so I think your task here now is to figure out how to make Text$$anonymous$$eshPro display this text that was loaded.
Idea #1: split the text file into 2 parts maybe?
Idea #2: experiment with text component display properties like
text.maxVisibleLines = 10
(it may be set too high by default for this text block)
For the Idea #1 You are referring to calling the thread 2-3 times, and it sends back 1/2 or 1/3 of the text file until it's done, That would work for the loading, but then were back to the problem where Unity and Scroll view is laggy.
For idea #2 sounds promising for solving the laggy problem when I scroll the text. I will look into changing the graphics settings for text to low, maybe that will fix the issues!
Answer by JareBear12418 · Jun 08, 2020 at 03:22 PM
I recommend this asset for an easier setup process, and threading for UI and threading for not UI, Super easy to use. https://assetstore.unity.com/packages/tools/integration/task-parallel-82257
Your answer
Follow this Question
Related Questions
How do I read unicode text file on IOS from resources folder? 1 Answer
Reading .txt file from Resources folder 1 Answer
upload text file from desktop to Resources Runtime 0 Answers
Resources.Load returns null in a build, but works in editor 2 Answers
Reading level specific file in build (from another level) 0 Answers