【问题标题】:C# Unity2D Is it possible to call a script based on a string? [closed]C# Unity2D 是否可以基于字符串调用脚本? [关闭]
【发布时间】:2021-01-05 00:32:21
【问题描述】:

是否可以在从文本变量中找到方法名称的脚本中运行方法?

例如:


public text MyVariable;

public void Start()
{
    MyVariable = RunMeBaby;
    MyVariable();
} 

public void RunMeBaby()
{
    Debug.Log("You did it!");
}

在上面的示例中,我将变量“MyVariable”分配给“RunMeBaby”(我要调用的方法的名称),然后尝试调用它。

以上方法对我不起作用,但还有其他方法吗?


编辑以在下面添加更多说明

我目前正在创建自己的纸牌游戏。我创建了一个可编写脚本的对象 (CardAsset) 来处理我所有填充的卡片都需要的一些字段。像这样的东西:

卡名(字符串)

成本(整数)

图像(图像)

描述文本(字符串)

现在我的原型的所有其他东西都已完成(比赛场地、套牌等),我需要开始为我的卡牌实际制作效果。由于每张卡都不同,但有些效果是相同的(例如,抽更多卡并对角色造成伤害很常见),我想我可以更改我的可编写脚本的对象 CardAsset 以包含一些脚本和变量:

卡名(字符串)

成本(整数)

图像(图像)

描述文本(字符串)

效果1(脚本)

Effect1Amount (int)

效果2(脚本)

Effect2Amount (int)

Effect3(脚本)

Effect3Amount (int)

这样,我可以创建最多具有 3 种效果的 CardAssets(例如对角色造成伤害或绘制卡片),然后在我的游戏中使用某些东西在玩家使用该卡片时调用具有相关变量的脚本.

我的问题是我无法将脚本附加到 CardAsset,因此我认为合适的解决方法是在 CardAsset 上的 Effect1/Effect2/Effect3 插槽中输入方法名称(DealDamage、DrawCards)(将它们更改为字符串),然后读取它们并在其他地方调用相关方法。

我了解此解决方案容易出错并且维护/更改可能会很痛苦,那么我有更好的方法吗?

【问题讨论】:

  • Action a = RunMeBaby; a();
  • 请描述你的用例..我想不出很多这会很有意义......当然你可以使用大多数答案中提到的反射..问题是:这真的是你想做的吗?使用字符串不仅很慢而且很容易出错,并且可能(并且将会)在可维护性方面给 a** 带来痛苦......
  • @derHugo 我在这里描述了我的用例:stackoverflow.com/questions/63974091/…

标签: c# unity3d


【解决方案1】:

您好,欢迎来到 Stack Overflow,

我不知道有关您的文本类的详细信息,但根据您的问题,我认为它是一个字符串容器(可以这么说)。 您可以使用反射完全按照您的要求(基于字符串调用方法):

// You need the class name, so I just called it MyClass
public class MyClass 
{
    public void Start()
    {
        string methodName = "RunMeBaby";

        // Invoke the method using reflection
        typeof(MyClass).GetMethod(methodName)?.Invoke(this, null);
    } 
...

但是,这是一个非常昂贵(且容易出错)的调用。 我的建议是使用一种不太通用的方法:

public void Start()
{
    // assuming text.Text is your string property
    string methodName = "RunMeBaby";
    
    CallMethod(methodName);
} 

private void CallMethod(string methodName)
{
    switch(methodName)
    {
        case nameof(RunMeBaby):
            RunMeBaby();
            break;
        case nameof(SomeOtherMethod):
            SomeOtherMethod();
            break;           
    }
}

private void RunMeBaby()
{

}

private void SomeOtherMethod()
{

}

注意: 我不知道你从哪里得到你的方法字符串,但如果它不是来自一些外部来源(例如用户输入),你最好使用 nameof 关键字而不是硬编码字符串。如果可能的话,您应该完全摆脱字符串并将它们替换为代表可调用方法的枚举,但此解决方案取决于您的用例。

【讨论】:

    【解决方案2】:

    如果您想按名称调用方法。你可以使用反射:

    Test type = new Test();
     typeof(Test).GetMethod("Hello").Invoke(type, new[] { "world" }); 
    

    【讨论】:

      【解决方案3】:

      您可以通过 C# 中的反射来实现。但在我们到达那里之前,我会推荐 如果可能的话,您可以使用 Action 委托 (https://docs.microsoft.com/en-us/dotnet/api/system.action?view=netframework-4.7.2) 来分配您的方法,然后在任何您想要的地方调用它。 因此,您的代码将如下所示:

      public Action MyVariable =RunMeBaby;
      MyVariable();
      

      现在的反射方式:

      public string MyVariable = "RunMeBaby";
      
      public void Start()
      {
          this.GetType().GetMethod(MyVariable).Invoke(this, null);
      }
      

      以上代码假定要调用的方法(在您的情况下为“RunMeBaby”)是公开的。

      https://docs.microsoft.com/en-us/dotnet/api/system.type.getmethod?view=netframework-4.7.1 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-26
        • 2020-01-16
        • 2014-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-29
        • 1970-01-01
        相关资源
        最近更新 更多