Issue with variables across gameObjects

I have this issue where I want to access a variable from another GameObject. In the other object, i type in “public (other script) script1”. The window appears in the script component’s dropdown menu, as it should. The issue is, I cant put the other script into the window. I tried copying and pasting the component and dragging the script itself into the window from my Assets screen. Is there a solution?

You cannot drag a script asset itself like that. You have to drag a game object that has the script as a component.

Okay, but this solution doen’t work if the object trying to access the script is a prefab, which is what I’m looking for. Any solutions for prefabs?

If the prefab is not instantiated you have to instantiate it first. If it is instantiated, it is in your current scene and you can get it when you need it with GetComponent . If you want your script to instantiate it, you can set the prefab as a public GameObject - and then drag and drop. You can also make the prefab script “set itself” to the other script in its Start method.

Can you describe the scenario you’re trying to make? If the script is on the root object of another prefab, you can drag the other prefab there.

Otherwise, if the script is in a game object that is created at runtime, then having it assigned on the prefab doesn’t make sense. You’d need to get a reference to that script at runtime somehow and assign it to the variable of a prefab instance via code.

The script is on a game object that is already there at runtime, but the gameObject trying to access it is a prefab. I’m looking for a way to assign the script to the prefab, right after it is created, and be able to access it later (the assigned script). Is that possible?

Not possible no, unless you drag the prefab in the same scene to create a prefab instance in the scene. Then you can drag the other game object into that prefab instance.

If the prefab instance will only be created at runtime, then you cannot have the reference set in editor. That wouldn’t make sense as the prefab has no “knowledge” of any scene. Instead, you’d need to get the reference to that script at runtime somehow, maybe via something like FindObjectOfType, or through some other manager object in the scene that already has a reference to it.

You could make a ‘dead’ instance of that prefab (one that will be invisible and disabled, so not running update etc) in the scene, set your script in the inspector and then clone that instance whenever you want to instantiate it.

However, since you have to instantiate it from another script, why not set the dependencies there right after instantiation?

I like this tidy pattern for making and late-connecting stuff at runtime… I use it everywhere in my games, having generally very little already placed in the scene beforehand.

Factory Pattern in lieu of AddComponent (for timing and dependency correctness):

There are some limitations to serialized fields:

  1. Serialized fields in prefab assets can not be assigned references to scene objects,
  2. serialized fields in scene objects can not be assigned references to objects in other scenes
  3. and no serialized fields can be assigned references to runtime-instantiated prefab instances (with the exception of objects attached to the instantiated prefab asset itself).

The most straight-forward way to get around these limitations is to make your client components locate the component they need from the scene hierarchies at runtime after it has been loaded. There are many ways to do this, such as FindAnyObjectByType and FindWithTag.

Alternatively you can register the prefab instance somewhere when it is instantiated, and then have your client components fetch the reference from that location.

Since serialized fields in all scenes and prefabs can always reference assets in the Project view, one way that references to runtime-instantiated prefab instances can be provided to scene objects is to have the prior register itself in a scriptable object asset when it is being loaded, and then have the latter fetch the reference from the scriptable object asset later on.

using UnityEngine;

[CreateAssetMenu]
public sealed class GameObjectReference : ScriptableObject
{
	GameObject gameObject;
	
	public void Set(GameObject gameObject) => this.gameObject = gameObject;
	public TComponent GetComponent<TComponent>() => gameObject.GetComponent<TComponent>();
}

[DefaultExecutionOrder(-1000)]
public sealed class Player : MonoBehaviour
{
	[SerializeField] GameObjectReference playerReference;

	void Awake() => playerReference.Set(gameObject);
}

public sealed class Enemy : MonoBehaviour
{
	[SerializeField] GameObjectReference playerReference;
	[SerializeField] Player player;
	
	void Start() => player = playerReference.GetComponent<Player>();
}

This is an example of the Service Locator pattern.

Other commonly-used solutions to the problem are the Singleton pattern and automating things using a Dependency Injection framework.

@Sealer0 Thanks, I think I’ll just do that!