【问题标题】:Access to the Coroutine through an unassigned(unknown) component通过未分配(未知)组件访问协程
【发布时间】:2023-04-02 20:37:01
【问题描述】:

下午好,也许我的问题对你来说很愚蠢!但我还是找不到答案!好像为了减少代码,我所有的尝试都陷入了深渊,我只是不知道该怎么办=(

我有很多字符串:

int _ID = Attacker.GetComponent<BaseHeroStats>().ID_Model;

if (_ID == 1) { yield return StartCoroutine(Elements[5].GetComponent<ID1>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker)); }
else if(_ID == 2) { yield return StartCoroutine(Elements[5].GetComponent<ID2>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker)); }
else if(_ID == 3) { yield return StartCoroutine(Elements[5].GetComponent<ID3>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker)); }
else if(_ID == 4) { yield return StartCoroutine(Elements[5].GetComponent<ID4>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker)); }
else if(_ID == 5) { yield return StartCoroutine(Elements[5].GetComponent<ID5>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker)); }
    ....

如何获得这样的东西,或者至少可以工作:

int _ID = Attacker.GetComponent<BaseHeroStats>().ID_Model;
yield return StartCoroutine(Elements[5].GetComponent("ID" + _ID).StartAttack(EnemysInBattle, HeroesInBattle, Attacker));

【问题讨论】:

    标签: c# unity3d coroutine


    【解决方案1】:

    你不能在没有反射的情况下执行此操作,这会很慢,具体取决于执行的频率。

    为了简化您的代码,您必须使用Dictionary 或提供一种将_ID 转换为您的函数的方法。由于您要让出每个协程函数调用,因此您必须将每个函数存储为 IEnumerator 以便您可以让出它。

    字典:

    Dictionary<int, IEnumerator> idToDict = new Dictionary<int, IEnumerator>();
    

    将 ID 及其函数添加到字典的函数。从AwakeStart 函数调用此函数。

    void InitIDs()
    {
        idToDict.Add(1, Elements[5].GetComponent<ID1>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker));
        idToDict.Add(2, Elements[5].GetComponent<ID2>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker));
        idToDict.Add(3, Elements[5].GetComponent<ID3>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker));
        idToDict.Add(4, Elements[5].GetComponent<ID4>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker));
        idToDict.Add(5, Elements[5].GetComponent<ID5>().StartAttack(EnemysInBattle, HeroesInBattle, Attacker));
    }
    

    要使用它,请检查Dictionary 中的_ID 值。如果存在,则执行与之配对的协程函数,然后像在原始代码中一样生成每个函数:

    int _ID = Attacker.GetComponent<BaseHeroStats>().ID_Model;
    
    IEnumerator action;
    //Check if the function name exist, start it then yield it
    if (idToDict.TryGetValue(_ID, out action))
    {
        //Execute the approprite code
        yield return StartCoroutine(action);
    }
    

    编辑:

    另一种选择是将您的_ID 替换为string。该字符串应该包含脚本的名称。然后您可以使用反射和dynamic 关键字来调用coroutine 函数。所以,int _ID 现在应该是 string _ID,其中包含脚本的名称。这也意味着BaseHeroStats 类中的ID_Model 变量现在应该是string

    例如这样的:

    string _ID = "ID2";
    Type type = Type.GetType(_ID);
    Component ids = GetComponent(type);
    dynamic val = Convert.ChangeType(ids, type);
    StartCoroutine(val.StartAttack());
    

    或者在你自己的代码示例中:

    string _ID = Attacker.GetComponent<BaseHeroStats>().ID_Model;
    
    Type type = Type.GetType(_ID);
    Component ids = Elements[5].GetComponent(type);
    dynamic val = Convert.ChangeType(ids, type);
    yield return StartCoroutine(val.StartAttack(EnemysInBattle, HeroesInBattle, Attacker));
    

    您必须启用 .NET 4.6 才能使用 dynamic 关键字。请参阅this 帖子。这应该可以,但使用此代码的字典版本,因为它更快。

    【讨论】:

    • 尊敬的哦,非常感谢您的工作!但关键是减少行数,但最后代码变得更复杂,行数变得更多..但你的例子会发现用处)thx
    • 我很抱歉我的英语不好
    • ID1 ID2 ID3 ID4 ID5 - 是位于空对象上的类。 Elements[5](这些文件中的每一个都包含一个单独的英雄机械化。)在每个类中都有public IEnumerator StartAttack(...) {}。现在你需要让你的角色开始移动并等待结束,通过 yield return yield return StartCoroutine(Elements[5].GetComponent(_ID)().StartAttack(EnemysInBattle, HeroesInBattle, Attacker)); AND - _ID 自己回答了战斗中将涉及哪些机制
    • 对不起,我可能没有完全回答你的问题,也许会更清楚link
    • 您的链接使我们能够了解正在发生的事情。我删除了我的数组 EDIT。请阅读新的编辑。它应该能够做到这一点。如果有问题请告诉我。
    猜你喜欢
    • 2011-07-30
    • 2017-11-27
    • 2011-04-10
    • 2016-04-22
    • 2020-08-20
    • 2015-08-13
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多