【问题标题】:Unity's GetComponent by string (or by some other method being passed from another script)Unity 的 GetComponent 通过字符串(或通过从另一个脚本传递的其他方法)
【发布时间】:2018-09-19 17:34:38
【问题描述】:

我试图使用尽可能少的脚本,所以我用buttonScript 预制件从SpawnerspawnerScript 实例化(例如:)Button。在点击Button(在buttonScript 中检测到)时,我希望在spawnerScript 中调用一个特定的函数——但没有SpawnerspawnerScript 由用户在buttonScript 中定义。它们可以注入到这个脚本中,但不能在脚本中输入或在 Unity 的编辑器中定义。我该怎么做?

tl;dr - 如何在其他脚本中调用函数而不在 GetComponent 中手动输入脚本名称?为 GetComponent 注入目标脚本是我正在寻找的。​​p>

【问题讨论】:

  • 这样的? gameObject.GetComponent("YourScriptAsString") as YourScriptType;
  • 如果我理解正确,那么只需使用 GetComponent 获取脚本句柄并将其设置为变量即可。然后在以后的代码行中使用该变量。
  • @Programmer 没错,除了“YourScriptType”应该代表什么?
  • 脚本或类的名称。例如public class Hello : MonoBehavior {}。在这种情况下Hello
  • @Programmer 当然,但我没有在 buttonScript 中定义这个。我如何将这个“你好”传递给它?

标签: c# unity3d


【解决方案1】:

您可以将委托传递给按钮

 public class Spawner : MonoBehaviour{

       void Start(){
             GameObject btn = Instantiate<GameObject>(btnPrefab);
             btn.GetComponent<Button>().onClick.AddListener(Method);
        }
        void Method(){}
 }

根据评论编辑:

“按钮包含一个非常简单的脚本,它只包含一个游戏对象(在实例化时分配)”

所以你在实例化时传递了 GameObject。让我们在下面的例子中考虑这个目标是从 GetTarget() 给出的(我不知道你是怎么得到它的)

void Start()
{
    for(int i = 0 ; i < 100; i++)
    {
         GameObject btn = Instantiate<GameObject>(btnPrefab);
         GameObject target = GetTarget();
         btn.GetComponent<Button>().onClick.AddListener(()=>
         {
             Method(target);
         });
    }
}
void Method(GameObject obj)
{
    Debug.Log(obj.name);
}

这里要抓住的概念是带有箭头的 lambda 表达式。这可以理解为一个没有名字的方法,只在里面使用(因为没有名字,所以不能在别处调用)。该方法返回 void 并且没有参数,因此它符合 Button 侦听器要求。在那个无名的方法中,您调用另一个采用 GameObject 目标的方法。这里创建了一个闭包,因此即使 Button 对象不知道目标,它也会找到它。

一开始并不那么简单,但你会明白的。

【讨论】:

  • 这对于我的需求来说似乎是一个相对不错的解决方案(除了我实际上需要按钮中的变量,但可能可以解决)。单击它时,我能否以某种方式获取按钮的游戏对象(假设生成了 100 个,而不是保存在列表中)?竖起大拇指,如果我没有得到专门针对我所要求的答案的答案,我会选择它作为答案。
  • (如,如果“btn”被时间覆盖,我可以得到被点击并触发方法的游戏对象吗?)
  • 你应该看看 lambda 方法。还有哪些数据,来自哪里以及如何使用?
  • 我正在制作一个通用按钮预制件(将在大列表中使用),其中按钮包含一个非常简单的脚本,仅包含一个游戏对象(在实例化时分配)。在生成器中(并且会有多个),他们使用“for”来生成许多这些按钮,修改它们并在完成后立即“忘记”它们。我希望从按钮调用这个相同的生成器脚本并传递它的目标游戏对象(来自之前分配的按钮脚本),而不由用户定义生成器游戏对象的脚本名称。它可以在按钮实例化时自动定义,否则不会。
  • 脚本不积累任何东西。它获取新创建的按钮的按钮组件并将其方法分配给它。如果 Spawner 脚本被销毁,那么您的按钮将获得空引用异常(实际上这取决于您所做的,但我们不要到达那里),如果您销毁按钮,则从 Button 到 Spawner 方法的链接将被删除,并且没有任何反应。尽管在销毁时清除或删除侦听器是一个好习惯。
【解决方案2】:

将您的 Spawner 脚本设为静态,以便始终只有一个,您可以使用 Class 而不是变量版本来访问它。

然后代替

GameObject.GetComponent().doMethod();

它的

Spawner.doMethod();

【讨论】:

  • 恐怕我不能这样做,因为我打算生成其他按钮来调用其他“生成器”(带有自己脚本的游戏对象)。
  • 如果我误解了您的评论,请说。我正在尝试创建通用按钮,可以将不同的目标脚本传递给该按钮以供同一功能使用。
  • 这可能不行,因为他有 100 多个按钮,而且他们都会使用该静态方法,因为他们都共享它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多