I’ve gone fairly boiler plate at this stage so that I can get the full scope of features on offer in this section before doing my own thing. Here it is.
Update 20181013
Added the first new feature. Shields. The player can collect up to 300 in shield health which is displayed in 3 overlapping shield health bars and as a graphic surrounding the player.
Still need to implement pickups for the player to power the shield but the feature is live
Addendum
Added this shield pickup with it’s little animation showing it was collected and 3 little animation for each shield layer showing the shield was powered up. Did the work last night (20181013) but was too late to post.
Update 20181014
I now have a (fairly shaky) power up dropping system in place.
The system allows;
- Set specific or random enemy to drop specific or random collectible
- Set a chance to spawn to collectible on a wave.
At the moment I only have three shield power ups hence that’s what’s seen in the video. But the system is in place so once I’ve tightened it up to ensure stability, it should be easy to add more power ups and containers.
Update 20181015
So after a couple hours spent trying to add weapon levels, weapon power ups and a way to change out the weapon prefab when the player picks up the weapon power up, I ended severely breaking my game
I tried reverting to a previous commit but too much damage was done for that to fix things. I had to delete local copy of my project and download last commit version.
Then added some weapon prefabs but haven’t put them in game. Need to work out how to decouple the projectile prefab, project speed etc from the player so the values can be dynamically updated from the game controller or something similar. At the same time I want to avoid creating a god class for Game Controller like I did in this monstrosity on a previous game I made with a friend.
Project code can be found here if anyone has encountered previous issues and found solutions when adding power ups to Laser Defender.
Quick screenshot showing what these early laser/weapon types look like.
Update 20181016
Have created a “system” for changing player weapon.
- Added SetWeapon method to GameSession which
- Takes an int parameter
- Clamps that within the range of weaponList items
- Sets the weapon Gameobject in GameSession
- Calls player.UpdateWeaponConfig
- Player.UpdateWeaponConfig calls gameSession.GetWeapon
- GameSession.GetWeapon returns the new weapon prefab to the player weaponPrefab property
After writing the above out I feel like it could definitely be more efficient but I will leave for now as I want to still add some customizations on weapons. Initial thought is to have a scriptable object on each weapon prefab which gives it’s attributes like speed, damage and directions for individual “bullets”. I’d like to have weapons that shoot diagonally as well as straight lines like;
Anyway, when updating the weapon using the method or similar above, these attributes will be read by Player’s UpdateWeaponConfig method and voila! … Hopefully
Until next time, here’s a quick vid demoing my weapon changing system switching between placeholder weapons.
Next step will be to add either a pickup to trigger these weapon changes (currently triggering via key press) or to fleshing out the proposed weapon attributes.
Nukkin Ya
Update 20181017
Implemented the weapon boost pick up / power up. Based of shield so not much technical details just plugging things in from the pick up and weapon changing systems. Then the inevitable troubleshooting to see where I didn’t think of XYZ.
Anyway once it was working, I made a quick particle system burst to give visual feedback that something happened when the weapon boost is collected. Here’s what it’s looking like.
Next time either adding sound effects for these pickups or trying to build out the weapons changing system to at least change the shooting speed. Once I’ve got that in it should just be a matter of learning how to give individual bullets on each weapon prefab independent directions or paths.
Update 20181018
Refactored code to remove all FindObjectOfType calls. Replaced by utilising a singleton instance pattern (Thank you Liz_The_Wiz for help) for GameSession and serialized fields for the rest.
Modified the UpdateWeaponConfig method to get projectileSpeed and projectileFiringPeriod from script attached to weapon prefab. It might not be noticeable as i haven’t improved the prefabs themselves yet but below is a video demoing.
Next will be either adding some sound effects, more prefabbed weapons and enemies or researching how to create multi directional bullet streams.
Refactored code to remove all FindObjectOfType calls.
Enjoying seeing your progress on your game Jeff, and have considered chiming in before, but didn’t want to spoil the flow of your updates - happy to remove this post if you don’t want it in the timeline. One thing I was going to suggest was the fade duration for the collected power-ups. In a couple of your videos it lives on after collected, not for long, but I found myself watching the power-up instead of watching the enemies flying in from the top - it could become a distraction for your players. Just a thought. Again, great work and really enjoying seeing your updates.
Hi Rob.
Input like that is really valuable as it’s something I never would have considered. Any and all feedback is appreciated
You have me thinking whether to freeze the objects fall and perform the animation on the spot, move the animation to the players transform.position and match movement or scrap the animation all together. I’ve set a task to rig up a demo of each for review in the near future.
Thanks again
Update 20181019
Nothing visual to show for tonight’s work. Recorded some silly sound effects but haven’t added yet as realised they’ll come in later when I have a settings menu with an option to switch between normal and silly sound effects. More prefabbed weapons will come when I find how to set up more diverse weapons so can shoot in multiple directions.
What I did get done was;
- Removed overlooked FindObjectOfType calls,
- Fixed broken singleton implementation (thanks again Liz/Sponge Borg)
- Set GameSession, MusicPlayer, SoundManager and SceneLoader all as singleton instances.
- Set clamps on values for health and shieldHealth
That’s all for tonight folks.
Hi Jeff,
You have me thinking whether to freeze the objects fall and perform the animation on the spot, move the animation to the players transform.position and match movement or scrap the animation all together. I’ve set a task to rig up a demo of each for review in the near future.
If it were me, I’d probably start super-simple and just make the fade after it’s been collected a little quicker. That way it will naturally disappear very soon after collection.
On a related note, you often see power-ups in games like this that radiate/pulse when they are available, you could then increase the speed of that pulse as it gets closer to expiring. I think at the moment you have it setup where by the power-up is always available until it goes off the screen - it’s just an alternative approach, but potentially you could use the same code for then altering the fade/pulse at the point of collision.
Thanks again
You’re very welcome, as I say I did hesitate a little as I didn’t want to interrupt your blog style development log and clutter it with my ramblings
Update 20181020
After much thought, errors and troubleshooting with assistance from people in the #Unity Discord channel, I was able to get add projectile directions to the weapons system. Here it is in action.
Update 20181021
Today has been mostly housekeeping.
- Added a function to destroy parent GameObjects of weapon prefabs when no child projectiles exist.
public void DestroyWhenProjectilesExpended()
{
if (transform.childCount == 0)
{
Destroy(gameObject);
}
}
private void Update()
{
timePassed += Time.deltaTime;
if(timePassed >= checkForChildrenPeriod)
{
DestroyWhenProjectilesExpended();
}
}
- Added side shredders to destroy bullets sent on angle that were not being captured by top and bottom shredders
- Swapped out old firing system for enemies for the one created for player allowing more flexible weapon configs
- Modified enemy shooting conditions to only shoot if on screen using OnBecameVisible and OnBecameInvisible to set bool used in fire method
private void CountDownAndShoot()
{
shotCounter -= Time.deltaTime;
if(shotCounter <= 0f && onScreen) // <----
{
Fire();
shotCounter = UnityEngine.Random.Range(minTimeBetweenShots, maxTimeBetweenShots);
}
}
private void OnBecameVisible()
{
onScreen = true;
}
private void OnBecameInvisible()
{
onScreen = false;
}
- Fixed minor bug in set enemy to spawn collectible method
- Fixed minor bug in enemy weapon prefabs
I also tweaked the waves for my dev level to test how these changes affect game play. Here’s what it currently looks like.
Addendum
- Fixed bug where player colliding with enemies wasn’t triggering the enemy deathFX by adding check if collided object had “Projectile tag”
public void Hit()
{
if(gameObject.tag == "Projectile") <-- Here
Destroy(gameObject);
}
And added a health boost.
Update 20181023
- Added player movement speed management methods to GameSession
- Added method on Player to read speed from GameSession
- Used weapon boost sprite (bolt) as speed collectible sprite
- Created laser burst sprite for weapon boost collectible sprite
- Removed power up levels to have just one power up for each attribute
- Weapon
- Health
- Speed
- Shield
- Each power up has distinctly different colours to help differentiate
- Weapon - white laser burst on green
- Health - red cross on white
- Speed - yellow bolt
- Shield - silver shield
These graphics should probably still be swapped out later but for now they’ll do.
Finally here’s a video demoing the changes.
Looking really good Jeff, well done
thats looking really slick
Well done and a thank you for sharing your progress thoughout, been a good ready to follow progress.
love the big boss, and the multi bullet weapons
Update 20181027
I’ve been working on a volume controller and options menu to interface with it. I finally worked out the issue with my SFX volume control was we were using the static AudioSource.PlayClipAtPoint method which seemed to ignore any input I gave on the volume parameter.
There are several posts online and some here on the GameDev.TV forum where it appears to work for some but I wasn’t haven’t luck. Rather than persist with banging my head against the wall I decided to replace the AudioSource.PlayClipAtPoint calls with audioSource.PlayOneShot(AudioClip myClip) calls. Now appears to be working and I can always revert down the track.
Here’s what the start and options menus are now looking like.
The Silly SFX option is a toggle/checkbox. I’m toying with the idea of replacing existing sound effects with voice recording of bang or pew. Here are some samples for those bored enough to be interested.
I’m using Panels on start menu canvas to display the start and options menus. When selecting Options, the start menu gets disabled and options enabled. Reverse when selecting main menu. I haven’t done anything for help section at this stage. Thinking of launching web browser / new tab to a web page with a game guide as seems more practical than creating a help scene in Unity.
Here’s the current state of my SoundManager script that sets the SFX to play.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoundManager : MonoBehaviour {
public static SoundManager Instance { get; private set; }
[SerializeField] AudioClip playerShotSFX, playerDeadSFX, enemyDeadSFX, enemyShotSFX, buttonClickSFX;
[SerializeField] AudioSource audioSource;
[SerializeField] [Range(0, 1)] float sFXVolume = 0.5f;
[SerializeField] [Range(0, 1)] float playerShotVolume = 1f;
[SerializeField] [Range(0, 1)] float playerDeadVolume = 1f;
[SerializeField] [Range(0, 1)] float enemyShotVolume = 1f;
[SerializeField] [Range(0, 1)] float enemyDeadVolume = 1f;
[SerializeField] [Range(0, 1)] float buttonClickVolume = 1f;
private void Awake()
{
SetUpSingleton();
SetSFXVolume(sFXVolume);
}
private void SetUpSingleton()
{
// First we check if there are any other instances conflicting
if (Instance != null)
{
// If that is the case, we destroy other instances
Destroy(gameObject);
}
else
{
// Here we save our singleton instance
Instance = this;
// Furthermore we make sure that we don't destroy between scenes (this is optional)
DontDestroyOnLoad(gameObject);
}
}
public void TriggerPlayerShotSFX()
{
audioSource.PlayOneShot(playerShotSFX, (sFXVolume * playerShotVolume));
}
public void TriggerPlayerDeadSFX()
{
audioSource.PlayOneShot(playerDeadSFX, (sFXVolume * playerDeadVolume));
}
public void TriggerEnemyShotSFX()
{
audioSource.PlayOneShot(enemyShotSFX, (sFXVolume * enemyShotVolume));
}
public void TriggerEnemyDeadSFX()
{
audioSource.PlayOneShot(enemyDeadSFX, (sFXVolume * enemyShotVolume));
}
public void TriggerButtonClickSFX()
{
audioSource.PlayOneShot(enemyDeadSFX, (sFXVolume * enemyShotVolume));
}
public float GetSFXVolume()
{
return sFXVolume;
}
public void SetSFXVolume(float newVolume)
{
sFXVolume = newVolume;
audioSource.volume = sFXVolume;
}
}
And here’s the volume controller which is attached to my volume sliders in the options menu.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class VolumeController : MonoBehaviour {
[SerializeField] Slider sFXVolumeSlider;
[SerializeField] Slider musicVolumeSlider;
public void SetSFXVolume()
{
SoundManager.Instance.SetSFXVolume(sFXVolumeSlider.value);
}
public void GetSFXVolume()
{
sFXVolumeSlider.value = SoundManager.Instance.GetSFXVolume();
}
public void SetMusicVolume()
{
MusicPlayer.Instance.SetMusicVolume(musicVolumeSlider.value);
}
public void GetMusicVolume()
{
musicVolumeSlider.value = MusicPlayer.Instance.GetMusicVolume();
}
}
I’m next wanting to tackle the problem of game states. I’m picturing 4 potential states.
- InMenu - Indicating player is in start menu, between levels or game over menu.
- InEvent - Indicating player is in a scripted event/animation/cut scene. Something I hope to implement. Not a big moving event. More just a game like scene with scripted player/enemy movement and dialogue windows appearing to deliver story. Not sure how but we’ll get there… Eventually.
- InGame - Indicating player is in an active level and playing, e.g. can shoot, move, etc.
- IsPaused - Indicating game is paused. May cross over with InMenu.
More than likely need to break this problem into smaller bits to implement. See how I go.
If you have any advice or feedback, feel free to post here in the thread.
Take care,
HorusOfOz
I love the background.
The Parallax effect is also really good.
All credit to @Rick_Davidson for the scrolling background. I’m hoping to change the image with the help of someone much more talented than I art wise, but Rick provided the code/logic and the art in place at the time of writing (See initial post for example).
Update 20181030
Unfortunately, not much progress. I tried removing the requirement for destroying GameSession so that I could add a game state controller to it but kept breaking my game. After a few days of this I’ve tried to revert everything.
I’m going to take some time to do some fun stuff like making a couple new enemies, paths and levels. Also want import the great booster art provided @Kevin_teeDee
Till next time