Why are unity scripts file executed in single thread?

Hi, I am quite new to unity and programming. The issue, I face more often, is that sometimes I want to execute some specific commands for particular frames, for instance, let’s say I want to deactivate an object for the rest of script life. That gameobject.setActive() will keep on executing for the rest of the frames in the update() . I want to ask why can’t we run the update() in two threads synchronously in such a way that commands like these will get executed in a parallel update process only once so that the object states won’t get updated every frame. Or Maybe we can have a specific function ExeOnlyForfewFrames() and put these statements into them. Sorry if I sound dumb but just curious about that.

Well i’d say we have 2 different answers to this.

The first answers your literal question: Why are scripts file executed in single thread?

We can only really guess about this as Unity afaik does not really put out an explanation but mine would be: For simplicity reasons. If you are a beginner as you claim to be one then multithreading will mess with you - big time. Multithreading puts in another layer of complexity and randomness that even experienced programmers can have a hard time to deal with. Writing threadsafe code is not easy and multithreading is sometimes also not just the simple solution to every problem.

Unity also offers a kind of Multithreading solution with their Job-System (see Burst as well). This can be used to speed up computational tasks which are needy regarding performance.
If you want to go full Job-System you can also just build your game in the ECS instead of the normal MonoBehaviour-System but that is way more difficult and an overkill for most projects.

Now in your post you basically state: “well my code calls “SetActive(false)” each frame so how to multithread”

This is the point where i’d suggest a different approach. You already realized that this does not seem to be a good solution so in that regard this should show you that perhaps the code design you chose is not the best.

In general the rule of thumb i’d propose is: Update() should do as few “checks” as possible. Most things that are commonly checked in Update - like if a variable has a specific value - can be moved to be executed when the variable is set instead.

Example:

public class BehaviourA : MonoBehaviour
{
	bool Flag = false;
	void Update()
	{
		if(Input.KeyDown(...)  && !Flag)
		{
			Flag = true;
		}
	}
}

public class BehaviourB : MonoBehaviour
{
	public BehaviourA otherBehaviour;
	void Update()
	{
		if(otherBehaviour.Flag == true)
		{
			otherBehaviour.gameObject.SetActive(false);
		}
	}
}

This solution will call “SetActive” for the otherBehaviour each frame.

Alternative way to write this:

public class BehaviourA : MonoBehaviour
{
	bool Flag = false;
	public BehaviourA B_Behaviour;
	void Update()
	{
		if(Input.KeyDown(...) && !Flag)
		{
			Flag = true;
			B_Behaviour.DoStuff();
		}
	}
}

public class BehaviourB : MonoBehaviour
{
	public BehaviourA otherBehaviour;
	public void DoStuff()
	{
		if(otherBehaviour.Flag == true)
		{
			otherBehaviour.gameObject.SetActive(false);
		}
	}
}

This version only does it once. Exactly then when we need to do it. No update in BehaviourB needed.

An even better way to do it to reduce dependencies of classes on one-another by using Actions:

public class BehaviourA : MonoBehaviour
{
	bool Flag = false;
	public System.Action OnFlagSetAction;
	void Update()
	{
		if(Input.KeyDown(...) && !Flag)
		{
			Flag = true;
			OnFlagSetAction?.Invoke();
		}
	}
}

public class BehaviourB : MonoBehaviour
{
	public BehaviourA otherBehaviour;
	public void Awake()
	{
            //"subscribe" to the OnFlagSetAction to execute "DoStuff":
		otherBehaviour.OnFlagSetAction += DoStuff;
	}
	
	public void DoStuff()
	{
		if(otherBehaviour.Flag == true)
		{
			otherBehaviour.gameObject.SetActive(false);
		}
	}
}

As you can see there are easy ways to reduce the need for Update methods and to slim down the performance that we need to execute them.
Imo Updates should only do stuff that for example check position changes, User Input (when using old Input System - the new one also uses Actions) and/or Timings.
Everything else should (and mostly can) be done event-driven → meaning that code is only really checked/executed when some event actually happens.

Only just come across this. Captain_Pineapple knows their stuff and their answer is very full. I will add one more thing, if I may,

Let’s say that you have a lot of enemies and they are all doing their own AI thing. In the single threading world, having all enemies recalculate their AI in Update could cause significant lag. This is where you would use coroutines. A coroutine allows you to split work into chunks and only do as much as you want in a single frame. So you might process just a few enemies and then yield until the next frame comes along when you do some more. Coroutines do not offer parallel processing so it’s not a route to what you might ultimately want but they are good are preventing lag by overloading a single Update.

Captain_Pineapple also mentions the Job system and if you’re into techy stuff, search out the Unity DOTS system, which will take advantage of multicore systems.