【问题标题】:How to get access to the target that has been instantiated in Unity?如何访问已在 Unity 中实例化的目标?
【发布时间】:2017-10-07 19:52:32
【问题描述】:

我正在制作一个游戏,我需要在游戏开始时生成一个玩家。然后我会得到那个玩家的transform.position,但我不知道该怎么做。这是我的代码:

GameObject playerball;
Transform spawpoint;
bool spaw

private void Start(){
    spaw = false;
}

private void Update()
{
   if(!spaw)
   {
       Instantiate(playerball, spawpoint.position, spawpoint.rotation);
       spaw=true;
   }

   //????????????
}

如您所见,我不知道如何访问该球员球。该 playerball 是包含控制脚本的预制件,该脚本具有“转换公共摄像机”,但在预制件中“公共转换摄像机”为“无(转换)”。所以我需要它,当我实例化球员球时,我可以控制它,这意味着我可以设置哪个是“公共变换相机”。我该怎么做?

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    Instantiate 返回对您刚刚实例化的对象的引用。您只需要保留该参考,并根据自己的需要进行处理:

    GameObject instance = Instantiate(playerball, spawpoint.position, spawpoint.rotation);
    

    另外,您在这一行缺少分号:

    bool spaw
    

    然后整个代码会给出:

    GameObject playerball;
    Transform spawpoint;
    bool spaw;
    GameObject playerballObject;
    
    private void Start(){
        spaw = false;
    }
    
    private void Update()
    {
        if(!spaw)
        {
            playerballObject = GameObject.Instantiate(playerball, spawpoint.position, spawpoint.rotation);
            spaw=true;
    
            // Do any first time modification you need on your object.
        }
    
        // Use your reference there to update the state of your object.
    }
    

    【讨论】:

    • 那么这意味着“实例”将具有已生成的“玩家球”的位置?
    • @Huy.V 没错。它是对您在场景中实例化的 Playerball 对象的直接引用。所以两个transform.position 组件是相等的。如果您修改该参考上的任何内容,它将影响场景中的对象。
    • 请注意...您可能希望将GameObject instance 声明在更新方法之外,以便它持续超过一帧。
    • 这有点取决于他想用它实现什么。对我来说,代码的这个 Instantiate 部分甚至应该放在 Start 函数中,以便它只运行一次,而不是像这样的 Update。不过,也许 OP 是有原因的。
    • 如果是一次性修改,那么声明应该在 if(!spawn) check. 内,这样可以避免不必要的 if(instance != null) 检查,因为它唯一不为 null 的时间是 if spawn 是 false 我们已经检查过了。
    【解决方案2】:

    替代脚本,为了提高效率、简洁的代码和良好的实践,做了一些 Isuka 没有做的更改。

    public GameObject playerballPrefab;
    public Transform spawpoint;
    private GameObject playerballInstance;
    
    private void Update()
    {
       if(playerballInstance == null)
       {
           playerballInstance = Instantiate(playerballPrefab, spawpoint.position, spawpoint.rotation);
          // Other spawn logic / modification
       }
    
       //do stuff with playerballInstance every frame
    }
    

    请注意,我们不再需要 bool spawn 变量(呃,spaw 拼写错误),因为我们可以检查 playerballInstance 是否为空,如果是,则生成它。任何时候它为空(例如,如果它被任何方式破坏),我们将生成一个新的(我将其重命名为playerballPrefab,只是为了使变量的名称表明该对象不在场景层次结构中;纯粹是可选的),就像 spawn 被外部脚本重置为 false 一样,但没有任何潜在的冲突(例如,将 spawn 设置为 false 不会破坏实例,反之亦然)。

    此外,我们永久保留该引用,以便可以连续对球进行操作,而不是针对它被实例化的单帧。 Isuka 编辑了他们的答案以包含此更改。

    playerballInstance 可以设置为公共(因为我们希望外部脚本修改值)或私有(因为其他脚本不应该接触它)。 prefab 和 transform 被声明为 public,因为大概它们是在编辑器/检查器中定义的(并且私有字段未列出且不可序列化)。

    不再需要 Start 方法,因为我们不再有 spawn 值来确保设置为我们想要的(以及最初不需要的,如 default value for a bool is false 以及我们可以声明 bool spawn = false 的事实无论如何都没有 Start() 方法)。

    Start()Update() 标记为私有也不是绝对必要的,但也没有错。同样,将其标记为公开也没有必要或错误。我个人要么将其关闭(从 MonoBehaviour 继承其保护级别),要么将其标记为公开(因为所有 MonoBehaviour 都声明了此方法)。使用什么保护级别对引擎没有影响,因为它被调用through voodoo

    【讨论】:

      猜你喜欢
      • 2020-08-25
      • 2017-09-30
      • 2017-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多