如何通过 GetComponent 从另一个游戏对象中的另一个脚本访问变量?

Posted

技术标签:

【中文标题】如何通过 GetComponent 从另一个游戏对象中的另一个脚本访问变量?【英文标题】:How to access a variable from another script in another gameobject through GetComponent? 【发布时间】:2014-12-20 12:10:40 【问题描述】:

我已经四处搜索,但我无法让它工作。我想我只是不知道正确的语法,或者只是不太了解上下文。

我有一个包含公共 int 的 BombDrop 脚本。我让这个与公共静态一起工作,但有人说这是一个非常糟糕的编程习惯,我应该学习封装。这是我写的:

BombDrop 脚本:

 <!-- language: c# -->

 public class BombDrop : MonoBehaviour 

 public GameObject BombPrefab;

 //Bombs that the player can drop
 public int maxBombs = 1;


 // Update is called once per frame
 void Update () 

 if (Input.GetKeyDown(KeyCode.Space))

         if(maxBombs > 0)
         DropBomb();

         //telling in console current bombs
         Debug.Log("maxBombs = " + maxBombs);
         
   


     

 void DropBomb()

     // remove one bomb from the current maxBombs
     maxBombs -= 1;

     // spawn bomb prefab
     Vector2 pos = transform.position;
     pos.x = Mathf.Round(pos.x);
     pos.y = Mathf.Round(pos.y);
     Instantiate(BombPrefab, pos, Quaternion.identity);

 

所以我希望附加到 prefabgameobject Bombprefab 的 Bomb 脚本访问 BombDrop 中的 maxBombs 整数,这样当炸弹被摧毁时,它会在 BombDrop 中的 maxBombs 上加一。

这是需要引用的 Bomb 脚本。

 public class Bomb : MonoBehaviour 
 // Time after which the bomb explodes
 float time = 3.0f;

 // Explosion Prefab
 public GameObject explosion;

 BoxCollider2D collider;

 private BombDrop BombDropScript;




 void Awake ()

     BombDropScript = GetComponent<BombDrop> ();
 

 void Start () 

     collider = gameObject.GetComponent<BoxCollider2D> ();

     // Call the Explode function after a few seconds
     Invoke("Explode", time);

 

 void OnTriggerExit2D(Collider2D other)

     collider.isTrigger = false;
 

 void Explode() 
     // Remove Bomb from game
     Destroy(gameObject);

     // When bomb is destroyed add 1 to the max 
     // number of bombs you can drop simultaneously .
     BombDropScript.maxBombs += 1;

     // Spawn Explosion
     Instantiate(explosion,
                 transform.position,
                 Quaternion.identity);

在文档中它说它应该类似于

BombDropScript = otherGameObject.GetComponent<BombDrop>();

但这不起作用。也许我只是不明白这里的语法。是否应该说 otherGameObject?因为那没有任何作用。我仍然收到错误:“对象引用未设置做对象的实例”在我的 BombDropScript.maxBombs 中的爆炸()

【问题讨论】:

你可以用这个BombDropScript = this.GetComponent&lt;BombDrop&gt;(); 嗯。还是同样的错误。 : / What is a NullReferenceException and how do I fix it?的可能重复 Don't know how to get enemy's health的可能重复 【参考方案1】:

您需要找到包含您计划引用的脚本组件的游戏对象。确保游戏对象已经在场景中,否则Find 将返回null

 GameObject g = GameObject.Find("GameObject Name");

然后就可以抓取脚本了:

 BombDrop bScript = g.GetComponent<BombDrop>();

然后就可以访问脚本的变量和函数了。

 bScript.foo();

我刚刚意识到前几天我回答了一个非常相似的问题,请查看: Don't know how to get enemy's health


我已经回答了你的问题,所以我会稍微扩展一下。

您的代码正在执行的操作是“在我的游戏对象中查找BombDropScript,大多数情况下脚本不会附加到同一个游戏对象。

还为maxBombs 使用setter 和getter。

public class BombDrop : MonoBehaviour

    public void setMaxBombs(int amount)
    
        maxBombs += amount;
    

    public int getMaxBombs()
    
        return maxBombs;
    

【讨论】:

这听起来很对,但只有一个问题。 bombPrefab 是我不想留在场景中的预制件。因为摧毁它会改变我的 maxBombs 计数。如果我在场景中已经有炸弹,它就会把柜台弄乱。有没有办法在没有场景的情况下访问预制脚本? 有一些方法可以让类对象在场景中不存在的情况下存活。例如,静态类、不是 MonoBehaviour 的常规 C# 类等。但是,您的代码确实暗示 BombDrop 需要在场景中,因为 Update 代码会创建炸弹。此外,我刚刚意识到您可以更简单地编写代码。我会更新我的答案。 是的,我的播放器有 BombDrop 脚本来实例化 bombPrefab。所以预制件在实例化之前不在场景中。但也许目标一旦实例化就可以工作?所以它还是找到了它的目标?好的,那将有很大帮助:) 我的代码正是我可以从自己的错误逻辑中总结出来的内容,呵呵。 还有一件事!我计划拥有多个玩家,所以炸弹需要知道是谁创造了它。所以它不会重置其他玩家的计数器。但那是以后的事了。首先我只需要参考:) 谢谢:)我会看看片场并从文档中获取逻辑。【参考方案2】:

在开始时使用它而不是在唤醒时使用它并且不要使用Destroy(gameObject); 你正在破坏你的游戏对象然后你想要从中得到一些东西

void Start () 
     BombDropScript =gameObject.GetComponent<BombDrop> ();
     collider = gameObject.GetComponent<BoxCollider2D> ();

     // Call the Explode function after a few seconds
     Invoke("Explode", time);

 

void Explode() 
//..
  //..
//at last
Destroy(gameObject);
 

如果你想访问另一个游戏对象中的脚本,你应该通过检查器分配游戏对象并像那样访问它

 public gameObject another;
void Start () 
     BombDropScript =another.GetComponent<BombDrop> ();

【讨论】:

嗯,不还是不行。也许它与explode方法有关? 不要使用 Destroy(gameObject);你正在摧毁你的游戏对象然后你想要从中得到一些东西 啊,我明白了,所以它会在调用之前将其销毁?但是我怎样才能让它在它被销毁后改变变量。如果我将它设置在 Explode() 中的破坏上,它永远不会破坏。 把它作为它做的最后一件事 void Explode() //.. //.. //at last Destroy(gameObject); 嗯。我现在有 Explode() BombDropScript.maxBombs before the Destroy(gameObject 但是 Ingame 现在它永远不会破坏,它永远不会消失。而且我仍然在我的 BombDropScript.maxBombs 上获得 Null 引用我怀疑它仍然找不到 maxBombs来自 BombDrop 脚本,因此只是停止。但它确实适用于公共静态。【参考方案3】:

可以用这个:

entBombDropScript.maxBombs += 1;

之前:

Destroy(gameObject);

我只想说你可以在Destroying游戏对象之前增加maxBombs的值。这是必要的,因为如果你先销毁游戏对象然后增加值,那么那时你的脚本BombDropScript 的引用将消失,你不能修改其中的值。

【讨论】:

以上是关于如何通过 GetComponent 从另一个游戏对象中的另一个脚本访问变量?的主要内容,如果未能解决你的问题,请参考以下文章

Unity:无法通过getcomponent获取对类的引用

从另一个 GameObject 的脚本设置变换

如何通过脚本查找 GameObject 的子对象或附加到子 GameObject 的脚本

unity3d通过代码动态创建销毁游戏对象

从另一层重新启动游戏/场景

在 Kivy 中,我如何从另一个以 kv 语言显示的另一个屏幕获取变量