I had a very interesting bug that for a moment made me think that I had perhaps changed some of my scripts on accident.
So I accomplished the challenge and had everything working beautifully with the following code
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
//configuration parameters
[Header("Player")]
[SerializeField] float moveSpeed = 10f;
[SerializeField] float padding = 0.5f;
[SerializeField] int health = 10;
[Header("Projectile")]
[SerializeField] GameObject laserPrefab;
[SerializeField] float projectileSpeed = 5f;
[SerializeField] float projectileFiringInterval = 0.2f;
[SerializeField] AudioClip projectileSound;
[SerializeField] float projectileVolume = 1f;
[Header("Death")]
[SerializeField] GameObject deathExplosion;
[SerializeField] float durationOfExplosion = 1f;
[SerializeField] AudioClip deathSound;
[SerializeField] float deathVolume = 1f;
Coroutine firingCoroutine;
//state variables
float xMin;
float xMax;
float yMin;
float yMax;
// Use this for initialization
void Start ()
{
MoveBoundry();
}
// Update is called once per frame
void Update ()
{
Move();
Fire();
}
private void Fire()
{
if (Input.GetButtonDown("Fire1"))
{
firingCoroutine = StartCoroutine(FireContinuously());
}
if (Input.GetButtonUp("Fire1"))
{
StopCoroutine(firingCoroutine);
}
}
private IEnumerator FireContinuously()
{
while (true)
{
GameObject laser = Instantiate(laserPrefab, transform.position, Quaternion.Euler(0, 0, -90)) as GameObject;
laser.GetComponent<Rigidbody2D>().velocity = new Vector2(projectileSpeed, 0);
PlayProjectileSFX();
yield return new WaitForSeconds(projectileFiringInterval);
}
}
private void Move()
{
var deltaX = Input.GetAxis("Horizontal") * Time.deltaTime * moveSpeed;
var deltaY = Input.GetAxis("Vertical") * Time.deltaTime * moveSpeed;
var newXPos = Mathf.Clamp(transform.position.x + deltaX, xMin, xMax);
var newYPos = Mathf.Clamp(transform.position.y + deltaY, yMin, yMax);
transform.position = new Vector2(newXPos, newYPos);
}
private void MoveBoundry()
{
Camera gameCamera = Camera.main;
xMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).x + padding;
xMax = gameCamera.ViewportToWorldPoint(new Vector3(1, 0, 0)).x - padding;
yMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).y + padding;
yMax = gameCamera.ViewportToWorldPoint(new Vector3(0, 1, 0)).y - padding;
}
private void OnTriggerEnter2D(Collider2D other)
{
DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();
if (!damageDealer) { return; }
ProcessHit(damageDealer);
}
private void ProcessHit(DamageDealer damageDealer)
{
health -= damageDealer.GetDamage();
damageDealer.Hit();
if (health <= 0)
{
Death();
}
}
private void Death()
{
Destroy(gameObject);
GameObject explosion = Instantiate(deathExplosion, transform.position, transform.rotation);
Destroy(explosion, durationOfExplosion);
PlayDeathSFX();
}
private void PlayDeathSFX()
{
AudioSource.PlayClipAtPoint(deathSound, Camera.main.transform.position, deathVolume);
}
private void PlayProjectileSFX()
{
AudioSource.PlayClipAtPoint(projectileSound, Camera.main.transform.position, projectileVolume);
}
}
And then I resumed the video and saw that Rick had named his AudioClips projectileSFX and deathSFX instead of projectileSound and deathSound. So I decided to use cntrl R R to change the variable names to Ricks example since its just a bit more clear.
I saved my scripts and hit play to test my game, and to my surprise my enemies were shooting projectiles like a stream, and my player ships Coroutine for rapid fire was not working.
I combed through the code closely to make sure I didn’t accidentally break my functionality anywhere.
I realize now that when I changed the name of my AudioClip variable unity emptied the audioclips I had selected.
My player not being able to fire continuously makes sense, but enemies firing a vomit stream of lasers doesn’t make sense to me. Why does this enemy behavior manifest with the following code?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
[SerializeField] int health;
[SerializeField] float shotCounter;
[SerializeField] float minTimeBetweenShots;
[SerializeField] float maxTimeBetweenShots;
[SerializeField] GameObject laserPrefab;
[SerializeField] float projectileSpeed;
[SerializeField] AudioClip projectileSound;
[SerializeField] float projectileVolume = 1f;
[Header("Death")]
[SerializeField] GameObject deathExplosion;
[SerializeField] float durationOfExplosion = 1f;
[SerializeField] AudioClip deathSound;
[SerializeField] float deathVolume = 1f;
// Use this for initialization
void Start()
{
shotCounter = Random.Range(minTimeBetweenShots, maxTimeBetweenShots);
}
// Update is called once per frame
void Update()
{
CountDownAndShoot();
}
private void CountDownAndShoot()
{
shotCounter -= Time.deltaTime;
if (shotCounter <= 0f)
{
Fire();
shotCounter = Random.Range(minTimeBetweenShots, maxTimeBetweenShots);
}
}
private void Fire()
{
GameObject laser = Instantiate(laserPrefab, transform.position, Quaternion.Euler(0, 0, 90)) as GameObject;
laser.GetComponent<Rigidbody2D>().velocity = new Vector2(-projectileSpeed, 0);
PlayProjectileSFX();
}
private void OnTriggerEnter2D(Collider2D other)
{
DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();
if (!damageDealer) { return; }
ProcessHit(damageDealer);
}
private void ProcessHit(DamageDealer damageDealer)
{
health -= damageDealer.GetDamage();
damageDealer.Hit();
if (health <= 0)
{
Death();
}
}
private void Death()
{
Destroy(gameObject);
GameObject explosion = Instantiate(deathExplosion, transform.position, transform.rotation);
Destroy(explosion, durationOfExplosion);
PlayDeathSFX();
}
private void PlayDeathSFX()
{
AudioSource.PlayClipAtPoint(deathSound, Camera.main.transform.position, deathVolume);
}
private void PlayProjectileSFX()
{
AudioSource.PlayClipAtPoint(projectileSound, Camera.main.transform.position, projectileVolume);
}
}