0

Good afternoon, maybe my question will seem stupid to you! but I still can not find the answer! As if to reduce the code, all my attempts have sunk into the abyss, I just don’t know what to do = (

I have a lot string:

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)); }
    ....

how to get something like this, or at least working:

int _ID = Attacker.GetComponent<BaseHeroStats>().ID_Model;
yield return StartCoroutine(Elements[5].GetComponent("ID" + _ID).StartAttack(EnemysInBattle, HeroesInBattle, Attacker));
Programmer
  • 121,791
  • 22
  • 236
  • 328

1 Answers1

1

You can't do this without reflection which is slow depending on how often this is done.

To simplify your code, you have to use Dictionary or provide a way to translate the _ID to your function. Since you're yielding each coroutine function call, you have to store each function as IEnumerator so that you can yield it.

The Dictionary:

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

Function to add the IDs and it's functions to the Dictionary. Call this function from the Awake or Start function.

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));
}

To use it, check for the _ID value in the Dictionary. If it exist, execute the coroutine function paired with it then yield each one just like you did in your original code:

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);
}

EDIT:

Another option is to replace your _ID with string. That string should instead contain the name of the script. You can then use reflection and the dynamic keyword to call the coroutine function. So, int _ID should now be string _ID which contains the name of the script. This also means that the ID_Model variable in your BaseHeroStats class should now be a string.

For example something like this:

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

Or in your own code example:

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));

You must enable the .NET 4.6 to use the dynamic keyword. See this post. This should work but use the Dictionary version of this code because it's faster.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • 1
    Respected oh thank you so much, for the work! but the point was to reduce the number of lines, but in the end the code became more complicated and the number of lines became only more .. But your example will find a use) thx – Александр Любчик Oct 21 '18 at 20:02
  • I apologize for my bad English – Александр Любчик Oct 21 '18 at 21:40
  • `ID1` `ID2` `ID3` `ID4` `ID5` - are classes, which are located on an empty object. `Elements[5]` (Each of these files contains a separate mechanization of the hero.) In each of these classes there is`public IEnumerator StartAttack(...) {}`. Now you need to run your character to start moving and wait for the end, via **yield return** `yield return StartCoroutine(Elements[5].GetComponent(_ID)().StartAttack(EnemysInBattle, HeroesInBattle, Attacker));` AND - _ID himself answers which mechanics will be involved during the battle – Александр Любчик Oct 21 '18 at 22:04
  • I'm sorry, maybe I didn’t quite answer your question, maybe it will be clearer [link](https://jsfiddle.net/1q5ohe6z/1/) – Александр Любчик Oct 21 '18 at 22:51
  • Your link made it possible to understand what's going on. I removed my array EDIT. Please read the new EDIT. It should be able to do that. Let me know if there is a problem. – Programmer Oct 21 '18 at 23:31
  • Good day, today I'm already trying to put `NET 4.6` .. but unsuccessfully, I will still try .. my version `Patch 5.6.4p2` `Released: 9. November 2017` and I am making a game for android! Log: `error CS1980: Dynamic keyword requires (System.Runtime.CompilerServices.DynamicAttribute) to be defined. Are you missing System.Core.dll assembly reference?` – Александр Любчик Oct 22 '18 at 10:36
  • can you tell me whether or not can replace the line `dynamic val = Convert.ChangeType(ids, type);` namely => `dynamic` on something that will perform the same function? knowledge is power, not knowledge of torment – Александр Любчик Oct 22 '18 at 12:16
  • see this error [link](https://pastebin.com/PFszTPyX) life is pain =(( `Debug.Log(methInfo);` => `IEnumerator StartAttack(System.Collections.Generic.List 1[UnityEngine.GameObject], System.Collections.Generic.List 1[UnityEngine.GameObject], UnityEngine.GameObject)` – Александр Любчик Oct 22 '18 at 17:25
  • I wanted to see if you're paying attention to the code. Your `GetComponent(type)` should be be `Elements[5].GetComponent(type)`. The rest of the code should be the-same – Programmer Oct 22 '18 at 17:39
  • i did that because it returned null – Александр Любчик Oct 22 '18 at 17:43
  • see time create ) [link](https://pastebin.com/QmZvKTkW) I'm not sure that Google Translator translates the correct idea, but all the heroes cannot walk at once! gives an error, `yield return` i try.. – Александр Любчик Oct 22 '18 at 17:44
  • Whats the value of `_ID` ? – Programmer Oct 22 '18 at 17:45
  • all is well, my fault, the first move was the hero of ID4 and your function caused ID1 because I am a ram sorry my fault [link](https://pastenow.ru/a5af4deb40b8c4265bc111f29417f85c) they all walk at the same time) – Александр Любчик Oct 22 '18 at 17:54
  • Like I said in my answer, the value of `_ID` has to be one of the ID classes name such as "ID1", "ID2" and "ID3". It is currently returning 1,2,3,4,5. The `_ID` value has to match one of the class names otherwise reflection cannot find it. You have to change `ID_Model` to string and change the way you name it or take your current code and prefix "ID" in front of the ID variavle and you will the class name. For example, `string _ID = Attacker.GetComponent().ID_Model.ToString();` **then** _ID = "ID"+_ID`. However you do it is your business. – Programmer Oct 22 '18 at 17:55
  • Glad you fixed it. – Programmer Oct 22 '18 at 17:55
  • wow everything is like a clock, you are just GOD, with a capital letter. I hope when people will look for this they will find exactly your message! LOVE YOU )) – Александр Любчик Oct 22 '18 at 18:01