• entries
44
19
• views
3244

# 100 Days of VR: Day 14 Finish Attacking the Enemy and Walking Sounds In Unity

831 views

We’re back in Day 14. I finally solved the pesky problem from Day 13 where the Knight refuses to get pushed back when we shoot at him.

Afterwards, I decided to get some sound effects to make the game a little livelier.

Without delay, let’s get started!

# Adding Player Hit Effects Part 2

As you might recall, we last ended up trying to push back the Knight when we shoot them by changing the Knight’s velocity, however the Knight continues to run forward.

The problem

After a long investigation, it turns out that Brute running animation that I used naturally moves your character’s position forward.

The solution

After finally searching for unity animation prevents movement I found the answer on StackOverflow.

In the animator, disable Apply Root Motion and then we must apply the movement logic ourselves (which we already are).

## Writing the Knock Back code

Once we have our Root Motion disabled. We’re relying on our code to move our knight.

The first thing we need to do is update our PlayerShootingController script to call the knock back code:

using UnityEngine;

public class PlayerShootingController : MonoBehaviour
{
public float Range = 100;
public float ShootingDelay = 0.1f;

private Camera _camera;
private ParticleSystem _particle;
private float _timer;

void Start () {
_camera = Camera.main;
_particle = GetComponentInChildren<ParticleSystem>();
Cursor.lockState = CursorLockMode.Locked;
_timer = 0;
}

void Update ()
{
_timer += Time.deltaTime;

if (Input.GetMouseButton(0) && _timer >= ShootingDelay)
{
Shoot();
}
}

private void Shoot()
{
_timer = 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>();
EnemyMovement enemyMovement = hit.collider.GetComponent<EnemyMovement>();
if (enemyMovement != null)
{
enemyMovement.KnockBack();
}
if (health != null)
{
health.TakeDamage(1);
}
}
}
}

The biggest change is that we get our EnemyMovement script and then call KnockBack() which we haven’t implemented yet.

Once we have this code in, we need to implement KnockBack() inside our EnemyMovement script. Here’s what it looks like:

using UnityEngine;
using UnityEngine.AI;

public class EnemyMovement : MonoBehaviour
{
public float KnockBackForce = 1.1f;

private NavMeshAgent _nav;
private Transform _player;
private EnemyHealth _enemyHealth;

void Start ()
{
_nav = GetComponent<NavMeshAgent>();
_player = GameObject.FindGameObjectWithTag("Player").transform;
_enemyHealth = GetComponent<EnemyHealth>();
}

void Update ()
{
if (_enemyHealth.Health > 0)
{
_nav.SetDestination(_player.position);
}
else
{
_nav.enabled = false;
}
}

public void KnockBack()
{
_nav.velocity = -transform.forward * KnockBackForce;
}
}

I know this was a one liner for KnockBack(), but there was a lot of work involved to get to this point.

Here’s how the code works:

1. When our shooting code hits the enemy, we call KnockBack() which sets the velocity to be the direction behind the knight, making the illusion of being pushed back.
2. This is only temporary as our Nav Mesh Agent will come back and move our Knight towards the player in the next Update()
3. Here’s how KnockBackForce effects the velocity
1. At 1, the knight stays in place when you shoot
2. <1, the knight gets slowed down
3. >1, the knight gets pushed back

# Adding Sound Effects

Now that we finally solved the knockback problem, we moved on to the next thing.

At this point, playing the game seems dull. Do you know what could make things a little bit more interesting? Sound effects!

I went back to the Unity Asset Store to find sound effect assets specifically:

1. Player shooting sound
2. Player walking sound
3. Player hit sound
4. Enemy hit sound
5. Enemy running sound
6. Enemy attack sound

Randomly searching on Unity, I found the Actions SFX Vocal Kit which contains everything we need. Fantastic!

Once we have finished downloading and importing the SFX into our Unity project, we’ll start using them.

## Adding Enemy Hit Sound Effects

### Adding the script

The first thing we’re going to do is that we need to add our Male_Hurt audio clips to our Knight.

Normally, we need to add an Audio Source component for our Knight. However, before that, let’s step back and think: what sounds do our knight need to play?

1. Hit sound
2. Walking sound
3. Attack sound

If we were to add an Audio Source component to the Knight Object and use that to play the sound, what will happen is that one sound will immediately be replaced by the other one. We don’t want that.

What we could do is create multiple AudioSources components and then manually attach them to our script, however that’s not very scalable if we ever decided that we needed more types of sounds.

Instead I found this great way to add multiple audio sources on a single GameObject.

The idea is that instead of manually creating multiple components and then attaching them to a script component, why not create the component in code?

Here’s what I did:

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 AudioSource _walkingAudioSource;
private float _time;

void Start ()
{
_nav = GetComponent<NavMeshAgent>();
_player = GameObject.FindGameObjectWithTag("Player").transform;
_enemyHealth = GetComponent<EnemyHealth>();
SetupSound();
_time = 0f;
}

void Update ()
{
_time += Time.deltaTime;
if (_enemyHealth.Health > 0)
{
_nav.SetDestination(_player.position);
if (_time > WalkingDelay && _animator.GetCurrentAnimatorStateInfo(0).IsName("Run")))
{
PlayRandomFootstep();
_time = 0f;
}
}
else
{
_nav.enabled = false;
}
}

public void KnockBack()
{
_nav.velocity = -transform.forward * KnockBackForce;
}

}

There’s a lot of code that was added in, but I tried to separate them as much as I can to easy to understand pieces.

Here’s the flow:

1. In Start(), we instantiate our new private fields, specifically our new variables:
1. _walkingAudioSource: our AudioSource for our steps
2. _time: to track how long the enemy steps take
2. We call SetupSound() from Start() and create a new instance of an AudioSource that will only appear when the game starts and we set the volume to 0.2f
3. In Update(), we add logic to play the stepping sound whenever the it has been 0.2 seconds and that if we’re still in the running animation.
1. Note: GetCurrentAnimatorStateInfo(0) the 0 refers to index 0 layer, which I’m not really sure why, but that’s what people use. From there we can check which state the knight is in.
4. In PlayRandomFootstep(), we randomly choose the walking sound clips that we downloaded and play them

Once we have all of this we need to add the audio clips in.

Go to EnemyMovement script attached to the Knight and then under Walking Clips change the size to 4. We can do this, because Walking Clips is an array of clips.

Then add in Footstep01-04 into each spot. Make sure that Walking Delay is set to 0.4 if it’s not already.

Run the game and you’ll see that the enemy makes running sounds now!

If you’re using a different animation, you might have to change the Walking Delay to match the animation, but on the high level, that’s what you must do!

Whenever the knight attacks us, the sound will stop and whenever the knight resumes running after us (with the help of some shooting knockback) the running sound will resume!

# Conclusion

Today in Day 14, we found the problem with the knight knockback had something to do with the root animation we used.

After disabling it we can start adding our knockback code without any problems.

With the knock back implemented, the next thing that we added was sound effects. We found some assets in the Unity store and then we added them to our enemy, where for the first time, we created a component via code.

My concern at this point is what happens when we start spawning a lot of knights? Will that create an unpleasant experience?

Either way, come back tomorrow for Day 15, where I decided I’m going to add the enemy hit sound and the player shooting sound.

There are no comments to display.

## 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

• ### Similar Content

• Greetings,
Its almost 4 AM in here, i am foreigner who lives in south Korea, married and i have also a stable job. i live in Seoul, and i am looking for a serious group that willing to design and develop a game as a hobby. I am kinda dead serious about it. I made a game but its far form being finished, because lack of ideas and code lines.
I am looking for group of friends who live in south Korea and are willing to sit down, have a coffee, discuss ideas, and start bringing these ideas to life. (Online, Offline, card or mobile) game. I am good with Unity3d, and a good painter and illustrator, furthermore experienced with WACOM tabs.

Many games started from a garage by a small groups of developers, and now they reached the sky with their dreams and ideas. Please contact me or comment here, if your passion fall in this direction.
Here is couple of screenshots of the project i am working on. called "chronicles of SORFIA"

• Looking for a 2D artist to make with me a top-down game with cool features, guns, spells, and powerups. I'm a programmer, and I already made the code for the guns, different spells, powerups and basic mechanics like shooting and moving and stuff like that. I just don't have any assets to use so I'm looking for 1-2 2D artists, can be a pixel artist or anything that you want. Compensation will be 50% for you and 50% for me if we are only 2 and will be different if we are gonna be a trio, you are not working for me (or volunteering) we are a team. The only thing that I control and you not is the money, but you can argue with me and I will probably give you the amount that you think that you deserve. It doesn't have a name yet, we will decide about the name together. You can create guns with no coding because of a system that I created so you will also be able to create content for the game, besides ideas and art. I really need an artist so if you are interested please contact me in discord: #1615Cringey Boy

I will leave a video to see the game and also the build to try and actually play the game that I have right now. I don't have any art so it looks bad (;
https://drive.google.com/drive/folders/1Na3JKPBYXuUpxtP-lBUO-hIl0xO1ujSj?usp=sharing < this is the build, just download the folder called "Dungeon" and in there press on Dungeon.exe to open the game.
Controls:
1. Switch to the main gun
2. Switch to the secondary gun
Mouse Left Click. Shoot (you also aim with the mouse)
R. Reload the gun that you are holding.
E. Use main spell (currently, fireball which explodes and deals damage. And you also aim that with the mouse)
Q. Use secondary spell (currently, heal aura which heals you pretty fast. You don't need to aim)
(In the video there is no restart but in the build, there will be a restart button when you die)

Desktop 2019.10.21 - 20.55.18.02.mp4 Desktop 2019.10.21 - 20.55.18.02.mp4 )

• On Aura you can find the Track Ray fossilized bones usually split up in 6 parts. This extinct reptile was incredibly colourful and was one of the largest land animals ever to have inhabited this cold planet. It is speculated that the thick feathers and scales were good insulators for the cold and the colour was most likely a display to attract mates.

• [The original post was published with its original formatting in The Gamedev Guru's Blog]
Heya, Unity Addressables fan.
Last week, I posted a short but powerful article detailing three ways Unity Addressables can help you developing better games. The article was very well received, thanks for your active participation.

Just at the end of that post, you were given the chance to test your knowledge in Unity Addressables through a short quiz.

The goal I had in mind when creating the quiz was to help you become aware of the areas you might be less familiar with, so you can get to develop your skills where you need the most.
I'll confess that, initially, I didn't expect many people to go through the quiz. After all, quizzes can be daunting and, as usual, there's this extra babbling coming from me.
But to my surprise, the quiz results well outperformed my expectations. I'm really happy to see that so many people accepted the challenge. You all rock!
I got some interesting statistics out of the quiz. Here are some figures I wanted to share with you:
The greatest part of the people who started it, about 80%, actually were determined enough to finish it The average score was about 12, which is pretty damn good for an API that was only introduced recently Less than 5% of the quiz participants fell in the Troll Guru rank About 50% are part of the Apprentice Guru group Over 40% of the participants scored enough to be Enlightened Gurus But only 5% made it to be considered The Final Boss Guru So, congratulations if you were part of the quiz experience!
And independently from the score you got, I am sure it will not take you much effort to reach the production-level required score of 20+. I'll be helping you along the path.

In this post, I will explain the most interesting challenges posed in the quiz. Some answers might differ depending on your particular context, so make sure to comment at the end of the post if you had a complementary experience.

If you didn't complete the quiz before, do it now before reading further.
Do not cheat. I'll know.

What were your results? Are you a Troll Guru, an Apprentice Guru, an Enlightened Guru or The Final Boss Guru? Share your results in the comments section.
Trusting that you finished it, let's have a look at the questions and some of the answers. The format should be self-explanatory, but I admit I could have chosen less cheesy graphics for it— yes, that's me.

Question 1: Intense Memory Pressure
An angry player leaves a 1-star review because your game uses too much memory. You...

Answer in public, telling the player to upgrade their device and then come back
This is a popular answer somehow. As much as we might feel like answering this, chances are, we have been too busy (or lazy) to implement a proper architecture. Blaming players for playing with a brick-phone won't get us more sales, so a better strategy is to fix our mess.
Switch to a more advanced texture compression method, e.g. ETC2 to ASTC
This is helpful and you should indeed switch to more advanced compression methods, where possible. But this solution will only take you so far. You'll get moderate gains in memory usage and texture quality, but they'll not be enough to cover your memory pressure issues.

Split your scenes into sub-scenes, so less content is loaded in memory
In general, sub-scenes used to be a good solution. I've used them in the past with great success. However, if you are having bad reviews already, chances are it is too late to introduce such a massive change in the architecture of your game. Better to look somewhere else.
Implement an asset lazy-loading mechanism through AssetReferences
Over 75% of people agreed on this, that's great.
AssetReferences are likely to give you the biggest gain for the buck. The migration to this workflow is usually straight-forward and much easier than the other alternatives.
However, be aware that, in some cases, it might be hard to work around the asynchronous requirements of the Unity Addressables API.

You press the play button. By the time your in-game scene is loaded, your coffee is cold. You...
Blame the artists and ask them to put every texture into atlases. Also, you buy a faster PC
10% of the subscribers chose this one. I love you guys.
Reduce the texture size globally, so asset loading is much faster. You don't submit these meta file changes in your versioning system
I've done this a few times recently. It works.
However, the pay to price is high. Your versioning system might go nuts and your changelists will be full of garbage. This is indeed hard to manage, as if you ignore these temporal texture import settings modifications, the real changes will mostly go unnoticed and won't be submitted.
Create custom scenes that contain just the functionality you are working on
Creating sub-scenes for faster iterations might be a possibility for your game, but in my experience, they tend to be left unmaintained. With time, they break and one might spend more time fixing them than the gain you eventually had back then.
Consider implementing sub-scenes only if you don't see these problems in your project.
Remove direct references and add indirect references instead, so only the required assets are loaded
Indirect references for the winner.
Direct references will implicitly ask Unity to load all their content as soon as the script holding them is instantiated. Indirect references, however, gives you full control over the when/how/what. That means, you can delay loading until you need it, if at all, saving you from unnecessary loading times and wasted memory.

Question 3: What Play Mode Script?
You are currently implementing materials for your new characters. You want to try Addressables, so in the Play Mode script section of Addressables, you select...
Fast Mode: we want it always fast, after all
This is a valid option, but fast mode does no validation at all of important aspects of development, such as asset dependencies and cross-references.
If there are no substantial changes in the content you're working on, fast mode will be fine. Otherwise, we can do better.
Packed Play Mode: yes! we want our characters to be packed
No! The Packed play mode requires you packing the assets every time you do a change in your addressable asset contents, otherwise you'll end up loading the old versions.
You don't want to be packing every time, it's a huge time sink.
But you might consider packed play mode once you're done working with addressables content to gain faster iterations, as these assets will require minimum processing while being loaded.
35% of the Guru Challengers chose this answer.
Virtual Mode: it sounds safer than fast mode
Virtual Mode is the option I suggest you using while actively working on your addressable content.
The virtual mode is fast enough to keep iteration times short and at the same time, it'll give you useful validation checks to avoid screwing it up and finding out the mess way too late.

Question 4: Oops... Error Diagnosing
You try Addressables but you don't recall your assets looking pink in your Android device. How weird! You...
Enable the ADDRESSABLES_LOG_ALL symbol, make a development build and check the logcat logs
If you came to me with such a description, I wouldn't necessarily take you down this road directly.
The main issue with adding scripting defines and checking the logs on the device is the time it takes to prepare such a build, deploy it, test it and gather useful information from the logs.
There are indeed better ways to tackle this, but certainly keep this as a backup option if they fail to give you an accurate diagnosis of the problem.
Set the play mode script to Packed Play Mode and run it in the editor to further diagnose the issue with the Addressable Profiler
Emulating as much as you can the environment in which the content will be displayed is my preferred option, as it takes the least total amount of time. You do this by selecting the packed play mode in the main Addressables Window settings. The Unity Editor will load the addressable resources directly from the built content, so this is expected to give you a similar behavior than on the device, as long as the editor can load such a content.
You can also try running it in virtual play mode, which does some validation on top of the traditional asset loading pipeline for addressables.
Don't forget to count on the Addressable Profiler's help, a tool that will inform you about the addressable operations that are taking place at all times in your game.
This answer was correctly chosen by 66% of the participants.
Post in StackOverflow and Unity Answers
12% of you see value in posting questions on these platforms, as there are always people willing to help. But preparing a reproduction project, posting and refreshing your screen with F5 is likely to take you much longer than just diagnosing and fixing the problem yourself. Trust me, this should be your last resort.

Question 5: Heavy Video Packing
You want your mp4 trailer video to be included in your game. You...
Toss it into the StreamingAssets folder
The StreamingAssets directory works just fine, especially when coupled with famous video plugins you find in the store. The assets stored in that directory are not packed together like Resources do but rather left as individual files when your game is installed. Its simplicity and easy I/O is the reason it is the default method of playing video.
The biggest con is that the assets stored in StreamingAssets are forcefully packed in your distributed game from the beginning, so they are likely to take a lot of space in your build.
Why would your users have to wait 5 minutes longer just to download the credits video that will be played at the end of a 30+ hours game?
Mark it as Addressable, add a "videos" label to it
Sure, making it addressable sounds cool. But adding a "videos" label to it?
Usually, labels are used to download all assets belonging to that label category at once. Unless you have a very specific use case, doing this is not likely to help your project.
Mark it as Addressable, adding it to a "videos" group with the following attributes: static content, no compression
Videos are not likely to change, so making them static makes sense. Also, there's no need to compress them, as the used video codec should already offer you compression. Adding LZ4 or LZMA compression on top of this already-compressed content will only incur in CPU overhead. Your users' battery will drain faster as well. I'm sure your players wouldn't appreciate it.
Mark it as Addressable, adding it to a "videos" group with the following attributes: dynamic content, LZMA compression
Dynamic, compressed content is by far the most commonly chosen answer. But it is a misleading one.
For the reasons stated above, you should avoid using compression on already compressed content. And videos are often enough very static, so by marking that group dynamic you wouldn't be helping your asset building workflows.
Most people (46%) thought this was to best option.

Question 6: Memory on Instance Releasing
You loaded your asset once through LoadAssetAsync. Now you're done with it, so you...
Call Addressables.Release, so the memory is immediately released
There's no guarantee that the memory will be freed right away, as the current documentation correctly points out. But do not worry about it too much, it will be correctly freed by Unity. 23% popular.
Call Destroy, we better make sure we free that memory up
Addressables is, as of now, unaware of traditional Unity instantiation and destroy mechanisms. If you do so by yourself, you are doing it at your own risk and bookkeeping. If you mess it up, the API and OS are unlikely to be happy about it. And you will know.
Call Addressables.Release, so the memory is released at some point in the future
The documentation implies that the memory occupied by addressable assets will be freed at some point in the future after calling the Unity addressables release method.
You can count on Unity smartly deciding when it is time to do just so (e.g. low memory situations, Resources.UnloadAllUnusedAssets, etc.). You guys got this one right!

You're excited about doing your first Addressables.LoadAssetAsync. So you call it and use its returned handle like...
while (handle.Status == AsyncOperationStatus.Succeeded) ;
I confess to you that I've tried this method to try to force a synchronous behavior out of the Addressables API (e.g. Photon Networking under Unity Addressables).
But you can guess what happened after seeing the answer's smiley. My computer's fan started spinning insanely fast and I had to reboot the computer as the OS became utterly unresponsive. I'm not trying this again any time soon, thanks.
Doing this loop is likely to cause a deadlock, as part of the loading process is executed in Unity's main thread. And that line of code is the easiest way to block your main thread.
await handle.Task; or yield return handle;
These two solutions are asynchronous ways of waiting for the loading process to finish before continuing with our code. That's great stuff for you and me, as they offer great readability and are easy to maintain.
However, be aware they incur on some performance penalty.
This is the simplest and yet most powerful option to do something after the asset has been loaded into memory.
Keep in mind, though, that you're introducing lambdas and/or callbacks. They will reduce the readability of your code and therefore make your programming style more dangerous. Unless you are a pro, of course.

Question 8: Migrating to Better Workflows
You have a bunch of skyboxes living as direct references in your Skybox manager as a list of materials. Those are eating all your memory, so you...
Move them into the Resources folder and start using Resources.Load as you need them
Don't ever use the Resources directory for heavy assets. They are a major cause of pain, tears and  burnouts in large scale projects. It is indeed surprisingly easy to misuse the Resources API. Read more info on why it is so here
Put all skyboxes in an asset bundle that you will load appropriately
Asset bundles were a much-needed solution back then. But we have better solutions now with Unity Addressables.
The issue is that working with asset bundles is way more tedious and expensive to implement and maintain than just using Unity Addressables. Unless you're doing a port and you don't want to touch much of the original systems, try to avoid them.
Replace the list of skybox materials with a list of AssetReference's and load them as you need
Using Unity Addressables is probably the best option to tackle this kind of memory issues.
One of the reasons it is such a silver bullet is because you can easily migrate from the most popular approaches of managing content such as direct references, resources API, additive scenes and asset bundles.
Unity Addressables are a simpler way to develop more efficient games.
Decrease the skybox texture sizes
Tweaking the texture import settings works up to a point. This has an upper ceiling limit, as you cannot infinitely go lower in memory usage (and quality) without re-categorizing your 3d game into pixel-art. This just doesn't scale well.

Chances are very high that you didn't reach the rank of The Final Boss Guru.
But that's good, because that means there's massive room for improving and optimizing the way you develop and ship games. And what is more important, your players will appreciate the expertise you build in each of these areas. The only place you want to read 1-star reviews is at the app store of your competitor's game.
Given the importance of delivering enjoyable experiences to your players, I will share something with you.
Between you and me: I have a work-in-progress plan for maximizing the potential of your game with Addressables. In the upcoming weeks, I will be revealing to you more information about the Unity Addressables level-up program I'm developing. That program is going to get you to the production level you need to deliver the games people will deeply enjoy (purchasing and) playing.
To make sure you don't miss on the upcoming content, subscribe now to the newsletter. I'll keep you posted.
Till then, comment below on what you would like to learn the most and also how you plan to use Unity Addressables in your project.
See you soon on the blog!
Rubén

• On Lelantos you can use Portals to quickly go from one side of the map to the other. Each Portal has a number that once discovered will show up on the mini-map to help you keep track of where you are. Just be careful when using these teleportation devices, you never know what waits on the other side of the gate!