【问题标题】:Unity - Cant access reference to another scriptUnity - 无法访问对另一个脚本的引用
【发布时间】:2022-01-12 00:55:51
【问题描述】:

我正在尝试了解 Unity 的工作原理,但现在我遇到了无法从另一个脚本访问脚本的问题。我在 Interner 上搜索了几个小时,我尝试了很多选项,但没有任何帮助。

我有 2 个脚本。

  • CoinSpawn.cs - 附加到播放器(我会将其更改为其他对象,但我还不知道是哪个对象,因为它在后台运行,所以它真的不需要在播放器上)

  • CollectingCoin.cs - 附加到 Coin(Coin 是对象,一开始它不在游戏场景中,它随机生成)

CoinSpawn 是随机生成对象 Coin 的实例化的脚本。我想从 CollectingCoin 更改 CoinSpawn.currentCoinOnScreen 的值。我试过了

CoinSpawn test = GameObject.Find("CoinSpawn").GetComponent<CoinSpawn>(); 

它不起作用。我的两个脚本也在同一个资产文件夹中。我究竟做错了什么?谢谢

CoinSpawn.cs

public class CoinSpawn : MonoBehaviour
{
    public GameObject coin;
    public int maximumCoinPerScreen = 10;
    public int currentCoinOnScreen = 0;
    private int randomNumber;
    private Vector2 spawnPosition;

    private void Update()
    {
        randomNumber = Random.Range(1, 1000);
        if(randomNumber >= 0 && randomNumber <= 1 && currentCoinOnScreen != maximumCoinPerScreen)
        {
            currentCoinOnScreen++;
            float spawnY = Random.Range
    (Camera.main.ScreenToWorldPoint(new Vector2(0, 0)).y, Camera.main.ScreenToWorldPoint(new Vector2(0, Screen.height)).y);
            float spawnX = Random.Range
                (Camera.main.ScreenToWorldPoint(new Vector2(0, 0)).x, Camera.main.ScreenToWorldPoint(new Vector2(Screen.width, 0)).x);
            spawnPosition = new Vector2(spawnX, spawnY);
            GameObject coinObject = Instantiate(coin, spawnPosition, Quaternion.identity);
        } 
    } 
}

CollectingCoin.cs

public class CollectingCoin : MonoBehaviour
{
    UnityEngine.UI.Text Coins;
    public static int totalCoins = 0;

    private void Start()
    {
        Coins = GameObject.Find("Score").GetComponent<UnityEngine.UI.Text>(); 
    } 
    void OnTriggerEnter2D(Collider2D c2d)
    { 
        if (c2d.CompareTag("Player"))
        { 
            totalCoins++; 
            Destroy(gameObject);
            Coins.text = "COINS: " + totalCoins.ToString();

            // TESTING 
           CoinSpawn test = GameObject.Find("CoinSpawn").GetComponent<CoinSpawn>();
            CoinSpawn test2 = GetComponent<CoinSpawn>();
        }   
    }
}

【问题讨论】:

  • 你的意思是test.currentCoinOnScreen++
  • 请使用正确的标签!请注意,[unityscript] 是或更好地曾经是一种在早期 Unity 版本中使用的自定义 JavaScript 风格的语言,并且现在长期弃用。您的代码显然是 c# .. 您更愿意标记的是 unity3d,因为这是您要询问的主要 API/框架

标签: c# unity3d


【解决方案1】:
GameObject.Find("CoinSpawn").GetComponent<CoinSpawn>();

搜索名称为 CoinSpawnGameObject。既然你告诉我们这个组件是附加到播放器对象上的,所以找不到它是有道理的。

GetComponent<CoinSpawn>();

在您的CollectingCoin 附加到的同一对象上搜索CoinSpawn 组件。从你的描述来看,显然也不是这样。


既然您说CoinSpawn 已附加到播放器,那么您可能更希望从以下位置获取组件

void OnTriggerEnter2D(Collider2D c2d)
{ 
    if (c2d.CompareTag("Player"))
    { 
        ...

        // rather get the component on the player object you collided with
        CoinSpawn test = c2d.GetComponent<CoinSpawn>();
    }   
}

或者假设您的场景中只有一个 CoinSpawn 实例,并且不一定在您的播放器上,您可以使用 FindObjectOfType

CoinSpawn test = FindObjectOfType<CoinSpawn>();

【讨论】:

  • 谢谢,这正是我想要的。老实说,我不明白为什么我需要通过 c2d Collider 引用另一个脚本,但我认为这是我将要学习的东西,并在未来找出为什么会这样。
【解决方案2】:

首先,永远不要使用 GameObject.Find(),它非常昂贵,因为它会遍历场景中的所有游戏对象来查找对象。这不是性能方面的明智之举。

有很多方法可以做到这一点。 最简单的一个:

  1. 将两个脚本作为组件添加到相同的游戏对象中。

  2. 在CollectingCoin脚本中创建一个全局变量CoinSpawn,然后在上面使用[serializedFiled]标签,这样你就可以在开始播放之前在编辑器中拖放引用。您可以按照自己的方式访问它。

第二种方式:

和第一个一样,但不是serializedFiled,而是在开头使用GetComponent缓存它。

只需确保将两个脚本都附加到同一个游戏对象。

public class CollectingCoin : MonoBehaviour
{
    UnityEngine.UI.Text Coins;
    public static int totalCoins = 0;
    CoinSpawn coinSpawn;

    private void Start()
    {
        coinSpawn = GetComponent<CoinSpawn>();
        Coins = GameObject.Find("Score").GetComponent<UnityEngine.UI.Text>(); 
    } 

    void OnTriggerEnter2D(Collider2D c2d)
    { 
        if (c2d.CompareTag("Player"))
        { 
            totalCoins++; 
            Destroy(gameObject);
            Coins.text = "COINS: " + totalCoins.ToString();

            // DO Whaterver you want with coinSpawn here 
        
        }   
    }
}

【讨论】:

  • 我不认为 OP 希望在场景中的每个硬币实例上都有一个 CoinSpawn 组件......而是一个单独的。这排除了您的两个建议
  • 如果最好不要使用 GameObject.Find() 那么我怎样才能找到我想要的任何对象?例如,我的场景中有文本分数,我想从我的一个脚本中访问它。目前我使用'Coins = GameObject.Find("Score").GetComponent();'。有没有更好的方法找到它?谢谢。
  • 当你学习设计模式时就会出现这种情况,比如 MVC...等
猜你喜欢
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
  • 1970-01-01
  • 2022-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多