In this post, we will add the Magnet Power-Up when collected and implement the magnet power-up.
Welcome to Day 86! After two or so posts talking about making the power-up magnet, we’re finally at the point where we have the infrastructure to write the magnet power up. I Promise!
For our plan of action today, we only have one goal and that is to:
- Add the Magnet Power-Up when collected
- Implement the magnet power-up
This might look like a short list, but we’re still going to need to make quite a bit of script changes, but it’s nothing that we can’t handle!
Let’s get started!
Step 1: Add the Magnet Power-Up to our Player State
Step 1.1: Add our Power-Up to the Plane Collider Script
Like how we collect a coin on collision, we need to have some logic that handles colliding against the magnet power-up.
We need to go to our Plane Collider script and add that logic in.
Here’s what we have now:
using UnityEngine;
public class PlaneCollider : MonoBehaviour
{
public GameObject PlaneObject;
public GameObject Explosion;
void OnTriggerEnter(Collider other)
{
print(other + " name " + other.name);
switch (other.tag) {
case "Coin":
CoinCollision(other);
break;
case "Magnet":
MagnetCollision(other);
break;
default:
CheckUnTaggedCollision(other);
break;
}
}
private void CoinCollision(Collider other) {
Coin coin = other.GetComponent<Coin>();
coin.Collect();
GameManager.Instance.CollectCoin();
}
private void MagnetCollision(Collider other)
{
PlayerManager.Instance.AddPowerUp(PlayerManager.PowerUpType.Magnet);
Magnet magnet = other.GetComponent<Magnet>();
magnet.Collect();
}
private void CheckUnTaggedCollision(Collider other) {
if (other.name.Contains("Cube")) {
EnemyCollision();
}
}
private void EnemyCollision()
{
Instantiate(Explosion, PlaneObject.transform.position, Quaternion.identity);
Destroy(PlaneObject);
PlayerManager.Instance.GameOver();
GameUIManager.Instance.GameOver(gameObject);
CameraManager.Instance.GameOver();
}
}
Walking Through the Code
There’s not much difference from what we do when we collide against a magnet power-up vs when we collide against a coin.
- We detect if we collided against the magnet power-up by checking the tag that we set in the previous day to see if it’s “
Magnet
”. - If it is
Magnet
, we call MagnetCollision()
, which we add a Magnet Power-up to our PlayerManager
and get rid of the magnet game object from the game. At this point, we don’t have a Magnet
script like we do in a Coin
script. We need to make one, as it stands now, our game won’t build.
Alternatively, we could have just removed the object inside the Plane Collider script, however if we want to play sound effects like what we do with coins, it would make sense to make another script that would take care of it.
Step 1.2: Create the Magnet Script
The next thing we need to do is make the magnet script.
- Put our magnet prefab back into the game.
- In the inspector, add a new script called
Magnet
.
Here’s what our Magnet
script will look like. It looks very similar to the Coin
script, because I mostly copied and pasted it:
using UnityEngine;
using System.Collections;
public class Magnet : MonoBehaviour
{
public AudioClip CollectMagnetSFX;
private SoundManager _soundManager;
void Start()
{
_soundManager = GetComponent<SoundManager>();
}
public void Collect()
{
StartCoroutine(RemoveGameObject());
}
private IEnumerator RemoveGameObject()
{
yield return new WaitForSeconds(0.1f);
Destroy(gameObject);
}
}
I won’t comment too much on it since it’s almost an exact copy of the coin
script, however I will point out that I renamed the sound effect that we give it and I made sure we don’t play any sound effects when we collect the magnet.
We will investigate this some other day.
With this, our game will now builds and if we run into a Magnet
power-up, we will collect it!
Pro tip: Instead of playing the game to find one, just drag and drop the prefab to be in front of the plane and collect it there.
Step 2: Implementing the Magnet Effect
We are finally here!
We:
- Added a magnet power-up asset
- Make it spawn in our game
- Added the necessary code to support getting a power-up
Now it’s time to finally code up a magnet effect!
How do we do it? It’s not actually too hard to do! Here’s our action plan to make it:
- We need to add a collider that will detect if we’re within a certain distance to coins.
- We need to modify our coin script to follow the player until the player collects the coin.
Once we have these two small changes, we should be able to get exactly what we are looking for.
Step 2.1: Detecting a Coin to Pickup
To detect coins for our magnet, we need to use a collider, we already have a Capsule Collider on our plane, which will make this confusing when trying to figure out if we are colliding against
- Create a new Game Object called Magnet Collider game object.
- Add a Sphere Collider to it.
- For the Sphere Collider make it a Trigger, set the Center to be (0, -1, 0) and change the Radius to be
- Add a Rigid Body component to the game object and disable gravity and enable Is Kinematic. This is necessary for us to be able to detect collision.
- Add a script called Magnet Collider to our game object.
What we’re going to do is we’re going to create a Magnet Collider game object that we will attach to our plane whenever we have the magnet power-up.
This game object will be the code that we’ll use to bring the coin towards us.
Here’s what the script looks like:
using UnityEngine;
public class MagnetCollider : MonoBehaviour {
void OnTriggerEnter(Collider other)
{
switch (other.tag)
{
case "Coin":
Coin coin = other.GetComponent<Coin>();
coin.Follow(gameObject.transform.parent.gameObject);
break;
}
}
}
Walking Through the Code
This is like the Plane collider script we have. We use OnTriggerEnter()
to detect when we run into a coin. With the coin script, we will call Follow()
(which we haven’t implemented yet) and pass in the parent game object, specifically this will be the Player
game object that we see in our project hierarchy. In theory, after this, the coin will start moving towards the player.
Step 2.2: Add the Magnet Collider Game Object to our Plane.
Now that we have a way for us to keep track of our magnet power-up, we need to add it our plane game object.
The best place to add the game object is when we collect the game object in the first place. Specifically in the PlayerManager
code where we add our power up.
Here’s what it looks like now:
using UnityEngine;
using System.Collections.Generic;
public class PlayerManager : MonoBehaviour
{
public static PlayerManager Instance;
public enum PlayerState { Alive, Dead }
public GameObject Player;
public GameObject MagnetCollider;
public enum PowerUpType { Magnet }
private Dictionary<PowerUpType, PowerUp> powerUpDictionary;
private float powerUpDuration = 15f;
private List<PowerUpType> itemsToRemove;
public PlayerState CurrentState
{
get { return _currentState; }
private set { _currentState = value; }
}
private PlayerState _currentState;
void Start ()
{
if (Instance != null)
{
Destroy(gameObject);
return;
}
Init();
}
void Update()
{
foreach (KeyValuePair<PowerUpType, PowerUp> entry in powerUpDictionary)
{
entry.Value.Duration -= Time.deltaTime;
if (entry.Value.Duration <= 0)
{
itemsToRemove.Add(entry.Key);
}
}
foreach (PowerUpType powerUpType in itemsToRemove)
{
switch (powerUpType)
{
case PowerUpType.Magnet:
Transform magnetCollider = Player.transform.Find
("Magnet Collider(Clone)");
print(magnetCollider);
Destroy(magnetCollider.gameObject);
magnetCollider = null;
break;
}
powerUpDictionary.Remove(powerUpType);
}
itemsToRemove.Clear();
}
private void Init()
{
Instance = this;
CurrentState = PlayerState.Alive;
powerUpDictionary = new Dictionary<PowerUpType, PowerUp>();
itemsToRemove = new List<PowerUpType>();
}
public void GameOver()
{
CurrentState = PlayerState.Dead;
}
public void AddPowerUp(PowerUpType powerUpType)
{
switch (powerUpType)
{
case PowerUpType.Magnet:
if (powerUpDictionary.ContainsKey(powerUpType))
{
break;
}
Instantiate(MagnetCollider, Player.transform.position,
Quaternion.identity, Player.transform);
break;
}
powerUpDictionary[powerUpType] = new PowerUp(powerUpDuration);
}
public bool ContainsPowerUp(PowerUpType powerUpType)
{
return powerUpDictionary.ContainsKey(powerUpType);
}
}
Looking at the Fields
We introduced two game objects that we will use in our script:
public GameObject Player
– This is a reference to our Player
game object that we control public GameObject MagnetCollider
– This is the MagnetCollider
prefab that we’re going to create and remove in our Player
game object.
Walking Through the Code
The change we added in are at Update()
in AddPowerUp()
:
- In
AddPowerUp()
, if we add a Magnet Power-Up, we add the Magnet Collider to our Player game object. - In
Update()
, when our power up is over, if we’re moving a Magnet Power-Up, we would find and remove the Magnet Collider that the Player game object contains.
Setting Up the Script
The only thing we need to make this script workable is to:
- Drag the Player game object in the hierarchy into the Player slot in the PlayerManager script in the Manager object in the game hierarchy.
- Drag the MagnetCollider prefab we made into the Magnet Collider slot in the PlayerManager script in the Manager object in the game hierarchy.
With this, we will now add the MagnetCollider
whenever we get our power-up and it will go away whenever the time passes!
Step 2.3 Get the Coin to Follow the Player
We’re almost there! Currently, our code doesn’t build and that’s because we’re trying to call Follow()
on our Coin
script, which doesn’t have that function.
We’re going to go and implement this function and then we’ll finally have implemented our magnet follow functionality.
Here’s our Coin
script:
using UnityEngine;
using System.Collections;
public class Coin : MonoBehaviour
{
public AudioClip CollectCoinSFX;
private SoundManager _soundManager;
private GameObject _player;
private readonly int _speed = 30;
void Start()
{
_soundManager = GetComponent<SoundManager>();
}
void Update()
{
if (_player != null)
{
print("coin moving");
float step = _speed * Time.deltaTime;
transform.position = Vector3.MoveTowards
(transform.position, _player.transform.position, step);
}
}
public void Collect() {
_soundManager.PlaySFXClip(CollectCoinSFX);
StartCoroutine(RemoveGameObject());
}
public void Follow(GameObject player)
{
_player = player;
}
private IEnumerator RemoveGameObject()
{
yield return new WaitForSeconds(0.1f);
Destroy(gameObject);
}
}
Looking at the Fields
private GameObject _player
– This field will hold a reference to the player that we will be given from Follow()
. It will be used to move the coin towards the player. private readonly int _speed = 30
– This field decides how fast the coin will move towards the player.
Walking Through the Code
- We implement
Follow()
which we previously called. All it does is that it sets _player
to be player, which means now in Update()
we have some direction we can go towards. - In
Update()
, after we have a player, we can start moving our coin towards the player. There’s a helpful function from the Vector3
game object that I found from this forum thread that makes moving towards the player really easy. Similar to what we have done before, we get our current position, our destination, and then frame by frame, we slowly move our current game object closer to the destination.
End of Day 86
Once we’re finished, we’ll finally have some form of Magnet Power-Up available to be used.
Here’s a simple gameplay of it. Notice that the coins are moving towards you? Neat!
At this point, we have our first power-up implemented, however there’s so much more that needs to be done. For one, we have no indication that we even grabbed a power-up and we have no idea when the power-up ends!
That’s why in the next post, we’re going to go and finish implementing the remaining sound and UI to help us make a more complete power-up experience. I’ll see you then!
Day 85 | 100 Days of VR | Day 87
Home
CodeProject
The post Day 86 of 100 Days of VR: Endless Flyer – Implementing Magnet Effect in Unity appeared first on Coding Chronicles.