Today, we’re going to have a relatively short day! Today will perhaps be our final day working on this game before I move on to creating what I hope to be a complete game!
However, before I get ahead of myself, let’s finish today first!
Today, there are two things that I want to do:
- Fix our score and health UI on our game which broke
- Use Google’s Spatial Audio system! Let’s get to it!
Step 1: Re-Fixing the UI System
One important thing I completely forgot about when we duplicated and moved our gun from the gaze controller to our Daydream controller is that we forgot to change a couple of places to use our new UI element.
Let’s put our components back in the correct places.
There are 2 places that use our UI components:
PlayerHealth
ScoreManager
Let’s add these back in.
- In
GameManager
, find the GameManager
Drag and drop our new Score UI Text from Player > Main Camera > GvrControllerPointer > MachingGun_00 (1) > MachineGun_01 > Score into our Score slot. - In
Player
, we have our PlayerHealth
script. Drag and drop our new Health Bar Slider from Player > Main Camera > GvrControllerPointer > MachingGun_00 (1) > MachineGun_01 > Health Bar into our HealthBar slot.
With these added in, when we play our game again, we can see the time on our gun and our health.
Plus, now that we can individually move our weapon, it’s a much more pleasant experience with our UI. We no longer have our time and health on our page anymore. Now its location is based on our controller. Nice!
Step 2: Adding Spatial Audio to the Game
Looking at the documentation page, there are a couple of elements that are needed to make this work. We only need to do 2 things:
- Replace the
AudioListener
component in MainCamera
with GvrAudioListener
- Replace all
AudioSource
with GvrAudioSource
There’s also another prefab and script called GvrAudioRoom
that allows us to reflect sound as if we were in a room with varying levels of surface materials to bounce off sounds. We won’t be working with this today, but it’s there.
Let’s set everything up!
First, let’s add our GvrAudioListener
script:
- In the Hierarchy go to Player > Main Camera
- Click Add Component and select
- Note: We still need the old AudioListener
Now the more complex part. We’re going to have to go in and replace all the AudioSources
with GvrAudioSources
.
Looking at the source code, it doesn’t look like GvrAudioSources
inherits directly from Audio Source, rather, it’s more like a wrapper that has the same functions to call, and uses an AudioSource
component underneath along with its extra changes.
Luckily for us, we only use them in a couple of places and only in code. Specifically, in these scripts:
PlayerShootingController
EnemyMovement
EnemyAttack
EnemyHealth
I’ll be replacing all the AudioSource
:
PlayerShootingController.cs
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 GvrAudioSource _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<GvrAudioSource>();
_audioSource.volume = 0.2f;
_audioSource.clip = ShotSfxClips;
}
public void GameOver()
{
_animator.SetTrigger("GameOver");
StopShooting();
print("game over called");
}
}
EnemyAttack.cs
using UnityEngine;
public class EnemyAttack : MonoBehaviour
{
public FistCollider LeftFist;
public FistCollider RightFist;
public AudioClip[] AttackSfxClips;
private Animator _animator;
private GameObject _player;
private GvrAudioSource _audioSource;
void Awake()
{
_player = GameObject.FindGameObjectWithTag("Player");
_animator = GetComponent<Animator>();
SetupSound();
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject == _player)
{
_animator.SetBool("IsNearPlayer", true);
}
print("enter trigger with _player");
}
void OnTriggerExit(Collider other)
{
if (other.gameObject == _player)
{
_animator.SetBool("IsNearPlayer", false);
}
print("exit trigger with _player");
}
private void Attack()
{
print("attack called");
if (LeftFist.IsCollidingWithPlayer() || RightFist.IsCollidingWithPlayer())
{
print("enemy attacked the player");
PlayRandomHit();
_player.GetComponent<PlayerHealth>().TakeDamage(10);
}
}
private void SetupSound()
{
_audioSource = gameObject.AddComponent<GvrAudioSource>();
_audioSource.volume = 0.2f;
}
private void PlayRandomHit()
{
int index = Random.Range(0, AttackSfxClips.Length);
_audioSource.clip = AttackSfxClips[index];
_audioSource.Play();
}
}
EnemyHealth.cs
using System;
using UnityEngine;
using Random = UnityEngine.Random;
public class EnemyHealth : MonoBehaviour
{
public float Health = 100;
public AudioClip[] HitSfxClips;
public float HitSoundDelay = 0.1f;
private SpawnManager _spawnManager;
private Animator _animator;
private GvrAudioSource _audioSource;
private float _hitTime;
private Boolean _isEnter;
void Start()
{
_spawnManager = GameObject.FindGameObjectWithTag("SpawnManager").GetComponent<SpawnManager>();
_animator = GetComponent<Animator>();
_hitTime = 0f;
_isEnter = false;
SetupSound();
}
void Update()
{
_hitTime += Time.deltaTime;
if (Input.GetButton("Fire1") && _isEnter)
{
TakeDamage(1);
}
}
private void TakeDamage(float damage)
{
if (Health <= 0) { return; } if (_hitTime > HitSoundDelay)
{
Health -= damage;
PlayRandomHit();
_hitTime = 0;
}
if (Health <= 0)
{
Death();
}
}
private void SetupSound()
{
_audioSource = gameObject.AddComponent<GvrAudioSource>();
_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;
}
}
public void HealthEnter()
{
_isEnter = true;
print("enter");
}
public void HealthExit()
{
_isEnter = false;
print("exit");
}
}
EnemyMovement.cs
using UnityEngine;
using UnityEngine.AI;
public class EnemyMovement : MonoBehaviour
{
public float KnockBackForce = 1.1f;
public AudioClip[] WalkingClips;
public float WalkingDelay = 0.4f;
private NavMeshAgent _nav;
private Transform _player;
private EnemyHealth _enemyHealth;
private GvrAudioSource _walkingAudioSource;
private Animator _animator;
private float _time;
void Start ()
{
_nav = GetComponent<NavMeshAgent>();
_player = GameObject.FindGameObjectWithTag("Player").transform;
_enemyHealth = GetComponent<EnemyHealth>();
SetupSound();
_time = 0f;
_animator = GetComponent<Animator>();
}
void Update ()
{
_time += Time.deltaTime;
if (_enemyHealth.Health > 0 && (_animator.GetCurrentAnimatorStateInfo(0).IsName("Run") ||
_animator.GetCurrentAnimatorStateInfo(0).IsName("Attack1")))
{
_nav.SetDestination(_player.position);
if (_time > WalkingDelay)
{
PlayRandomFootstep();
_time = 0f;
}
}
else
{
_nav.enabled = false;
}
}
private void SetupSound()
{
_walkingAudioSource = gameObject.AddComponent<GvrAudioSource>();
_walkingAudioSource.volume = 0.2f;
}
private void PlayRandomFootstep()
{
int index = Random.Range(0, WalkingClips.Length);
_walkingAudioSource.clip = WalkingClips[index];
_walkingAudioSource.Play();
}
public void KnockBack()
{
_nav.velocity = -transform.forward * KnockBackForce;
}
public void PlayVictory()
{
print("victory");
_animator.SetTrigger("Idle");
_nav.enabled = false;
}
}
Now let’s play our game and see what our spatial setting sounds like…
…except when we try to play the game, we don’t have any audio at all!
After playing around and looking up why GvrAudioSource is not playing, I found the reason. We need to enable a spatial audio plug in.
To do that, we have to:
- Go to Edit > Project Settings > Audio to open our AudioManager
- In the Spatializer plug in, change from None to Gvr Audio Spatializer
With this setup, let’s go back in and try playing again.
It’s amazing how adding spatial sound changes the game. Before, I didn’t know where the enemies were, except that they’re somewhere in the game, however with Spatial Sound enabled, I can figure out where enemies are without having to do a complete 360 look around the game.
Conclusion
Wow! It’s been a long journey! 43 days in and we have gone from a complete beginner in Unity to someone who can create a simple VR First Person Shooter gameplay.
At this point, I’m going to call this project complete.
I’m not saying that this “game” is done, I’m far from having a functional game. Heck, even the gameplay part of the game that we’ve been working on isn’t as complete as I would like it to be!
However, this simple prototype has provided enough value for me (and I hope you the readers too) and spending more time trying to get every detail perfect would not be a good use of time. It’s time to work on something new!
The question now is: what’s next?
I think it’s time to make a new game, one that I hope will be able to ship! Find out more next time!
Day 42 | 100 Days of VR | Day 44
Home
CodeProject
The post Day 43 of 100 Days of VR: Setting up Google Spatial Audio in Unity appeared first on Coding Chronicles.