Welcome to a very special day of my 100 days of VR. Day 10! That’s right. We’re finally in the double digits!
It’s been an enjoyable experience so far working with Unity, especially now that I know a bit more about putting together a 3D game now.
We haven’t made it into the actual VR aspects of the game, but we were able to get *some* foundational skills for Unity, which I’m sure will help translate into the skills needed to create a real VR experience.
We’re starting to get the hang of what we can use in Unity to make a game. Yesterday, we created the beginning of the shooting mechanism.
Currently, whenever we hit something, we just print out what we hit. Today we’re going to go in and create an enemy player that we can shoot and make some fixes.
Updating the Shooting Code
The first thing I would like to fix is that when we shoot, we shoot at whatever our cursor is pointing at, which is kind of weird.
Looking the cursor to the middle
This can be easily fixed by adding:
Cursor.lockState = CursorLockMode.Locked;
To Start() in our PlayerShootingController script
We’ll have something like this:
void Start () {
_camera = Camera.main;
_particle = GetComponentInChildren<ParticleSystem>();
Cursor.lockState = CursorLockMode.Locked;
}
Now when we try to play the game, our cursor will be gone. It’ll be in the middle of the screen, we just can’t see it.
Adding a Crosshair
At this point, we want some indicator to show where our “center” is.
To do this, we’re going to create an UI crosshair that we’ll put right in the middle.
In the hierarchy, add an Image which we will call Crosshair. By doing this Unity will also create a Canvas for us. We’ll call that HUD.
By default, our crosshair is already set in the middle, but it’s too big. Let’s make it smaller. In the Rect Transform, I set our image to have Width and Height 10, 10.
You should have something like this now:
Before we do anything else, we need to make sure that our mouse collider doesn’t send a raycast onto our UI elements.
In HUD, attach a Canvas Group component and from there, uncheck Interactable and Blocks Raycasts. As you might recall, the Canvas Groupcomponent will allow us to apply these 2 settings to its children without us having to manually do it ourselves.
Go ahead and play around with it. If we observe our console, whenever we fire we hit where our little “crosshair” is located at.
Creating our Enemy
So now we fixed our cursor to be the center, the next thing we need to do is to create an enemy.
We’ll improve upon this, but for now, let’s create our first enemy! A cube!
Add a Cube to your hierarchy, name it Enemy, and then drag it near our player.
Boom! First enemy!
Now currently, nothing really happens when you shoot at it, so let’s fix it by adding an enemy health script. We’ll call it EnemyHealth
Here’s what the code looks like:
using UnityEngine;
public class EnemyHealth : MonoBehaviour
{
public float Health = 10;
public void TakeDamage(float damage)
{
Health -= damage;
if (Health <= 0)
{
Destroy(gameObject);
}
}
}
It’s relatively simple:
- We have our health
- We have a public function that we’ll call our player hits the enemy that’ll decrease the enemies HP
- When it reaches 0, we make our enemy disappear
Now before we update our script, let’s make some optimizations to our raycast.
Go to our Enemy game object and then set its layer to Shootable if it doesn’t exist (which it most likely doesn’t), create a new layer, call it Shootable, and then assign it to the Enemy layout.
Now let’s go back to our PlayerShootingController and grab the EnemyHealth script that we just created and make them take damage:
using UnityEngine;
public class PlayerShootingController : MonoBehaviour
{
public float Range = 100;
private Camera _camera;
private ParticleSystem _particle;
private LayerMask _shootableMask;
void Start () {
_camera = Camera.main;
_particle = GetComponentInChildren<ParticleSystem>();
Cursor.lockState = CursorLockMode.Locked;
_shootableMask = LayerMask.GetMask("Shootable");
}
void Update () {
if (Input.GetMouseButton(0))
{
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit = new RaycastHit();
if (Physics.Raycast(ray, out hit, Range, _shootableMask))
{
print("hit " + hit.collider.gameObject);
_particle.Play();
EnemyHealth health = hit.collider.GetComponent<EnemyHealth>();
if (health != null)
{
health.TakeDamage(1);
}
}
}
}
}
The changes we’ve done is very similar to what we have seen before with Survival Shooter, but here’s the addition that we added:
-
We created our LayerMask for our Shootable layer and passed it into our Raycast function
- Note, I tried to use an int at first to represent our LayerMask, but for some reason, the Raycast ignored the int. From searching around online, I found that instead of using the int representation, we should just try the actual LayerMask object. When I gave that a try, it worked…. So yay?
- Next, when we hit an object, which at this point, can only be Enemy, we grab the EnemyHealth script that we added and then we make the enemy take 1 damage. Do this 10 times and the enemy will die.
Now with this script attached to our enemy, shoot our cube 10 times (which should happen really fast), and then BOOM, gone.
Conclusion
And that’s about as far as I got for Day 10! Today was a bit brief, because I didn’t get much time to work, but I think we made some good progress!
We created the basis for an enemy and added a basic crosshair UI that we can use. Tomorrow, I’m going to start looking into seeing how to add an enemy from the Unity Asset Store into the game.
Until then, I’ll see you all in day 11!
Original Day 10
Visit the 100 Days of VR main page