Welcome back to day 29!
Yesterday we finished creating our final enemy that we’re going to use for the game.
Now that we have everything ready, it’s time to use them!
After finishing the spawn system and played the game for a bit, I noticed a small problem.
Sometimes when we shoot, the enemy doesn’t get hit. This becomes obvious when we try to switch the health of our enemy to be 1.
Our goals today are:
- Start spawning all 3 of our enemies
- Fix the shooting bug
Without any delays, let’s get started!
Step 1: Spawn our new enemies
Setting up the spawning system with our new enemies is simple, we already have the SpawnManager script to take care of spawning enemies every wave.
Let’s add them in!
In our hierarchy, look at GameManager > SpawnManager and to find our SpawnManager script.
Set our Waves size to be 3.
We want to spawn:
- 5 Knights at Wave 1
- 5 Bandits at Wave 2
- 5 Zombie at Wave 3
When we’re done, we’ll have something like this:
Now we can play the game and we’ll be able to fight all of our new enemies on the map!
Here might be something we’ll see!
You might notice that after we win, our gun doesn’t stop shooting and our shooting sound doesn’t stop.
Not today, but some other day, we will go in and disable all of those when the player wins.
Step 2: Solving the Mystery Missing Shot
Now that we’re spawning enemies and playing the game, we might encounter a very weird problem.
When we’re shooting an enemy, sometimes they don’t get hit.
I’m not talking about a long distance either, I’m talking very close proximity. What’s happening?
After digging around for a bit, I found the problem: our raycast is still hitting the mesh collider of our dead enemies.
As we have discussed in Day 20 the Mesh Colliders that we attach to our enemy doesn’t follow the form of our enemies. They’re just still there, as you can see from the image above.
What’s happening here is that even though we defeated our enemies, their mesh collider is blocking our shots from hitting other existing enemies.
But it’s okay, we can fix this. We must disable all colliders attached to the enemy when they die.
Step 2.1: Disabling our Colliders in Code
Now, let’s think, where would we know when the enemy is dead? In the EnemyAttack script!
In EnemyAttack we have a function called Death() that takes care of everything when the enemy dies.
Let’s use that:
using UnityEngine;
public class EnemyHealth: MonoBehaviour
{
public float Health = 100;
public AudioClip[] HitSfxClips;
public float HitSoundDelay = 0.5f;
private SpawnManager _spawnManager;
private Animator _animator;
private AudioSource _audioSource;
private float _hitTime;
void Start()
{
_spawnManager = GameObject.FindGameObjectWithTag("SpawnManager").GetComponent<SpawnManager>();
_animator = GetComponent<Animator>();
_hitTime = 0f;
SetupSound();
}
void Update()
{
_hitTime += Time.deltaTime;
}
public void TakeDamage(float damage)
{
if (Health <= 0) { return; } Health -= damage; if (_hitTime > HitSoundDelay)
{
PlayRandomHit();
_hitTime = 0;
}
if (Health <= 0)
{
Death();
}
}
private void SetupSound()
{
_audioSource = gameObject.AddComponent<AudioSource>();
_audioSource.volume = 0.2f;
}
private void PlayRandomHit()
{
int index = Random.Range(0, HitSfxClips.Length);
_audioSource.clip = HitSfxClips[index];
_audioSource.Play();
}
private void Death()
{
_animator.SetTrigger("Death");
_spawnManager.EnemyDefeated();
foreach (Collider collider in GetComponentsInChildren<Collider>())
{
collider.enabled = false;
}
}
}
New Variables Used
None
Walking Through the Code
There’s only one major change that we did and that’s in Death() where search through all of the enemy’s child game objects looking for any collider component. If a collider is found, we would just disable it.
One interesting thing to note is that we’re looking for anything of type Collider. We’re more used to finding something of exact type, for example, GetComponent<SpawnManager>();
However, taking advantage of the fact that all of the Colliders: Box Collider, Mesh Collider, Capsule Collider, etc all extend from the Collider parent class, they’re all considered of type Collider. What that means is that we can do what we did in Death() and look for anything that is of type Collider or inherits the class.
Now after we added the code, if we play the game, we’ll see that dead enemies no longer have their Colliders on anymore:
There are things that are sometimes better off staying dead.
Conclusion
That’s it for today! Today, we incorporated the rest of our enemies to the game and we even went in to fix “ghost” mesh colliders that prevented us from shooting properly.
I think we’re going to work on one more feature before I start moving on to the actual VR portion of this series, and that’s making a point system!
In our current game, we win and that’s it. There’s no replay value at all!
Tomorrow we’re going to start making this game more interesting by adding a scoring system!
With that all being said, it’s getting late, I’m headed out!
Source: Day 29
Visit the 100 Days of Unity VR Development main page.
Visit our Homepage
To get your mesh collision to deform in Unity you will have to either destroy and re-create it each frame, or you will have to replace the Unity collision system with your own.
The problem you have is that the mesh collider uses the original mesh and stays that way. So even when you animate the collider will always look like that.
The slow update of recreating the collisions at run time is why we re-create the collisions using primitives like I showed you. That way you can parent each part to a bone and it will deform with the character; solving this little problem you had.
Then again, games is about solving problems and you did solve this one.
The spawn manager is well made, liked that a lot.