New Enemy Projectile: Mine

Adding velocity and direction to instantiated objects

Today we will share how we created a new enemy projectile.

Mine Projectile Logic Pseudocode

Mine that moves down slowly
If player shoots it
then it explodes
If player gets too close it explodes
and shoots projectiles in 8 directions

Mine Projectile Script

Our scripts only tell when to instantiate the projectile this way we can compose new enemy types. This is why we put all logic (like aiming) on the projectile behavior scripts.

We created a separate gameobject MineShard prefab that will be used for the 8 direction explosion of the mine.

Start()

[SerializeField] private float _DownSpeed = 1f;
[SerializeField] GameObject _mineShard;
[SerializeField] private float _shardSpeed = 3f;
private GameObject _player;
[SerializeField] private float _minDistance = 3f;

void Start()
{
_player = GameObject.FindGameObjectWithTag("Player");
if (_player == null)
{
Debug.LogError("EnemyMine.player is NULL");
}
}

Update()

Move the mine down
If the mine is off bottom screen
then destroy the mine

Check if Distance between Mine and Player is smaller then minimum distance
Then start for loop to spawn 8 mine shards
and each mine shard gets a different angle based on the loop index i when instantiated.
We got the best results when we used i * Mathf.Pi * 2f / (1/7f). To be honest don’t know why it’s around 1/7. This value was found by tweaking the number… A bit of randomness is added as well.

For each Mine Shard we get the Rigidbody2D component and add a velocity to it. Here the angle is used again to move the right direction. The precious angle was used to face the right direction.

Important: Quaternion x Vector ORDER MATTERS. If you try the other way around it won’t work.

Finally we destroy the mine after we instantiated 8 mine shards that we moved into 8 directions with velocity.

void Update()
{
transform.Translate(Vector3.down * _DownSpeed * Time.deltaTime);
if (transform.position.y < -10)
{
Destroy(gameObject);
}
if (Vector3.Distance(transform.position, _player.transform.position) <= _minDistance)
{
for (int i = 0; i < 8; i++)
{
float angle = i * Mathf.PI * 2f / (1/Random.Range(7f,8f));
GameObject mineShard = Instantiate(_mineShard, transform.position, Quaternion.AngleAxis(angle, Vector3.forward));
Vector3 movement = Quaternion.AngleAxis(angle, Vector3.forward) * new Vector3(0, _shardSpeed, 0); mineShard.GetComponent<Rigidbody2D>().velocity = movement;
}
Destroy(this.gameObject);
}
}

OnTriggerEnter2D

If Laser hits the Mine
Then destroy the Laser and the Mine

private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == “Laser”)
{
Destroy(other.gameObject);
Destroy(this.gameObject);
}
}

Mine Shard Script

Self destruct after 5 seconds
If mine shard colliders with player
then damage the player and destroy self

void Start()
{
Destroy(this.gameObject, 5f);
}

private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Player player = other.GetComponent<Player>();
player.Damage();
Destroy(this.gameObject);
}
}

VFX: Mine Projectile Simple Animation

Using the Record function in the animator we adjusted the scale of the mine. This animation will make the mine feel more alive.

Aspiring developer that’s self-learning Unity & C# to transition to a career with Unity. I got a passion for creating interactive experiences.