Assets cannot directly refer to Objects in Scenes
Prefab assets cannot refer to components in the Scene, their instances can be configured with those references. This is a form of dependency injection.
If your prefab is already in the scene it is a prefab instance and treated like any other object in the scene, it just has overrides for authoring purposes.
The in-scene component that instances your prefab can reference other in-Scene components, so have it pass your instance that reference.
Refer to the table to understand the terms used in the following steps.
Term | Description |
---|---|
Spawner | A component in the scene that spawns your prefab asset. |
Root component | A component on the top-level GameObject of your prefab. |
Target component | A component in the scene that you want to pass to your prefab. |
Instance | A copy of your prefab that exists in the scene. |
Instantiate
the root component (your prefab).using UnityEngine;
/// <summary>
/// This component lives in the scene and spawns instances of MoveToTargetExample.
/// </summary>
public class SpawnerExample : MonoBehaviour
{
// (1. 1) Our prefab:
[SerializeField] private MoveToTargetExample _prefab;
// (1. 2) Our target component:
[SerializeField] private Transform _target;
public void SpawnAndConfigurePrefab()
{
// (2) Instantiate the prefab:
MoveToTargetExample instance = Instantiate(_prefab);
// (4) Configure the newly-created instance with the in-Scene reference:
instance.Initialise(_target);
}
}
using UnityEngine;
/// <summary>
/// This component lives on the root of a prefab, and is configured by SpawnerExample after it's instanced.
/// </summary>
public class MoveToTargetExample : MonoBehaviour
{
// (3) A local reference to the target:
private Transform _target;
// Step (4) calls this method:
public void Initialise(Transform target)
{
// (4) Configure this instance with the reference to target that was passed from the spawner.
_target = target;
}
Example usage// --- Example usage ---
[SerializeField] private float _speed = 1;
public void Update() =>
transform.position = Vector3.MoveTowards(transform.position, _target.position, _speed * Time.deltaTime);
}
You must change the types and variables used in this example to match yours:
Transform
must be replaced with your target type.MoveToTargetExample
must be replaced with a type of component on the prefab root.You can choose to set members directly, or customise your Initialise
method to take more parameters.
Awake
is called as soon as an object is created; in this case, don't attempt to use the references in Awake
as they haven't been assigned by the spawner.
If your prefab is being spawned outside of your control, you can delegate the target component assignment to a singleton.
Start
on a component in your prefab, register the instance (this
) to your singleton.If you are confused by any individual steps, click through the links in the resolution to see detailed examples.