I have an array that I am shuffling and then assigning to buttons. Depending on the item in the array, the button will perform a different function. This is currently my code, and it works, but is extremely inelegant.
I am currently shuffling the array first, then assigning the first 2 items of the shuffled array to the button text, and then using if statements to check whether or not the string matches so that it will execute a specific code for that string.
There is definitely a better way to do this, but I can’t seem to figure it out.
public TextMeshProUGUI firstChoiceText;
public TextMeshProUGUI secondChoiceText;
public GameObject player;
public string[] upgrades =
{
"Speed Up",
"Fire Rate Up",
"Damage Up",
"Max Health Up"
};
public void Shuffle(string[] array)
{
for (int i = 0; i < array.Length; i++)
{
string tmp = array[i];
int rand = Random.Range(0, array.Length);
array[i] = array[rand];
array[rand] = tmp;
}
firstChoiceText.text = upgrades[0];
secondChoiceText.text = upgrades[1];
}
// Start is called before the first frame update
void Start()
{
Shuffle(upgrades);
}
public void FirstChoice()
{
Debug.Log("first choice clicked");
if (firstChoiceText.text == "Speed Up")
{
player.GetComponent<PlayerController>().playerSpeed += 1;
}
else if (firstChoiceText.text == "Fire Rate Up")
{
player.GetComponent<PlayerController>().fireRate -= 0.05f;
}
else if (firstChoiceText.text == "Damage Up")
{
player.GetComponent<PlayerController>().playerDamage *= 1.1f;
}
else if (firstChoiceText.text == "Max Health Up")
{
GameManager.maxHealth += 5;
player.GetComponent<PlayerController>().Heal(5);
}
Time.timeScale = 1;
gameObject.SetActive(false);
Shuffle(upgrades);
}
public void SecondChoice()
{
Debug.Log("second choice clicked");
if (secondChoiceText.text == "Speed Up")
{
player.GetComponent<PlayerController>().playerSpeed += 1;
}
else if (secondChoiceText.text == "Fire Rate Up")
{
player.GetComponent<PlayerController>().fireRate -= 0.05f;
}
else if (secondChoiceText.text == "Damage Up")
{
player.GetComponent<PlayerController>().playerDamage *= 1.1f;
}
else if (secondChoiceText.text == "Max Health Up")
{
GameManager.maxHealth += 5;
player.GetComponent<PlayerController>().Heal(5);
}
Time.timeScale = 1;
gameObject.SetActive(false);
Shuffle(upgrades);
}
>Solution :
One solution would be to create a Dictionary<string, Action<Player>> where your Action delegate corresponds to your string key and call the method via Action delegate based on the string key of the Dictionary, also moved your shuffle logic into it’s own private method to reduce code duplication:
//Dictionary to hold string key/Action delegate pairs
private Dictionary<string, Action<Player>> _actions = new Dictionary<string, Action<string>>
{
{"Speed Up", (player) => player.GetComponent<PlayerController>().playerSpeed += 1;},
{"Fire Rate Up", (player) => player.GetComponent<PlayerController>().fireRate -= 0.05f;}
{"Damage Up", (player) => player.GetComponent<PlayerController>().playerDamage *= 1.1f;},
{"Max Health Up", (player) => { GameManager.maxHealth += 5;
player.GetComponent<PlayerController>().Heal(5); } }
};
//You could reduce your First And Second Choice down to using the
//dictionary to call the cooresponding Action delegate:
public void FirstChoice()
{
Debug.Log("first choice clicked");
_actions[firstChoiceText.text](player);
DoShuffle();
}
public void SecondChoice()
{
Debug.Log("second choice clicked");
_actions[secondChoiceText.text](player);
DoShuffle();
}
//Moved this into a method to reduce repetitive code
private void DoShuffle()
{
Time.timeScale = 1;
gameObject.SetActive(false);
Shuffle(upgrades);
}