0

I made a prefab to be instantiated in game.

But because I wish it to be instantiated "behind the scene", which means, create all those multiple copies of prefabs "while the player is doing something else".

So I put the code generating the prefab "in another thread".

But the Unity told me that "Load can only be called from the main thread."

I tried to move the code into a coroutine, but unfortunately coroutine runs in the "main thread"!

Or maybe I should say, they don't do multiple coroutines "parallely and concurrently"!

So could somebody please be so kind and teach me what should I do!?

Much appreciated!

Codes: (In case needed, even though I don't think it would do any good)

void Start()
{
    Thread t = new Thread(Do);

    t.Start();
}

private void Do()
{
    for(int i=0;i<1000;i++)
    {
        GameObject RaceGO = (GameObject)(Resources.Load("Race"));

        RaceGO.transform.SetParent(Content);
    }
}
11
  • Its not solution but You can't access the Unity API from any outside thread but the main. As unity only run on Main tread so you have to do each and every thing in main tread like instantiation, Loading Scene, Co-routines Etc, But you can do calculation out side of main tread and then take that information back to main thread do thing what ever you want. Commented Nov 6, 2019 at 12:17
  • But there is unity job system that might help in this case. there is a lot of tutorial you check out.Like this one : youtube.com/watch?v=gibqhg0wMA0 Commented Nov 6, 2019 at 12:21
  • You can't. I guess what you are looking for is Resources.LoadAsync Commented Nov 6, 2019 at 13:20
  • @derHugo What you're trying to say is "There is no way I can instantiate multiple prefabs simultaneously"!? Commented Nov 6, 2019 at 15:10
  • No .. what I says is you can't call Resources.Load from a thread or run it on a thread. Most of Unity's API can only be used in the main thread. You should change the title because this is the answer to your title actually ;) Commented Nov 6, 2019 at 15:17

1 Answer 1

4

I'm unable to test this code atm, but i guess you get the idea.

GameObject raceGameObject;
// Start "Message" can be a coroutine
IEnumerator Start()
{
    // Load the resource "Race" asynchronously
    var request = Resources.LoadAsync<GameObject>("Race");
    while(!request.IsDone) {
        yield return request;
    }
    raceGameObject = request.asset;
    Do();
}

private void Do()
{
    // Instantiating 1000 gameobjects is nothing imo, if yes split it then, with a coroutine
    for(int i=0;i<1000;i++)
    {
        GameObject RaceGO = Instantaite(raceGameObject);
        RaceGO.transform.SetParent(Content);
    }
}

Also i do not recommend this you should just make a public Gameobject myGameObj; field assign a value to it inside the editor then just do this:

// Assign this inside the editor
public GameObject Race;

void Start()
{
    Do();
}

private void Do()
{
    // Instantiating 1000 gameobjects is nothing imo, if yes split it then, with a coroutine
    for(int i=0;i<1000;i++)
    {
        GameObject RaceGO = Instantaite(Race);
        RaceGO.transform.SetParent(Content);
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I think this while(!request.IsDone) { yield return request; } is a bit redundant and you could either directly yield return Resources.LoadAsync(...); or just yield return null; in the loop
@derHugo i think you are right, for sure returning request is redundant, will edit the answer tho when i tried the code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.