将预制件的脚本作为组件附加到另一个预制件

Attaching prefab's script to another prefab as a component

我有带有脚本 Player 的 Player 预制件

我还有带有脚本 TouchMove 的 GameController 预制件。 这是 TouchMove 代码:

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

所以 TouchMove 将播放器对象作为一个组件,我通过 unity inspector 附加了它。 TouchMove 脚本负责玩家移动。这就是为什么它需要玩家对象。

我还有很多场景,每个场景都包含 GameController 和 Player 对象。 当我修改 GameController 或 Player 组件时,我希望更新所有场景中的所有游戏对象。这就是我决定创建预制件的原因:GameController 预制件和 Player 预制件。

在检查器中,我将 Player 预制件添加到 GameController 预制件中,因为 GameController 的 TouchMove 需要玩家对象。

但在它之后 当我 运行 游戏时玩家脚本变得不活跃 。我的意思是我无法在游戏中移动玩家。 (播放器脚本无法正常工作) 如果我将 Player 附加到 GameController 作为游戏对象(不是预制件或没有预制件)

,这个问题就会解决

所以,我的问题:

  1. 为什么如果我用预制件附加播放器脚本就不能工作,而如果我像游戏对象一样附加它(没有预制件)它就可以工作
  2. 是否可以按照我描述的方式link两个预制件?

您遇到此问题的原因是播放器预制件和播放器预制件的特定实例 - 不是同一个对象。都是GameObject-s,都可以引用

在你的例子中,GameController 引用了一个玩家预制件,但场景中的玩家是一个新对象,它是在场景开始时通过克隆玩家预制件创建的。由于它仅在场景开始时创建 - 另一个预制件永远无法引用它。

要解决这个问题,您可以采取几种方法。

First,玩家和游戏控制器都在 1 个新对象下,例如将其称为 GameManager。那么你将只有一个预制件 - 游戏管理器,其中包含玩家和控制器。

第二个选项,我通常使用的选项是在加载时查找播放器对象。不要向 player 传递一个 public 参数,而是在唤醒时找到它,例如:

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

预制件需要在场景中存在(实例化)才能运行,您正在尝试做的是可编写脚本的对象的工作流。

不要通过检查器从项目目录附加源预制件,而是尝试在场景中查找预制件的现有实例(在运行时)。

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