Reputation: 623
I'm trying to implement a system for powerups into my game, but not sure how to approach it. So far i have a powerup spawner, which instantiate a powerup prefab on a random location. Once picked up, it destroys itself and spawns on another location. The same prefab is used for all powers, and there is only one on the map at a time.
spawnLocations = GameObject.FindGameObjectsWithTag("spawnLocation");
Instantiate(powerup, spawnLocations[spawnRandom].transform.position, transform.rotation);
As for the powerups, when picked up it should remove the current power (if the player has one) and replace it with a new randomly selected. (No timers needed).
I made a couple of simple powerups:
public void SpeeedBoost(float speedMultiplied) {
var playerController = gameObject.GetComponent<PlayerController>();
playerController.speed = playerController.speed * speedMultiplied;
}
public void JumpBoost(float jumpPower) {
var playerJump = gameObject.GetComponent<PlayerJump>();
playerJump.jumpSpeed = playerJump.jumpSpeed * jumpPower;
}
+ maybe a change of weapon etc.
And they should be called like this:
private void OnTriggerEnter2D(Collider2D collision) {
if (collision.gameObject.tag == "powerup") {
// Remove current powerup and call a new random one
}
}
So i need some help here. How should I structure my powerups? And how do i call them randomly? Thinking of maybe using unityEvent somehow for this. Or maybe save each powerup as a prefab with its own script and swap them around (although feels a bit messy).
I'm a bit lost here, any suggestions/examples are appreciated. :)
Upvotes: 1
Views: 383
Reputation: 3576
You could enumerate the powerUps
public enum PowerUp
{
None, //default value
SpeedBoost,
JumpBoost,
//etc
}
Then create a reference to the current active powerUp
private PowerUp currentPowerUp;
So that afterwards, we can undo it's effect before assigning a new value
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "powerup")
{
switch (currentPowerUp)
{
case PowerUp.JumpBoost:
RemoveJumpBoost();
break;
case PowerUp.SpeedBoost:
RemoveSpeedBoost();
break;
}
do
{
//I set the minimum value to 1 to skip "None"
var nextPowerUp = (PowerUp)UnityEngine.Random.Range(1, System.Enum.GetValues(typeof(PowerUp)).Length);
}
while (nextPowerUp == currentPowerUp);
switch (nextPowerUp)
{
case PowerUp.JumpBoost:
AddJumpBoost();
break;
case PowerUp.SpeedBoost:
AddSpeedBoost();
break;
}
currentPowerUp = nextPowerUp;
}
}
Or you could also add a script to the powerUp prefab where you specify the aforementioned powerUp enum value, or even declare there on the OnDestroy event what to do. Or you could create a prefab for each powerUp type, and call the random generation before deciding which one to instantiate. It's for you to decide which solution seems cleanest and easiest to understand to you, they're all perfectly valid
Upvotes: 2
Reputation: 350
I think you could use ScriptAbleObjects for your PowerUps. It would have a reference to the prefab it spawns. To randomize it, I would store them in a List and calculate a random index to retrieve a random power up.
public class PowerUpObject : ScriptAbleObject
{
public GameObject Prefab;
}
public class PowerUpManager : Monobehaviour
{
public List<PowerUpObject> PowerUps;
public PowerUp GetRandomPowerUp()
{
if(PowerUps != null && PowerUps.Count > 0)
{
int randomIdx = Random.Range(0, PowerUps.Count);
return PowerUps[randomIdx];
}
// error case
Debug.Log("No PowerUps in List");
return null;
}
}
This is not complete but should give you the inspiration you need. You would have a manager GameObject holding all known powerUps in the game. You could request a random power up from it, and then use the Prefab member of the PowerUpObject to spawn the actual Prefab.
Also I recommend this Video: https://www.youtube.com/watch?v=CLSiRf_OrBk
Upvotes: 1