1

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

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

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

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

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

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

在此处输入图像描述

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

所以,我的问题:

  1. 为什么如果我将播放器脚本与预制件一起附加它会不起作用并且如果我将其作为游戏对象附加(没有预制件)它会起作用
  2. 是否可以按照我描述的方式链接两个预制件?
4

2 回答 2

1

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

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

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

首先,在 1 个新对象下将玩家和游戏控制器作为父对象,例如将其称为 GameManager。然后您将只有一个预制件 - 游戏管理器,它包含播放器和控制器。

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

private Player player;
void  Awake() {
    player = FindObjectOfType<Player>();
    Assert.IsNotNull(player);
}
于 2021-12-16T11:58:31.267 回答
1

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

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

private void Awake()
{
    player = FindObjectOfType<Player>();
}
于 2021-12-16T12:03:46.820 回答