Search code examples
unity-game-engineprefab

Attaching prefab's script to another prefab as a component


I have Player prefab with script Player

Also I have GameController prefab with script TouchMove. This is TouchMove code:

public class TouchMove{
    [SerializeField] Player player;
    .....
}

So TouchMove has player object as a component, which I attach through unity inspector. TouchMove script is responsible for player movement. That is why it neads the player object.

Also I have a lot of scenes and each one contains GameController and Player objects. When I modify the GameController or Player components I wanted the all game objects at the all scenes to be updated. That is why I decided to create prefabs: GameController prefab and Player prefab.

In inspector I added Player prefab to GameController prefab because TouchMove of GameController requares player object.

enter image description here

But after it when I run the game the player script gets not active. I mean that I get unable to move player in the game. (the player script gets not working) This problem solves if I attach Player to GameController as just game objects (not the prefabs or without prefabs)

So, my questions:

  1. why player scripts gets not working if I attach it with prefabs and it works if I attach just as game objects (without prefabs)
  2. Is it possible to link two prefabs in the way I described?

Solution

  • The reason you are getting this problem is that player prefab and specific instance of the player prefab - are not the same object. They are both GameObject-s, and can both be referenced.

    In your case GameController references a player prefab, but the player in the scene is a new object, which was created on scene start by CLONING the player prefab. Since it was created only on scene start - another prefab can never reference it.

    To solve this, you can take couple approaches.

    First, parent both player and game controller under 1 new object, call it GameManager for example. Then you will have only one prefab - game manager, that contains both player and controller.

    Second option, the one I usually use, is to find the player object at load time. Instead of passing player s a public argument, find it on awake, for example like this:

    private Player player;
    void  Awake() {
        player = FindObjectOfType<Player>();
        Assert.IsNotNull(player);
    }