Jump to content
  • entries
    44
  • comments
    19
  • views
    2315

Day 38 of 100 Days of VR: Creating a VR First Person Shooter I

Josh Chang

1000 views

Welcome to Day 38! Today, we’re going to talk about the limitations of mobile VR and make some changes in our game to fix things.

We’ve already started to fix some things, specifically adding event triggers to our enemies, but there’s still many more things to solve!

Here’s a quick list of things I want to tackle from what we encountered 2 days ago:

From a technical limitation:

  1. We can’t move
  2. We only have one input which is clicking

Some actual technical problems:

  1. The enemies are all black color
  2. We don’t have any of our UI’s anymore

We’re going to address these problems over the next couple of days.

Today, we’re going to focus on the technical limitations of Mobile VR, today’s priorities are:

  1. Discussing how to change our game design to accommodate our new limitations
  2. Implementing our new designs

Edit, Important Note:

After playing around with the Cardboard in Unity today and looking at this article about Google Cardboard’s inputs.

It seems that we don’t have to use Google VR SDK. Unity already has most of the internal integration necessary to make a VR app

Everything we had already works, the reason why there I initially thought there was a problem is, because of how we did raycasting.

Specifically, our raycasting code targeted where our mouse/finger was touching, not the middle of the screen! More on this later.

Step 1: Changing the Game to Fit our Mobile Limitations

Like mentioned before, in the Google Cardboard, we have 3 limitations:

  1. We can’t move our characters position
  2. We only have tapping as an input to interact with the game
  3. Our cursor will always be in the middle of the screen

Even for the Daydream Viewer, we will have the first 2 limitations.

However, with the new Daydream Standalone device coming out, we’ll have World Space, finally allowing us to track the player’s movements without requiring external devices like what the Vive does!

Anyways, back on topic.

Considering these 3 limitations, here are my thoughts of what needs to be changed in our game:

  1. Because we can’t move, we should place our character in a more centered location for the enemies to reach us
  2. Because we can no longer run away, we should make the enemies weaker so that we don’t get swarmed
  3. Because we only have one input, we can shoot, but we can’t reload, we should get rid of the reload system

Essentially, we’re going to create a shooter with our player in the center with enemies coming from all around us.

Step 2: Implementing Our New Designs

Now that we have everything we want to do planned, let’s get started in the actual implementation!

Step 2.1: Placing the Character in the Middle

Let’s place the character in the middle of where our spawn points are set.

After playing around with it, I think the best spot would be at Position: (100, 1, 95)

center-location-1024x394.png

  1. Select Player in our hierarchy.
  2. In the Transform component, set our Position to be X: 100, Y: 1, Z: 95

Step 2.2: Making the Enemies Weaker

Next up, let’s make the enemies weaker.

In the Enemy Health script component attached to our Knight, Bandit, and Zombie prefab, let’s change their health value.

In order of our health, the order of size from largest to smallest is: Zombie > Knight > Bandit. Let’s set the health to be:

  1. Zombie: 4 HP
  2. Knight: 2 HP
  3. Bandit: 1 HP

Here’s how we change our health:

  1. In Assets > Prefabs select our prefabs, in this case, let’s choose Zombie.
  2. In the Inspector, select the Enemy Health (Script) component and change Health to be 4

change-zombie-health-to-4.png

Do the same change with the other 2 prefabs.

Step 2.3: Remove our ammo system

Now it’s time to back to our Player Shooting Controller (Script) Component that we disabled yesterday.

I want to keep the animation and sound effects that we had when shooting our gun, however, I’m going to get rid of the ammo and the need to reload.

Here are my changes:

using UnityEngine;
using System.Collections;

public class PlayerShootingController : MonoBehaviour
{
    public float Range = 100;
    public float ShootingDelay = 0.1f;
    public AudioClip ShotSfxClips;
    public Transform GunEndPoint;
    //public float MaxAmmo = 10f;

    private Camera _camera;
    private ParticleSystem _particle;
    private LayerMask _shootableMask;
    private float _timer;
    private AudioSource _audioSource;
    private Animator _animator;
    private bool _isShooting;
    //private bool _isReloading;
    //private LineRenderer _lineRenderer;
    //private float _currentAmmo;
    //private ScreenManager _screenManager;


    void Start () {
		_camera = Camera.main;
	    _particle = GetComponentInChildren<ParticleSystem>();
	    Cursor.lockState = CursorLockMode.Locked;
	    _shootableMask = LayerMask.GetMask("Shootable");
	    _timer = 0;
        SetupSound();
        _animator = GetComponent<Animator>();
        _isShooting = false;
        //_isReloading = false;
        //_lineRenderer = GetComponent<LineRenderer>();
        //_currentAmmo = MaxAmmo + 10;
        //_screenManager = GameObject.FindWithTag("ScreenManager").GetComponent<ScreenManager>();
    }
	
	void Update ()
	{
	    _timer += Time.deltaTime;

	    // Create a vector at the center of our camera's viewport
	    //Vector3 lineOrigin = _camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 0.0f));

	    // Draw a line in the Scene View  from the point lineOrigin in the direction of fpsCam.transform.forward * weaponRange, using the color green
	    //Debug.DrawRay(lineOrigin, _camera.transform.forward * Range, Color.green);

        if (Input.GetButton("Fire1") && _timer >= ShootingDelay /*&& !_isReloading && _currentAmmo > 0*/)
	    {
            Shoot();
	        if (!_isShooting)
	        {
	            TriggerShootingAnimation();
	        }
	    }
        else if (!Input.GetButton("Fire1") /*|| _currentAmmo <= 0*/)
	    {
            StopShooting();
	        if (_isShooting)
	        {
	            TriggerShootingAnimation();
            }
	    }

	    /*if (Input.GetKeyDown(KeyCode.R))
	    {
	        StartReloading();
	    }*/
	}

    private void StartReloading()
    {
        _animator.SetTrigger("DoReload");
        StopShooting();
        _isShooting = false;
        //_isReloading = true;
    }

    private void TriggerShootingAnimation()
    {
        _isShooting = !_isShooting;
        _animator.SetTrigger("Shoot");
        //print("trigger shoot animation");
    }

    private void StopShooting()
    {
        _audioSource.Stop();
        _particle.Stop();
    }

    public void Shoot()
    {
        //print("shoot called");
        _timer = 0;
        Ray ray = _camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));//_camera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit = new RaycastHit();
        _audioSource.Play();
        _particle.Play();
        //_currentAmmo--;
        //_screenManager.UpdateAmmoText(_currentAmmo, MaxAmmo);

        //_lineRenderer.SetPosition(0, GunEndPoint.position);
        //StartCoroutine(FireLine());

        if (Physics.Raycast(ray, out hit, Range, _shootableMask))
        {
            print("hit " + hit.collider.gameObject);
            //_lineRenderer.SetPosition(1, hit.point);
            //EnemyHealth health = hit.collider.GetComponent<EnemyHealth>();
            EnemyMovement enemyMovement = hit.collider.GetComponent<EnemyMovement>();
            if (enemyMovement != null)
            {
                enemyMovement.KnockBack();
            }
            /*if (health != null)
            {
                health.TakeDamage(1);
            }*/
        }
        /*else
        {
            _lineRenderer.SetPosition(1, ray.GetPoint(Range));
        }*/
    }

  
    // called from the animation finished
    /*public void ReloadFinish()
    {
        _isReloading = false;
        _currentAmmo = MaxAmmo;
        _screenManager.UpdateAmmoText(_currentAmmo, MaxAmmo);
    }*/

    private void SetupSound()
    {
        _audioSource = gameObject.AddComponent<AudioSource>();
        _audioSource.volume = 0.2f;
        _audioSource.clip = ShotSfxClips;
    }

    public void GameOver()
    {
        _animator.SetTrigger("GameOver");
        StopShooting();
        print("game over called");
    }
}

I’ve kept what I commented out, here’s the clean version of our script.

using UnityEngine;
using System.Collections;

public class PlayerShootingController : MonoBehaviour
{
    public float Range = 100;
    public float ShootingDelay = 0.1f;
    public AudioClip ShotSfxClips;
    public Transform GunEndPoint;

    private Camera _camera;
    private ParticleSystem _particle;
    private LayerMask _shootableMask;
    private float _timer;
    private AudioSource _audioSource;
    private Animator _animator;
    private bool _isShooting;

    void Start () {
		_camera = Camera.main;
	    _particle = GetComponentInChildren<ParticleSystem>();
	    Cursor.lockState = CursorLockMode.Locked;
	    _shootableMask = LayerMask.GetMask("Shootable");
	    _timer = 0;
        SetupSound();
        _animator = GetComponent<Animator>();
        _isShooting = false;
    }
	
	void Update ()
	{
	    _timer += Time.deltaTime;

        if (Input.GetButton("Fire1") && _timer >= ShootingDelay)
	    {
            Shoot();
	        if (!_isShooting)
	        {
	            TriggerShootingAnimation();
	        }
	    }
        else if (!Input.GetButton("Fire1"))
	    {
            StopShooting();
	        if (_isShooting)
	        {
	            TriggerShootingAnimation();
            }
	    }
	}

    private void TriggerShootingAnimation()
    {
        _isShooting = !_isShooting;
        _animator.SetTrigger("Shoot");
    }

    private void StopShooting()
    {
        _audioSource.Stop();
        _particle.Stop();
    }

    public void Shoot()
    {
        _timer = 0;
        Ray ray = _camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));
        RaycastHit hit = new RaycastHit();
        _audioSource.Play();
        _particle.Play();

        if (Physics.Raycast(ray, out hit, Range, _shootableMask))
        {
            print("hit " + hit.collider.gameObject);
            EnemyMovement enemyMovement = hit.collider.GetComponent<EnemyMovement>();
            if (enemyMovement != null)
            {
                enemyMovement.KnockBack();
            }
        }
    }

    private void SetupSound()
    {
        _audioSource = gameObject.AddComponent<AudioSource>();
        _audioSource.volume = 0.2f;
        _audioSource.clip = ShotSfxClips;
    }

    public void GameOver()
    {
        _animator.SetTrigger("GameOver");
        StopShooting();
        print("game over called");
    }
}

Looking through the Changes

We removed a lot of the code that was part of the reloading system.

We basically removed any mentions of our ammo and reloading, however, I kept the changes involved with the shooting animation, shooting sound effects, and shooting rate.

There were only 2 changes that were made:

  1. I changed the input we use to shoot from GetMouseButton to GetButton(“Fire1”), I believe this is the same thing, but I’m making the change anyways. Either option returns true when we’re touching the screen on our mobile device.
  2. I also changed our Ray from our raycasting system. Before casted a ray from where our mouse was located at, which before we fixed at the center. However, after we got rid of the code that fixed cursor to the middle, we needed a new way to target the middle. Instead of firing the raycast from our mouse, we now fire the raycast from the middle of our camera, which will fix our problem with our mobile device.

Go ahead and play the game now. We should be able to have a playable game now.

There are 2 things that will happen when we shoot:

  1. We’ll shoot a raycast and if it hits the enemy, they’ll be pushed back
  2. The enemies trigger event will detect that we clicked down on the enemy, so they’ll take some damage

At this point, we have a problem: if we were to hold down the screen, we’ll push the enemy back, but they’ll only be hit once! That’s because we only have that deals with an OnClick event, but not if the user is currently selecting them.

We’re going to fix this problem tomorrow, but I’ve done a lot of investigation work with raycasts now and want to take a break!

Step 2.4: Changing the ScreenManager script

One more thing we need to do before we leave.

The Unity compiler would complain about a missing reference with our ScreenManager, specifically with the MaxAmmo variable that we got rid of.

Let’s just get rid of it:

using UnityEngine;
using UnityEngine.UI;

public class ScreenManager : MonoBehaviour
{
    public Text AmmoText;

    void Start()
    {
        {
            PlayerShootingController shootingController = Camera.main.GetComponentInChildren<PlayerShootingController>();
            //UpdateAmmoText(shootingController.MaxAmmo, shootingController.MaxAmmo);
        }
    }

    public void UpdateAmmoText(float currentAmmo, float maxAmmo)
    {
        AmmoText.text = currentAmmo + "/" + maxAmmo;
    }
}

And we’re good to go! Technically speaking, we won’t be using this script anymore either.

Conclusion

And another day’s worth of work has ended! There’s a lot of things I learned about VR, such as: we don’t need ANYTHING that the Google VR SDK provides!

Unity as a game engine already provides us with everything we need to make a VR experience. Google’s SDK kit is more of a utility kit that help make implementation easier.

The TLDR I learned today is that we don’t have to be fixed on using Unity’s Raycasting script, we don’t need it. We can continue to use what we already have. However, for the sake of learning, I’m going to continue down re-implementing our simple FPS with the Google Cardboard assets!

We’ll continue tomorrow on Day 39! See you then!

Day 37 | 100 Days of VR | Day 39

Home



2 Comments


Recommended Comments

VR actually does have other input, you can move things around.

Using a Leap motion controller I was able to create a reloading function. I just had a box around the gun's hand grip and a smaller one attached to the clip's top. Once the two boxes intercept a reload animation plays.

This was easier than the "realistic" gun VR games and had none of that struggle to reload problems. 

Share this comment


Link to comment

That's a really interesting idea. I've never thought of using Leap motion controller. I've heard a lot about them, but I've never had the chance to play around with one. It'll definitely be on my bucket list of things to do!

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By Sergio Ronchetti
      Continuing to work on “Eldest Souls” (first article here!), I’ve begun familiarising myself with the workflow between Fmod and Unity, and the integration system. I know much of this will be pretty obvious to most, but I thought I’d share my thoughts as a complete beginner learning the ropes of sound designing. 
      The library of sounds that Fmod provides has been very useful, at least as reference points. I’ve still kept to my ethos of producing the sounds myself as much as possible. Having said that, Fmod gives you 50 free sounds with your download, and I’ve used a wooden crate smash, a drawbridge and electricity sound you can hear in the foley video below.
       
       
      The thing i found most useful was witnessing changes i made in Fmod being realised instantly in Unity. If a volume needed changing, or the timing of one of my effects was off, i can literally switch to Fmod and then back to Unity and immediately see the result of my alterations. It also seems apparent that using middleware such as this (or i've heard Wwise is also equally intuitive) grants the developer, and myself included, a great deal more flexibility and opportunity to edit sounds without going all the way back to a DAW, and bouncing down again. Needless to say, my workflow is so much faster because of it.
      I've also loved the randomised feature of Fmod, whereby any sound can be made to sound slightly different each time it is heard. Taking a footstep recording i made for example, I was able to add further authenticity of uneven footsteps by randomising the pitch and volume of each playback. 
       

       
      I used this technique when creating footsteps for the first major boss in the game called "The Guardian". A big, over-encumbered husk of a monster. I also had fun rummaging through the garage for old tools and metal components for the “Guardian” (the first boss) footsteps. See below!
       
       
      I also created a sword attack for our player, trying to sound different from the generic “woosh” I see in so many video games. I used a very “sharp” and abrasive sound to differentiate him from any enemies.
       
       
      On another note, I recently upgraded my microphone to a Rode NTG2 shotgun, which has been phenomenal. I haven’t had to worry about noise interfering with the clarity of my objects, whereas before with the sm58 I had to be clever with my EQ and noise reduction plugins.
      Important to note again that this still a “cheap” mic in comparison to most other products on the market, and all in all my entire setup is still very simple and affordable which I’m quite proud of. I’ve seen many musicians spend heaps of money on gear they don’t necessarily need. I much prefer being resourceful with less equipment, than to have more than I can understand or remember how to use.
      It’s forced me to understand every aspect and capability of my tools, which I believe is a principal that can be applied to any discipline.
       
      I have more fun little sound effect videos on my Instagram for those interested, where I post regular updates. Thanks for reading! (if you’ve made it this far)
       
      www.sergioronchetti.com
      INSTAGRAM
      fallenflagstudio.com
    • By Sergio Ronchetti
      BASICS IN SOUND DESIGNING FOR VIDEO GAMES
       
      Recently I joined the talented team at Fallen Flag Studio as the composer for their latest release "Eldest Souls" which consequently lead me into a field I have always dreamt of trying - sound design!
      Having no prior experience, I began watching a few online tutorials (if you want to learn from anyone make it Akash Thakkar from "Hyper Light Drifter"... what a guy!) and basically just testing stuff out i found around the house. Luckily my dad has a garage FULL of random crap to use.
      Before i continue, it's important to note that i DO NOT have fancy equipment, meaning anyone can try this. (my equipment is an sm58, focusrite scarlett interface and Logic Pro X plugins... that's it!)
      I started basic with some footsteps, which weren't all too difficult. Then I moved on to projectiles and a spear attack one of the bosses has. Below are a couple super short videos on my resulting attempts.
       
       
      Amazing how great a banjo sounds for that typical "woosh" sound! And if you're wondering, the paper was added to give some texture to the jab.
      I could be finding a lot of these sounds in libraries online (like the built-in ones that come with Fmod and Unity) but I've chosen not to, in order to produce authenticity and hopefully a more unique gameplay experience for players when the final product is put together.
       
      P.S. if you'd like to try the game and hear my hard work we'll be at EGX and several other conventions later this year, soon to be announced! Thanks for reading!
      www.sergioronchetti.com
      fallenflagstudio.com
       
      To those interested, there's an Alpha trailer of the game in question below.
       
       
    • By OConquestGame
      Hello there!
      I’m the creator and producer of an upcoming visual novel / video game. 
      My team and I are looking for artists (character and background), writers (experienced in writing relatable characters and witty dialogue), and programmers (familiar with unity and creating mini games). 
      Our team is a group of close friends looking to break the mold of the traditional visual novel and create something new and positive. This game will be highly promoted and be a great portfolio piece. Rates are negotiable!
      If you are interested please contact/message us today! OConQuestGame@gmail.com
    • By Kamal Wafi
      Hi there,
      i recently start learning unity and im working in my first game ,
       
      I was wondering if unity had functions to support the motion control effect (tilting screen to move character) you see
      in doodle jump (which is 2d game) ? If it exists, what are they called? and how it works ?

      Thanks
    • By Gafami
      Dear community,
      I would like inform you that "War IOM" v2 have been re-work graphics and added more feature to serve user experience.
      Here is my banner screenshot: 

      You can access to the website and play it directly on your phone (Chrome mobile, Safari iPhone, iPad) or your Laptop
      Link to play: https://www.iomgame.com/wariom/
      ++++ Game description: 
      The rule to win the game is very simple: buy the soldiers, defeat the enemy army and then destroys the flag. Try to use fireball to wipe out the enemy. 
      The game had the shop to buy new soldier, upgrade soldier and choose the team out. 
      Game data be stored on both user's device and server so never lost data again.
       
      ++++ Here is the look and feel of War IOM icon on your Home-screen phone

       
      Rumor: You can get double gem receive if you beat the mini boss at level 3. Also win level 3 will give you a lot of Gem, use it to buy new solider and upgrade your army!
      My facebook page: https://www.facebook.com/Iomgame-245553622715070/
       
      /******** Change log update 08/26 ********/
      -- Add new game play for level 6.

      -- Improve camera.
      -- Improve game performance.
      /******** Change log update 08/31 ********/
      -- Improve sound load time. No painful for waiting sound loading any more!
      /******** Change log update 19/09 ********/
      -- Add level 7 with new game play.
      Regards,
      Gafami
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!