Creating a Bubbly Pixel Art Acid Pool in Unity

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey pals welcome back to a new video today i wanted to talk to you about a little effect that i created uh recently for insignia it is uh something that i have not really been able to do for like the entirety of working on this game it's only in the last couple of years that i've picked up the skills to figure it out and uh in this case what i'm talking about is an acid pool effect uh so i'll jump straight into uh into showing you what i'm talking about here is the effect i'm really proud of this uh what this essentially started as was i am working on a dungeon in the second chapter of insignia and it takes place in this forest cavern place there is like a disturbance in the natural order and so these pools of acid have started rising up and uh flooding the place now this is a common theme it's something that i've seen in in films like princess mononoke the idea of you know radiation in real life and radioactive material sludge or garbage runoff oil spills these are real things that seem to sort of permeate media it's funny because we have an understanding of how these things work but in real life i don't think i've ever seen a picture or anything that remotely looks like this kind of like pool of liquid with bubbles and it's sort of like a radioactive light coming off it although you'll see it in things like the simpsons and rick and morty and all kinds of science fiction and things of that nature so let's sort of break down what the effect is how i implemented it and uh yeah let's get into it what is the effect well mechanically it's a zone that represents like a hitbox if you fall into the hitbox you take some damage the scene fades to black the scene fades back in and you return to the last safe position that you've been to so i can demonstrate that essentially you just drop in and you come back yeah a little bit worse for wear but still safe this is a really standard way of handling this kind of pitfall situation for games you know like the legend of zelda any kind of adventure game where there aren't any levels or lives it's just about sort of health the idea of fading the scene taking some health away and returning you back at a safe position is very common so i was pretty confident that this is how i wanted to handle this color wise originally i was going for green i mean green radioactive kind of acid is very common it's kind of the most popular way of displaying something like this but uh it wasn't really gonna work given that this is a forest environment and there's green everywhere i mean we could have gone for like a lighter green and i still could but i think in this case going for a color that clashes with the green was a smarter choice here so i chose pink pink and purple is very common in games to represent poison and poison acid isn't really uncommon as a concept either you can see this in games like final fantasy vii remake or even super smash brothers the piranha plant has like a poison sort of acid and these were inspirations as well so i started with a simple box collider with an ontrigger enter function that would run the uh sort of reposition sequence and fade the scene out uh and that was very easy to get going it's something at this point in insignia where i've got collisions and damage pretty much down pat as well as fading the scene that's something that i do quite commonly so i was just using existing features for that there were definitely a couple of pitfalls here around what happens if you set the safe point at a point that's not safe how do you actually determine what a safe point is so you can see here like there is ground where armin is uh standing and then there's also the same kind of ground at the bottom of the pool so if for whatever reason almond hits the bottom of the pool after getting hit by the liquid and after where the respawn happens then the safe point ends up being a point that's not safe and you'll end up in like a loop that will just kill you eventually so there's a little bit of logic around making sure that you know we set the safe points when we actually are in a safe position actually one other bug that does appear here which i'll show you now if you're really interested is that in this dungeon there are more mechanics one of them are these vines these like swinging vines and if you uh essentially if you pull these down you can jump on the vine right and swing across it and i'm really happy with where this is at the moment but if you happen to take damage and then get caught by the vine you will respawn still childed to the vine transform and you'll start swinging around in space so that was one bug that was very fun to solve and once i had the features working next was the visual aesthetic which i'm sure you're all very interested in now what you're looking at here is uh four different things going on okay the first thing is we have a spring system for the surface of the water that creates these ripples and this tension uh which allows the the thing to sort of like react to the bubbles popping the bubbles are a particle system there is also a shader happening over a mesh that's tied to those springs and some light radiating off the top originally you know i considered doing like a hand baked animation for this but it really wasn't something that was on the cards because i wanted to be able to resize these pools depending on the size of the hole that i wanted and this is dependent on the platforming challenges so for the sake of you know allowing me to very quickly make lots of different size liquid pools uh if i had hand drawn that you could see why that wouldn't be very um very feasible i could imagine doing some sort of tile based system uh and i'm sure that's been done many times in games prior but i think something like this feels a little more alive and more dynamic so that's what i decided to do now this sort of spring thing is not a particularly original approach i've seen this been done in a lot of different games uh specifically you know any kind of platformer where you can swim that's 2d this is a really common way of handling what happens when the player sort of like splashes through into the underside of the water so the way this works is the spring system treats the surface of the water so just the top layer as a chain and each point along the chain is a spring that can transfer energy to neighboring springs and also dampen the energy over time that it's containing so it's sort of like if you apply some sort of velocity that velocity sends it up and then that gets reflected and it bounces down and as it's doing that it's dampening sort of like just like slowing down over time and every frame it's passing some of its energy to its neighbors and that allows for that sort of uh surface tension kind of like you know cascading ripple effect that you're seeing here so it's great for those ripples but it's not really something that we could use to have any kind of uh part of the volume of water leaving the pool right it's like a blanket it can't like have pieces flying out and you can't have pieces overlapping on top so to implement this the first thing that i did was use this bright shape unity's sprite shape controller is something that i've used quite a lot of recently but i found that whenever i tried to use many points and update those points every frame the sprite shaped controller just wasn't a very good vehicle for this the reason why is because updating the points in a sprite shape causes this bright shape to re-instantiate itself and this has some garbage implications so basically some memory needs to get cleaned up after and if you do it too often the garbage collector which is a feature of c sharp tries to step in and free up that memory every you know say one second and so you have these spikes every second of like stuttering now uh instead to solve this problem i used a custom mesh so it's just like an actual 3d mesh that's just being shown in 2d where i plot those points across the top of the mesh and this has the same problem as a sprite shaped controller in that you can't really move any of the vertices in a mesh without like essentially recalculating the mesh however meshes are so much lighter that the effect on the garbage collector is essentially zero now originally i had random disturbances in the water so just setting a spring's velocity to some number just to create some sort of ripple because otherwise this thing just sits very still and to spice things up i added a sine wave offset so you can see the rising and falling even though this isn't an ocean and even though it's a still pool you would expect it to be mostly still but i thought giving it a little bit of a wave would make it feel more alive and just a bit more interesting to look at so there's kind of like a time delayed sine wave that just undulates you can see that the wave is you know a bit wider than the entire screen and undulates kind of like once per second or so the rest of this as far as the actual visual appearance of the liquid itself is part of a shader so i have this system in unity that i created called pixel effects basically what it does is there is a camera that looks just at the acid and moves the mesh into a special point in space where the normal camera can't see it and sends what it sees to a texture and then puts a quad with that texture back in the scene when the texture is made i can pixelate it so it's kind of the same as how unity's pixel perfect camera works so i can pixelate that texture and i can shade it with any kind of shader so that's how i do my pixel perfect effects in unity and so once i had it in shadowgraph it was pretty straightforward to then get this thing looking like how i wanted now in order to determine what i wanted i went into a sprite and just drew up something which i thought would look good and would be shadeable shaders are really picky right you have to be able to describe what you want in mathematical terms and it has to be an operation that exists essentially over the entire texture you're talking in in uv space so you can't really talk about oh i want to shade you know this pixel with this tint it's like okay i want to offset the entire image and then you know do some operation that cancels out the overlap and then if i can isolate the overlap then i can shade that it's very very um broad logic and it's it's quite difficult to isolate but if you've spent a lot of time in shaders like i have you kind of get it get the idea of how to do it so i can talk through that very quickly if you want to look at it don't get too alarmed because it looks like a lot but that's just how shadowgraph looks before i go any further i'll just explain like what the effect is so i take the texture i offset that texture a few times once about 10 pixels down for the bulk of the surface you can see that here and then once again another pixel down and that's the highlight that's the specular here then i take those components and i color them separately i separate them color them and then recombine them again with the original texture sort of working as the alpha cut out so it's a mask over the original texture and that gets us this lovely water this space in the middle wouldn't normally be there it's just that the circle happens to touch the top of the texture so i can't isolate it but effectively there's like a pixel that runs across here of the highlight as well the highlight would run across the entirety of the thing so that's what's happening here the first thing you'll notice is right up the back we can see and this came quite late in the piece this is just a standard uv that is being filtered through some noise this is gradient noise it's just like a static of a tv but blurrier that's how you can think about it and that is being offset over time so this is just time being multiplied by some number so i can slow it down that's being put into the x component of a vector which offsets the noise so we're just moving forward in time essentially and then we're moving some noise forward in time multiplying that by a number and then adding it we're doing some maths here basically to get our offset so a visual sort of vertical offset so there's three components the body the top face and then the specular and that's one two three the top face and the specular are the ones that get offset through noise like this and there's just some mathematical operations that just you know we're just adding things together we're isolating things by you know culling anything that's not above a certain brightness and that lets us get this um same sort of thing here where we're cutting away everything that's not this 50 range and then we're just multiplying them by a color like in this case i'm just tinting it purple or tinting it pink and the reason why i would do this is to have some sort of like precision over the output so in the first go i was just doing sort of like a color multiple over the entire thing but when you multiply by a color you're just going up through brightness whereas in my game there's a palette that describes all the colors and so rather than moving up in brightness i'm moving up through the palette right so this is one palette color another palette color and a third and that's how i make it look like it belongs in my game it's a minor thing but i think it goes a long way here so you can see that these are the different palette colors that are being applied into those different split versions this doesn't actually get used at all i just kept it here for the sake of it same thing with this for a while i was thinking of having the bubbles be a texture that repeats and shifts upwards and i just abandoned that but it's fun to keep it there just in case that's it really you know once i have all those colors i merge them with a custom union node so i just like layer them back on together and keep the stuff that's on top and then mask them out by the original texture again and voila that's that's the output so that's what we're seeing here one thing to note about this is that there are now two different functions that control the thickness of the top of the water right we have like one being the noise offset creating one undulation that's what i guess you would call like the foreground wave and then the background wave which is like the actual mask of the mesh itself is controlled just by a sine wave and i think the two of those things being in and out of phase uh helps really sell this as being something with depth so uh the third thing is the particle system particle systems are pretty easy in unity it's it's very straightforward you just load up a particle system component and tweak a bunch of knobs until you get something that looks like what you want in this case i have an edge along the bottom of the pool and that spawns the particles up the particles grow in size as they age so over time and then i have a script that looks at all the particles and when the particles breach the surface of the water i disable them and create a sub-emitter particle system which does the little splash so that's another particle system as well and that keeps things random and uh and nice and interesting at the same time when i instantiate that splash that's when i add that velocity to the spring system and that creates that lovely ripple across the top as well the particles are just a sprite that i created in a sprite and there's not really much going on there it's just a single image and to top things off i added a glowing light 2d component to the entire volume of the thing it's it's just a standard component that you can get in the package manager it's part of the urp the universal render pipeline and uh in this case it's just a pink light that's just sitting behind it i was thinking about doing mist or smoke but uh honestly uh this kind of got me most of the way there i could still do it but we'll see for now i would say this is pretty much where it needs to be so that's it pretty straightforward actually as complicated as this could have been you know sometimes i get a bit stuck with something there are a lot of technical uh things like for a while i was trying to have the particles uh pop on collision with like a volume that sits on top like a box collider on the top of the of the actual uh lake and capturing the collision of the particles was a little difficult saving the particles back into the particle system is kind of tricky and just getting the actual thing to look like it lives in the scene is also quite difficult one thing about my camera system is that when the texture gets saved to the camera and then the camera moves the actual resulting output is one frame late because it's looking at information from the previous frame so as the camera moves the actual lake is shifting very slightly by the distance the delta of the camera position from the previous frame and to counteract that i sort of just like add that back in so i just say oh just if we've moved to the right move to the right a little bit by that same amount that we were at last frame and so the lake's actually sort of like catching up to the camera just a little bit on every frame and yeah i mean it's it's something that i'm pretty happy with i to be honest was not expecting it to come out this well and there were things that i really expected to do that i chose not to do once i was prototyping it like i really thought that the bubbles would need to be a different color as they broke the surface i really thought that i would have to animate them and that there would be a lot of difficulty around the actual layering of this stuff so the bubbles you know you can see that the bubbles are really behind the lake but they don't really look like they're behind it unless you're looking at the very very top that surface layer as they're coming up through the through the surface you would expect them you know to be uh in front of you know the amount of water that was you know relative to where they were positioned in the lake so like rather than just appearing out of the back you would expect them to be appearing somewhere in the middle right but they don't do that because there is no top face it's just it's just a flight texture but honestly that kind of stuff it seems really picky now in retrospect and i guess this is a kind of takeaway that if you approach things you know trying to you know solve first things first in this case the functionality and then just increment towards the destination that you want you know the final look that you're looking for uh sometimes you find that good enough is better than what you expected and comes a bit sooner and for me this has been a bit of a lesson because you know i'm the kind of person who really likes to overthink this kind of stuff and overthinking leads to anxiety and so you know there were a couple of weeks back there between when i first implemented the actual physics of it and when i did the visuals where i was thinking oh this is just like going to take me way longer and i'm going to be tweaking it for ages and ages and how am i going to make this thing work and ultimately if you just jump in and start and just have fun with it it's easier enough and it's likely that you'll actually hit something that you like and just have fun discovering where that thing takes you rather than trying to solve it all in advance when i was at university i had like a like a supervisor for my honors who was a bit of a mentor and he used to say uh not his quote but it's a quote that he would quote to me which is that premature optimization is the mother of all evil and i believe that it's it's true if you try to solve problems before their problems you get nowhere so that's it i made an acid pool and uh i really like how it looks and i think it really makes this scene and feels like something that's threatening and dangerous so yeah thanks for watching i will catch you very soon with more updates from insignia and more tutorials for the pixel art class you've been enjoying so much thank you everyone for your support uh this channel is growing dangerously close to 100k subs and as we near the end of the year i just want to reflect on like how quickly that's happened in january we were at 20k i think so to reach 100 is uh it's kind of ridiculous and i just want to thank you all for for doing that hoping you have a very happy holiday if i don't make another video between now and then and i'll see you in the next one hey pal thanks for watching and thanks most especially to the patrons and twitch subs who support this channel and my gamedev project insignia to find out more click the links in the description below and if you like this video tell youtube by clicking the like button and then youtube will tell me and then i'll make more videos that's nice thanks again and until next time [Music]
Info
Channel: AdamCYounis
Views: 33,103
Rating: undefined out of 5
Keywords: game development, pixel art, game dev, game, video game, indie games, stream, vlog, effects, unity
Id: xXYBMTnTems
Channel Id: undefined
Length: 22min 7sec (1327 seconds)
Published: Mon Dec 13 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.