Jump to content
  • Advertisement
  • entries
    44
  • comments
    11
  • views
    3833

About this blog

An update blog for projects going on that have some degree of interest

Entries in this blog

Unity Weekly updates #24 - I'm capable, you know...

Hey, nice seeing you again!  I can safely say that this update is packing quite a punch, so let's get right to it! Patching up holes First, I want to talk about navigation meshes. Previously, only the procedurally generated floors were included in the navmesh baking process. This meant that all special rooms (aside for landfills and gyms) were completely inaccessible for any NPCs. This was due to two issues. The first one was simply that the navmesh baker only looked for the generated floor rather than any walkable surface. In Unity, it was just a matter of changing things a bit to use a bound box rather than checking in the object's hierarchy. The other issue was the way the floor was generated... Previously, most special rooms using static assets had floors that only covers the room itself, without counting the actual connective gap between it and the rest of the rooms. Because the floors were generated using marching squares, that connection's floor turns into an awkwardly shaped triangle, and thus created two small triangular holes. The problem was fixed by simply adding another square of the floor after that connective square.  With these two solutions, NPCs are now able to enter and navigate special rooms, so there's no escape now! New Relics and capacities Next, there's now a lot of newly implemented capacities (and thus relics). Backup Floppy Capacities This relic comes with the Second Chance capacity Second Chance When the player is about to die, then they instantaneously regain 25% of their health. This capacity can only be used once. You can, however, have that capacity many times and thus have multiple chances. Stats Bonuses DEF -35% HP -25% Beach Ball Capacities This relics only has one capacity: Double Jump. Double Jump This capacity is self-explanatory: You can now jump again in mid-air. Stats Bonuses AGL -12% Concentrated ATK Juice Capacities This relics comes with two capacities: Slow Attack and Charge Up Slow Attack This capacity simply slows down the attack speed. It also influences the charging times of chargeable weapons (like bows). This capacity can also be applied multiple times, meaning that attacks get slower and slower the more Slow Attack capacities you have. Charge Up This capacity lends to the wearer the capacity to charge attacks with swingable weapons like swords. A charged attack will have a somewhat substantial damage bonus depending on how long the player held the attack button. Quite useful to deal with stronger enemies! Stats Bonuses ATK +25% AGL -10% Echo Drop Capacities This relic only got one capacity: Shockwave. Shockwave With this capacity, the entity can generate a shockwave when they attack if they're lucky.  This makes any enemies in a small radius take damage no matter if they're hidden or not Stats Bonuses DEF -29% Electronic Mask Capacities This relic comes with two capacities: See Enemy Health and Clairvoyance. See Enemy Health This capacity is quite self-explanatory. It gives the player the ability to see any targeted enemy's current health.  Quite handy for planning attacks! Clairvoyance This capacity helps the player find their way by rendering a nice glowing path to the exit. The path actually gets refreshed every 5 seconds, and there's even a nice fade-out. Here's a picture of that path  As you can see it's really AESTHETIC. The colours of that path are picked from our palette, meaning that it changes colours depending on the current level. Stats Bonuses DEF + 5% HP -20% Fan Of Violence Capacities This relic lends two capacities: Corrosive Spead and Enflamer Corrosive Spead This capacity makes any killed enemies drop a puddle of poisonous blood. If another enemy walks on it they instantaneously become poisoned (if they don't have any other status effect that is). The puddle dries up after a while.  As of now, there's no actual damaged dealt directly to enemies when they stand on a puddle. This might an idea for later, though. Enflamer This capacity is quite easy to understand: you now deal fire damages and have a chance to give the burning status to any attacked entities. Stats Bonuses ATK +5% HP -5% Flying Shoe Capacities This relic only got one capacity: Hover. Hover This capacity makes the entity able to glide for a short period of time after a jump. Simply press and hold the jump button to glide. After a bit, the glide will stop. You can also release the jump button during a glide to stop it. One would think that the Double Jump capacity would counteract with this one but one would be wrong: just hold the button down after the double jump. This paired with a ranged weapon will make a deadly combo. Stats Bonuses HP -5% New Activatable Item Next, I want to talk about a new activated Item: French Fried French Fried Alignment: Future Funk Description This is a rather funny looking moustached french fry wearing a beret and smoking a cigarette (Don't smoke, kids). This item can summon a seagull familiar that attacks any nearby enemies for a limited amount of time. Once the time runs out the seagull disappears. The player can have up to 3 seagulls at a time. there's also a cooldown before the item can be used again. Capacities Aside for its activatable ability, the Hover capacity is also given to the player as long as they hold the item. Stats Bonuses DEF -11% Headshots! I've previously thrown the idea around of having different damage bonuses if the player targets a specific body part with a projectile. I'm proud to say that the feature is now fully implemented. Now there's a 5x damage multiplier to projectile if they hit the head (for example). Although these bonuses exist, there's still a lot of balancing to do and whatnot. But I got to say that it's quite fun headshooting enemies with arrows (mainly because enemies aren't balanced yet). This works (of course) for any projectiles. Mouse Refactored There's also have been a big mouse control refactor. Previously, the mouse script I used wasn't as flexible as I originally thought. Rather than coding everything from the ground up, I've decided to cherry-pick code from Unity's standard Assets FirstPersonController script. I Initially wanted to fully use the controller, but there were some input delays with the Update and FixedUpdate functions. I decided to pick its MouseLook script and integrate it into my custom PlayerController. The results were night and day. Not only I could easily change the sensitivity, but there's even a "Smooth Mouse" function which interpolates mouse movements. Mouse Sensitivity Speaking of mouses, I've also added the ability to change the mouse sensitivity. This was made after many feedbacks of my playtesters, who were either unable to use the mouse properly or complained about an excessively sensitive mouse. The Mouse Sensitivity setting takes the form of two components:  a slider and an input field. In essence, the input field is used to save the actual sensitivity, while the slider is just a more tactile way to set the sensitivity. Right now, changing the slider will update the input field, which in turns updates the mouse sensitivity. If the player wants an absurd sensitivity (like 100 or something), they can't use the slider for that (which only goes up to 20 right now) and instead have to manually input this in the input field. There's also another checkbox component controlling that previously mentioned "Smooth Mouse" mode. Pause Screen Option Tab Now there's an options tab in the pause menu: This is a quick way to change common settings such as volume slides and mouse sensitivity among other things. These work just like their Main Menu counterparts. Once the player closes the pause menu, options are automatically saved. Quite handy if you want to adjust your mouse sensitivity mid-game, or lowering volumes while streaming. Closed Rooms Previously, all rooms were open form the getgo. The player could technically speedrun their way through the game without breaking a sweat. This kinda made the game quite boring, as there weren't any valid reason to destroy every enemy in each room. This was in a dire need of change. So I've now implemented a linear progression system, in which the player needs to clear the room of any enemy before passing on.  Of course, the player can break walls or enter special rooms anytime (mainly because these rooms are optional and won't provide any shortcuts at all), but in order to go to the next room, they need to clean the room first. The way this works is by having closed/opened doors (much like locked doors but without any type of locks). This makes the game feel more like a game, although there's still place for improvement. Minor Upgrades Fixed the MSAA artifact bugs It was quite simple: just use FXAA Technically I can also do TAA (Temporal Anti Aliasing), but this could be put in the options. Of course, there's a lot of other options, but right now FXAA does the job just fine There might be better options, or maybe an MSAA fix but this will wait. Added a  looping testing sound effect when fiddling around with the Sound Effect volume slider This is for both the Main Menu's options screen and the Pause Menu Options tab. Fixed a lot of bugs, especially with destruction/creation Charging an attack now slow down the player Once the player unleashes its attack it resets Previously both the Quick and Slow Attack capacities only affected swing speeds. Now they also affect the charging rate. Added a touch of Ambient Occlusion I will probably put this in the options later on... Next Week Even with a cold doing its thing I'm still trying to be proactive and work on the game. In fact, yesterday I started working on a draft of a boss behaviour tree. Although still really rough and full of bugs I think I can have a working boss ready for next week. Afterwards, It'll be modelling time again, but this time it'll be level specific stuff. And after that, there's other relics, items, food, capacities and abilities that are left in the design document that needs to be implemented in the game, which means modelling, coding, designing and whatnot. But right now let's focus on bosses...

jb-dev

jb-dev

Unity Weekly updates #23 - A flock of VIRTUAL SOUNDS

Last week wasn't as productive as the last, but it's still substantial nevertheless. So without further ados, let's get to it! GUIs Previously, some GUI elements didn't scale to the screen's density. This meant that no matter the resolution those items always remained at a set size. This was fine and dandy, but now that menus are implemented it's primordial to have some kind of cohesion. The main reason why such constraint existed was mainly due to those wacky title bars of those funky windows. Before these were all textures, and in essence, I wanted to make sure that these won't get blurred or offset, so keeping the same scale was the only choice back then. I, however, tried a different approach: because these funky lines were relatively simple and didn't require any type of special texture I thought that we could easily replace them with custom geometries. This way I can control where each vertex goes and how they adapt to the GUI element's rectangle. After a bit of tinkering, I finally managed to change this, meaning that I could now get rid of the unscaled canvas. As you can see the results are a whole lot better : And here's how it looked previously: And just for comparison, let's take a look at the GUI at my screen's native resolution: It was a long-awaited change, to be honest. Especially if I want to try to have dynamic resolutions in the future. Wonderful Sounds One of the most striking updates has to be the sounds. Previously, there weren't any sounds yet, but now there are progressively more and more varied sounds, making the game a bit more complete. On most items (collectables and whatnot) there's now a physic sound that plays when the item's associated rigid body get hit. The sound changes its volume based on the impact velocity's magnitude. This makes locating those items so much easier.  Similarly, there's now another sound that plays when said item gets picked up. Let's take a look: As you can see (or heard in that case), most sounds are also given a random pitch just to spice things up. Weapon Balances Another big upgrade would be weapons. After a bit of closed testing, I've realized that the weapons could need a bit of balancing. The Gun Got Nerfed The Gun itself got a slight nerf. Before each bullet shot could be recycled. This, in effect, makes it behave more like Heavy Bullets. However, it was clear that picking up each of these bullets were kind of a pain for most people.  So I've decided to reduce the amount of time a bullet can be recycled by linking that recycling to the player's current luck stats.  In the future, there might be even actual bullet magazines and an automatic reload process (or manual). This way we could counteract the fact that bullets would be scarce if the player has poor luck. The bow got buffed The bow, however, got a big buff. Now, arrows are infinite. This effectively means that there are no more melee attacks and every time the player wants to attack a pre-charge is needed. The Mini Map Next, there's a new Minimap. This Minimap shows a simplified layout of the level. The room the player is currently in is also highlighted, and it changes when the player moves to another room. Each type of rooms has their own colours, which is dictated by the colour palette. This means that each level has their own room colours. If this might be a hindrance then this could be easily changed, but so far I simply lack the data to know. So far all rooms are shown (even the hidden ones), but eventually, only the discovered rooms would be shown. There's also no other things as of yet. There might be enemies, items and whatnot. These would be pretty easy to implement though. The map also rotates to match the player's view. It also follows the player around so that the player's position will always at the middle of the map. Take a look: Minor updates Fixed a bug with enemies' animations not working properly; Undid (partially) the UnityEvent's to also use C# native events: As seen here, there's basically no reasons to use UnityEvents rather than native C# events. One of the reasons one might use UnityEvents is of they use a serialized and strongly linked. But overall it's significantly slower; Another reason for the undoing is simply because my capacities are technically not serialized. This means that those capacities listeners are never invoked when the event is called. Added an empty Option tab in the pause menu. Next week So next I'll probably work a bit on the minimap, and perhaps fix a few graphical bugs linked with the MSAA applied to the game. Some models get unwanted gaps between shared vertices: So I might have to implement FXAA or TAA to fix this. Afterwards, it's boss time!

jb-dev

jb-dev

Unity Weekly updates #22 - LETHAL

Hi there, and welcome to this very special weekly update! Yes indeed, this one can be special. Everything about this update is related in one form or another to death. As you may or may not know death (or the capacity for a player to lose) can be an important part of any game. It can take many forms but in our case, it's a typical death. So without any further ados, let's dive right into it! Weapons and View models One of the most striking updates I've made was to weapons, or more precisely how the player uses weapons. Previously attacks, in general, were mainly governed by actual skeletal animations (i.e. the actual world model of the player) This meant that when a player swings a weapon the attack would be oriented not to the head of the player but to its body. One adverse effect of this is that the player couldn't aim up or down. Now, I've introduced view models to the game. For those who didn't know, view models are 3D models that only appear on the player view. (Think of it like gun models in Frist Person Shooters) These make it really easy to align attack not to the actual world model but to the view. This is especially useful to fix our up/down aiming problems. swings.mp4 Of course, this meant that a big refactor was in order but I think it makes the game much more enjoyable. Another effect of this change is that guns and other aiming weapons now have their own animations, meaning that they are now actually aiming at the crosshair in the middle of the screen. There's also a unique melee attack animation for these too. swingAim.mp4 Charging Weapons Previously, changing weapons such as the Bow didn't have any visual indicator of how much tense the bow was. Although this could have been fixed with animations, I didn't rig any weapons as of now. Paired this with the view models refactor and it wasn't really wise to immediately embark on such adventure. To fix this I've decided to add a nice charging bar that shows how much power a charged attack will have. There's even a nice gradient and everything. chargeBar.mp4 Projectiles and compound colliders Previously there was no actual difference between melee and ranged attacks. Both used the same colliders and did the same damage. However, now this has changed. Projectiles are now testing their hits based on a completely different set of hitboxes that are spread all over the model, one for each body part. This makes hit detection react realistically. It also means that, in case of arrows, we can stick the arrow to a particular body part and make the former follow the latter in a realistic manner. gettingShot.mp4 There could be a damage bonus in the future but at the moment it's not a priority. Aside from that, there's another benefit of using compound colliders: rigid bodies. When the player attacks using a projectile and make a lethal strike, the game can then apply a given force to the rigid body that was hit, making ragdolls behave more realistically than ever before. Death And finally, here's the best part: our own mortality. Yes, now players can experience the full thing. When their health drops down to zero, players simply die in a flamboyant way by using ragdolls. When they die, the camera is transferred to a ragdoll and a sad jingle is played. death.mp4 Death Popup After the jingle ends a nice death popup shows up and the player has three different options. Retry This options simply reuses the same run configs (aside from the seed which is regenerated) and start a new one. Main Menu   This options boots back the player to the main menu. From there the player can load a new save file and start a new run with a different character and seed. Exit  This is quite simple: it ends the game and closes the app. Popup Text The popup itself has dynamic texts that changes based on how powerful the last blow was. In the future, there might be different types of damages leading to different types of texts. We might even change the text based on what killed the player, to begin with. That's about it for death. Minor Updates Fixed many bugs related to enemies. Refactored almost everything.  Every C# events were replaced by UnityEvents. Although their implementation isn't actually any better than the native one this gives us the ability to edit events directly in the Unity Editor. It can also give us the ability to change which type of collections are used to store every observer. More optimization opportunities, yay! Added a bunch of extension methods (That thing is OP, to be honest) Removed a bunch of unused codes and whatnot. Reduced muzzle flashes. This could have been hazardous for epileptic people. Added a nice keyboard (?) model. 
Fixed bugs whit the analog blur effect dishing out unclamped colour values, resulting in strange dark lines artifacts. Added a death plane at the bottom of levels. This means that pesky player that found their way out will suffer the consequences. 😈 fallDeath.mp4 Fixed bugs with the character selector highlighting the wrong character when switching screens. Changed some sounds and added a bunch of new ones. Next week Next week will probably a continuation of the cleaning process. Afterwards, it's boss time! I've also started to read this book on game design, so there might be some unplanned edits here and there, too.

jb-dev

jb-dev

Unity Weekly Update #21 - Getting In The 【Game】

Last week was intense! There's a lot of new stuff! So without further ados, let's cut the cheese. 🧀 Loading Screens A-Plenty So last week I said I was able to load a level from the main menu. However, there were some problems when it came to the reactivity of the app during that loading phase... The game froze and gave no signs of activity, promoting Windows to administer the "Not Responding" treatment. To fix this I've broken up the loading process onto three separate loading processes.  I've also optimized the music playing feature: it now initializes before the menu screen, so now everything can be offset to a secondary thread. It's just a matter of waiting for the end of that process with a Coroutine and load the next scene when it's done. This significantly speeds up the loading process to the point where some loading screen only shows up to immediately disappear after. Getting In and Out of Levels Secondly, I've finally linked all levels together. Now, when the player jumps down the Ethernet port a loading screen is shown and the next level is then loaded. This means that the player can theoretically complete the game for the very first time. (Yay!) Levels  Thirdly, there is now more than one level. Each level has their own localized name. In the future, an AESTHETIC Sonic-like splash screen will be shown to introduce the level. Right now it's only a small notification, but it's getting there.   Because the game uses a palette, it was really easy to add other levels. I did, however, need to make each level look distinct from one to another, so I had to work on their palettes a bit. In order to get the right feel, I've tried to get Vaporwave images that inspired me and extrapolate on their palettes to create new ones. Here's a bunch level and their respective name:         Keep in mind that there'll be some level-specific props for each level in the future. (Just changing colours won't be enough to make each level unique) I also want to mention that two of these levels, mainly Current Cave and Hot Hell, have inverted palettes. Usually, each colour changes their values from light at the top to dark at the bottom. These levels have these value flipped. This creates an uneasy feeling, not unlike photo negatives. This effect was used in Current Cave to indicate that it's dark, while at Hot Hell it's hot. Development Builds While working on the game, it occurred to me that I've never built my game at all. This was kinda troubling, as I had a skewed view of the game's performance: the Unity Editor creates a lot of overhead, meaning that the game genuinely runs slower in the Editor than as a standalone. So I've decided to finally build one small developer build to evaluate the game's performance. While doing this I've also decided to tweak some the standalone's settings. For example, I've added a nice logo at the game's main splash screen. (Just a placeholder one don't worry) I've also added a bunch of program icons and cursors. While doing the cursor, it occurred to me that I could generate different cursors for each level, so I tried it.  First, I've created a base cursor image. Secondly, I map each colour channel of our base cursor to a colour given by the palette and store the result for later use. Then, when the level loads, we simply replace the cursor with the level's one and voilà. But anyways, I was able to compile a development build and give the link to some of my friends and relatives... I won't put it online right now: there're some easter eggs in it that aren't hidden yet 😉. Counting .mp3 files, the game's size is about 80 MB. While this can be quite big it is but a development build, so not everything has to be perfect. New Characters There's also three new "character" classes: gunner, marksmen and swordsmen. Each of these characters starts with their own equipment, base stats and even their own focus alignment. When the player starts a game with a specific character, its choice is saved in the save file. When the player plays again, the last used character will be already highlighted. But enough talk, let's get right into each of these classes. The Gunner Nicknamed "True American", this character starts with, well, a gun. His weapon: The Gun The gun is a new hit-scan weapon that can also be obtained in-game. It uses ammo and doesn't need to be charged like the bow. This is quite handy, but this weapon is also especially loud: It's not the most subtle weapon out there. Also, unlike the bow, it can only hold a set amount of bullets. (no reload sorry guys) When the gun runs out of ammo, the player can use a secondary melee attack. This attack, however, is considerably weaker than using a bullet.  Once the player has a gun, ammo will spawn where common consumable items would also spawn. It can even be found in Malls if the player holds a gun when the level was generated. The ammo is game persistent. This means that if the player had a gun, collected and used ammo, switched to another weapon and switch back to another gun then the ammo amount will stay the same. His Item: The Cellphone The True American also comes whit a cellphone. This gives him the ability to create one-way teleportation points. His Stats   For stats, he's really kinda weak compared to The Standard, but what he loses in raw defence he gains back in HP, making him a powerhouse if you can avoid direct contacts with enemies. The Marksmen Nicknamed "Robin Hood", this character uses a bow to dish out damages. His Weapon: The Bow This new weapon can also be obtained in the game. The Bow is used in conjunction with arrows to create a formidable combo. Unlike the gun, the bow isn't a hit-scan weapon: it instead throws arrows. In order to be effective, this weapon needs to be charged up. The player presses and hold the attack button, and release it to unleash a deadly arrow. The longer the player holds the button the faster and deadlier the arrow is. The player can also use a secondary melee attack by quickly tapping the attack button rather than holding it down. This is useful to break breakable boxes or quickly dispatch weaker enemies without wasting any arrows. Like the gun, when the player runs out of arrows, then the weaker melee attack is used. Arrows behave just like gun ammo: they will be lootable when the player holds a bow and their amount is game persistent. Oh, and it's a really expressive way to do art too: His Item: The Survival Gear Robin Hood also holds a survival backpack. This makes him able to consume some of his health and produce food items. His Stats Robin Hood's stats are somehow similar to the True American's, but where the latter gains more in HP the first has a significant advantage in Agility. The Swordsmen Nicknamed "The Standard", this is the default character and probably the only character that isn't an unlock. His Weapon: The Sword   The Standard uses a basic sword. It only has a melee attack with a set range. It's quick enough to repeatedly attack in quick succession, but that's about it. His Item: None The Standard doesn't hold any items nor any other equipment whatsoever. I'm not sure whenever or not there should be an unlockable item for this character much like The Binding of Isaac or not... His Stats This is a placeholder stats, but the idea is that this character is an all ground one. Minor Tweaks Upgraded particle physics. Now each rock crumbles made by breaking either a breakable wall or a rock will react according to their position and the explosive force of the bomb. Fixed a bunch of bugs with collision layers. Added locked folder items. This means that in order to open these you'll need a key.
   Optimized the VaporMaker album image system. Now the colour mapping takes place in the GPU rather than the CPU, saving memory and quickening the whole VaporMaker process. Optimized shaders so that the building of the game doesn't take ages. Added colour palette support for many GUI components. Made GUI component's colour listen to any palette changes so that their colour would always follow the palette. A lot of refactors and fixes. Made some GUI layout more responsive. Fixed bugs. a lot. Made State loading more dynamic. Next week What is planned next week is to polish and balance those new classes. I also want to polish some stuff that I've noted down. After that, It's up to bosses. Afterwards, it's the usual suspect... I got to say: the more and more new features get implemented the more and more this thing I have starts to resemble an actual game.  

jb-dev

jb-dev

Unity Weekly Updates #20 - Loading...

Last week wasn't concretely visual or anything... It was mainly an integration one. There was also some graphical updates plus I've also made part of the options menu. Graphics First, let's talk about those graphics. Previously, the skybox was of a solid colour. This was a placeholder skybox. However, I thought about it and came to the conclusion that it was about time to have a better one. I've searched on the internet and found this lovely gradient skybox, so I've added it to the game but with a bit of pizzazz. Basically, I've added a screen-positioned grid pattern and make a big dot in it representing the sun. I've loved it so much that I've decided to add it to my levels too! Here's how it looked previously: And here's how it looks now: I personally like how this looks. Also, previously the directional light that lights the scenes weren't following the colour palette, so I've added a bit of script to help with that, hence the different lighting... Integrations I've mainly had to link up the menus and the actual first level of the game. To do this I've used the Scene loading functions of Unity. I've added a nice loading screen with a working loading bar that fills up to the loading process' actual progression. There is, however, a bit of a hiccup while loading the level. The game window actually freezes and seems like it stopped working... This might be related to the loading process of the Music Player I've previously made: while the process loads in a different thread, the first load is done on the main process. This makes the game hang up until the first song actually loading...  This is something I'm currently working on. Options Secondly, I've also added a bunch of drivers to the options screen. Let's take a look at each tab... General This is where general options will be. Right now, there's only a dropdown to switch languages, but eventually, there might be more options if it's needed. Graphics This is where the meat is.  Here, the player can set many types of graphical settings, like resolution and quality settings. There are six quality presets: Very Low, Low, Medium, High, Very High and AESTHETIC (Ultra). There's also a seventh one, called Custom, where the player can set each graphical settings separately. As of now, this setting doesn't do anything, as it is only a driver. Audio This is where the player can set all its audio configs. Mainly this is where the player can adjust any volume sliders. There's also another section called "Others" where other audio settings can be set. As of right now, there's only a toggle indicating whenever or not the VaporMaker is active. There might be more options in the future. That's about it for options: the other tabs are still in development. Minor Updates Reflection Probes! Now there's a bunch of reflection probes in special rooms. This means that lights will feel more natural and specular materials will look better. Shader optimizations. I've optimized some shaders and the game builds quicker. (Speaking of build...) I've created a really dirty private build of the game. While still building, there was a lot of bugs and isn't really presentable. The important thing is that it builds properly and without any hiccups. I've fixed some bugs with state loading and overall scene progression. Previously the level scene was completely separate from the menu screen, meaning that a lot of states appeared twice between the scenes. Because these are supposed to be singletons, many of the level's controller were removed, breaking everything. Next week Next week is going to be the continuation of the integration. I mainly need to fix my loading screen hiccup problems and many other things. Afterwards, I might need to make an actual progression between each level. As of right now, there's only one level with no exits. Afterwards, it's gonna be boss time! And then after it's the usual suspects... I gotta say, with all that integration, I'll be soon ready to actually publish some kind of demo or test build by the end of December.

jb-dev

jb-dev

Unity Weekly updates #19 - Got CLASS and STYLE

Last week started with some kind of epiphany: I've kinda forgotten the idea of the iterative top-down development of Agile development, which is sad. So after a bit of reflexion, I've decided that it was time to start building stuff like menus, save files and playable characters. This way I could ship a playable alpha quicker, meaning that I could start getting monetary funds sooner. But anyway, let's get right to it! New Shader Beforehand, let me show you my newest shader. This one is supposed to mimic Memphis-like designs. The name "Memphis" comes from the "Memphis Group", an Italian designer group that tried to design THE design of the decade (which coincidently was the 80's). This design was mainly expressed through furniture, although it was still used in many other media. Here are some examples: (Fun fact: most furniture made by the group was actually bought by David Bowe for some reason. By far he had the most exhaustive collection.) But anyway, here's the shader: The shader is supposed to represent a rough texture typically found in many Memphis designs like so: As for the actual shader, I've first experimented with that kind of noise while making splash screens mockups in Blender. Here's the original mockup: (Notice the green bar on the left) This was achieved by using the Musgrave cycles node. The main gist is to use a Perlin noise to which we apply different types of filter to change their appearance to match the desired texture.
So I've figured that if I wanted to translate this shader in Unity I needed to take a look at blender's source code, which is coincidently open. Here's the final shader code: float4 mod(float4 x, float4 y) { return x - y * floor(x / y); } float4 mod289(float4 x) { return x - floor(x / 289.0) * 289.0; } float4 permute(float4 x) { return mod289(((x*34.0)+1.0)*x); } float2 fade(float2 t) { return t*t*t*(t*(t*6.0-15.0)+10.0); } float4 taylorInvSqrt(float4 r) { return (float4)1.79284291400159 - r * 0.85373472095314; } // Classic Perlin noise float cnoise(float2 P) { float4 Pi = floor(P.xyxy) + float4(0.0, 0.0, 1.0, 1.0); float4 Pf = frac (P.xyxy) - float4(0.0, 0.0, 1.0, 1.0); Pi = mod289(Pi); // To avoid truncation effects in permutation float4 ix = Pi.xzxz; float4 iy = Pi.yyww; float4 fx = Pf.xzxz; float4 fy = Pf.yyww; float4 i = permute(permute(ix) + iy); float4 gx = frac(i / 41.0) * 2.0 - 1.0 ; float4 gy = abs(gx) - 0.5 ; float4 tx = floor(gx + 0.5); gx = gx - tx; float2 g00 = float2(gx.x,gy.x); float2 g10 = float2(gx.y,gy.y); float2 g01 = float2(gx.z,gy.z); float2 g11 = float2(gx.w,gy.w); float4 norm = taylorInvSqrt(float4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); g00 *= norm.x; g01 *= norm.y; g10 *= norm.z; g11 *= norm.w; float n00 = dot(g00, float2(fx.x, fy.x)); float n10 = dot(g10, float2(fx.y, fy.y)); float n01 = dot(g01, float2(fx.z, fy.z)); float n11 = dot(g11, float2(fx.w, fy.w)); float2 fade_xy = fade(Pf.xy); float2 n_x = lerp(float2(n00, n01), float2(n10, n11), fade_xy.x); float n_xy = lerp(n_x.x, n_x.y, fade_xy.y); return 2.3 * n_xy; } /* Noise Bases */ float safeNoise(fixed4 p) { return cnoise(p); } float noiseMusgraveHeteroTerrain(fixed4 p, float H, float lacunarity, float octaves, float offset) { float value, increment, rmd; float pwHL = pow(lacunarity, -H); float pwr = pwHL; int i; /* first unscaled octave of function; later octaves are scaled */ value = safeNoise(p) - offset; p *= lacunarity; for (i = 1; i < (int)octaves; ++i) { increment = (safeNoise(p) + offset) * pwr * value; value += increment; pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); if (rmd != 0.0) { increment = (safeNoise(p) + offset) * pwr * value; value += rmd * increment; } return value; } fixed4 frag(v2f IN, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target { half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; fixed2 g_Resolution = _ScreenParams.xy; float factor = -IN.texcoord.y + 1; float dimension = max(_NoiseDimensions, 1e-5); float octaves = clamp(_NoiseDetails, 0.0, 16.0); float lacunarity = max(_NoiseLacunarty, 1e-5); fixed4 p = screenPos; p = p / _NoiseScale; float intensity = 1.0; float offset = smoothstep(1, 0,factor); color.rgb = lerp(color.rgb, _NoiseColor.rgb, saturate(intensity * noiseMusgraveHeteroTerrain(p, dimension, lacunarity, octaves, offset))); return color; } The Menus Then the next big thing was to create different menus in the game. In order to achieve a somewhat proper menu navigation, I've first created a simple navigation flow chart that tells what is the flow between two screens. For example, the player firstly goes through the Title screen, then goes to the main menu and so on. As for the actual implementation, I've decided to use the State design pattern. This way I can easily create simple flows between two screen. First, I've got an AbstractMenuState class: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public abstract class AbstractMenuState : MonoBehaviour { public AbstractMenuState m_nextMenu; public AbstractMenuState m_previousMenu; public Animator m_menuAnimator; protected GameObject m_menu; public GameObject menu { get { if (!m_menu) { m_menu = transform.GetChild(0).gameObject; if (!m_menuAnimator) { m_menu.GetComponent<Animator>(); } } return m_menu; } } // Show the menu public virtual bool ShowMenu() { menu.gameObject.SetActive(true); m_menuAnimator.SetBool(MenuState.instance.openParameterId, true); selected = firstSelectable; return true; } // Hide the menu public virtual bool HideMenu() { m_menuAnimator.SetBool(MenuState.instance.openParameterId, false); StartCoroutine("DisableMenuDelayed"); return true; } // Things to do when we procede to the next menu public virtual void OnNext() { } // Things to do when we return to the previous menu public virtual void OnPrevious() { } IEnumerator DisableMenuDelayed() { bool closedStateReached = false; bool wantToClose = true; MenuState instance = MenuState.instance; // We're disableing the menu once its animation transition is done while (!closedStateReached && wantToClose) { if (!m_menuAnimator.IsInTransition(0)) { closedStateReached = m_menuAnimator.GetCurrentAnimatorStateInfo(0).IsName(instance.closedStateName); } wantToClose = !m_menuAnimator.GetBool(instance.openParameterId); yield return new WaitForEndOfFrame(); } if (wantToClose) { m_menu.gameObject.SetActive(false); } } public GameObject firstSelectable { get { // We search for the first selectable child Selectable[] selectables = m_menu.gameObject.GetComponentsInChildren<Selectable>(true); for (int i = 0, length = selectables.Length; i < length; ++i) { Selectable selectable = selectables[i]; if (selectable.IsActive() && selectable.IsInteractable()) { return selectable.gameObject; } } return null; } } public GameObject selected { set { //Select the GameObject. EventSystem.current.SetSelectedGameObject(value); //If we are using the keyboard right now, that's all we need to do. var standaloneInputModule = EventSystem.current.currentInputModule as StandaloneInputModule; if (standaloneInputModule == null) { //Since we are using a pointer device, we don't want anything selected. //But if the user switches to the keyboard, we want to start the navigation from the provided game object. //So here we set the current Selected to null, so the provided gameObject becomes the Last Selected in the EventSystem. EventSystem.current.SetSelectedGameObject(null); } } } } Then I've also got a MenuState MonoBehavoir that is composed of an AbstractMenuState instance: using System; using System.Collections; using System.Collections.Generic; using UnityEngine; // This is a Singleton public class MenuState : MonoBehaviour { public static MenuState instance; private bool isReady = false; public AbstractMenuState m_currentMenu; /// <summary> /// Awake is called when the script instance is being loaded. /// </summary> void Awake() { // Setup singletion if (instance == null) { instance = this; } else if (instance != this) { Destroy(gameObject); } DontDestroyOnLoad(gameObject); isReady = true; } const string OPEN_TRANSITION_NAME = "Open"; const string CLOSED_STATE_NAME = "Closed"; private int m_openParameterId; public int openParameterId { get { return m_openParameterId; } } public string closedStateName { get { return CLOSED_STATE_NAME; } } /// <summary> /// This function is called when the object becomes enabled and active. /// </summary> void OnEnable() { //We cache the Hash to the "Open" Parameter, so we can feed to Animator.SetBool. m_openParameterId = Animator.StringToHash(OPEN_TRANSITION_NAME); //If set, open the initial Screen now. if(m_currentMenu) { m_currentMenu.ShowMenu(); } } // Proceding to the next menu public void NextMenu() { AbstractMenuStrategy next = m_currentMenu.m_nextMenu; if (next != null) { m_currentMenu.OnNext(); m_currentMenu.HideMenu(); next.ShowMenu(); m_currentMenu = next; } } // Returning to the previous menu public void PreviousMenu() { AbstractMenuStrategy previous = m_currentMenu.m_previousMenu; if (previous != null) { m_currentMenu.OnPrevious(); m_currentMenu.HideMenu(); previous.ShowMenu(); m_currentMenu = previous; } } } When the player clicks an OK button (for example), then the NextMenu() function of the MenuState is called. This internally calls the Show/Hide function of the needed AbstractMenuState and so on.  The same thing is true for any "Cancel" type of button, but using the PreviousMenu() function instead of the NextMenu() ones. Because I'm using Unity, I can then just drag and drop each AbstractMenuState instance the m_previousMenu and m_nextMenu fields to recreate my flowchart. I can even technically set these dynamically based on which button was pressed (like in the main menu screen for example) So let's get right into each menu then! Title Screen This is the title screen. The player just presses any keys to pass right through it and go straight to the main menu. Main Menu This is the main menu. The player can navigate to different screens by pressing one of the menu's buttons. Let's see what each button do. Quick Play This button is quite simple; it quickly prepares a game by reusing previously used parameters. This way the player can quickly get in the game with just one click. This automatically picks the last used savefile and character and puts the player directly at the confirm screen. If it's the first time the game is launched, then the first savefile and the default character are used. This is kinda useful. You only need two clicks and you're ready to go! Play This one is the long version of the Quick Play button. The player then needs to pick a save file from 4 different saves. Right after that, the player chooses a playable character and is then put right at the confirm screen. Options This is self-descriptive. It puts the player at the options screen. Exit This button spawns a quitting prompt.  If the player chooses "Yes", then the game quits. Otherwise the prompt closes. Savefile Screen This screen is where the player can choose which save files to use. A savefile holds many different types of pertinent statistics and information (Things like unlocks, run statistics and game completion). It also holds things like the last used character and so on. At this screen, the player will be able to do many different types of savefile manipulation like copy and erase. As of now, these operations aren't implemented, so only the OK button works. Before any operation buttons are enabled, the player must select a save file by clicking (or selecting if you use a controller) a specific save file. A selected savefile will have a green checkmark on its upper-right corner. When the player enters the screen the last used savefile is highlighted. If the game is fresh then the first savefile is used. Each save file also shows things like a progression mark and a last used date. I have yet to precise how the progression percentage is calculated, though I have some ideas on how this can be done (maybe thought unlocks and achievements, but I'm not sure yet). The player can also go back to the main menu using the "Cancel" button. Once the savefile is chosen, the screens translate to the character selection screen. Character Selection Screen This screen is where the player chooses its characters. Each character comes with different stats, focus and equipment. Each of these characteristics can be inspected through the white panel in the lower half of the screen. Like how these components behave in the pause menu, some of these also have tooltips. The characters themselves are laid in a circle formation. The layout system is dynamic enough to have n playable characters, and it's using the game object's children to do all of the layings. The currently selected playable character has a thick outline and it often the one closest to the camera. Also, the currently selected character is determined by the selected savefiles' last used character. If the data is missing then it goes to the default character. In order to change the currently selected character, the player simply uses both left and right arrows at both sides of the screen. This simply turns the contraption by a given angle (calculated from the amount of object present in the root game object). This changes the outline so that it'll follow the currently selected character. Again, the player can either go back to the save file screen or proceed to the confirmation screen. Confirmation Screen This is the last screen before starting the run. In this screen, the player can review its run parameters (like the used save file and the selected character). We can also set the generation seed at this point. As of now if the player chooses to go back then he goes all the way back to the main menu... I'm not sure if it's a better idea if we store from which screen the player came from and use this to send it back to the relevant screen. Options Screen This is where the options will be displayed. I didn't have the time to complete it yet, but it's still accessible. There will be different types of settings typical of any modern games, like graphical settings and whatnot. I've also planned to show statistic here. However, I'm not sure if I should have different tabs/view for each saves file... Technically I could place the save file selection right before the main menu and only show one statistics screen, but I'm not sure yet. That's about it for screens. Minor upgrades Because of the new shader, I've also changed some of the pause menus to use the new shader: There are also some GUI elements that also use these, like the aesthetics lines and health bars... I cant show them just yet because the menu kinda blocks the access to levels right now... I've implemented a playable character class that stores any character specific things like equipment and such;  Also, save files are in. There's a simple serialization/deserialization going on with these: I'm not sure when to save though. Right now it's after each savefile changes (like when the player uses a crystal and whatnot). I've also added a GUI shader that uses a special "Hard Light" blend mode when dealing with GUI element textures. Normally Unity uses chromatic multiplication to blend GUI textures with colours. This, however, makes any pure white pixels on the texture take the actual GUI colour;

(Hard Light on the left Left, Multiplication on the right) I've added a bunch of textures on buttons and panels. This really looks AESTHETIC now. I've added a normal mapped variant of the AtlasShader. This is quite useful for the menus' statues. Speaking of which these are actually still technically low poly (under 600 tris each!).
  Their normal maps were baked from high poly models with over 2M verts! Needless to say that Blender crashed a bunch of times while manipulating these... I've finally switched some GUI components to used the Unity's Graphic class rather than coding everything by hand and manually calling the CanvasRenderer. This makes the GUI element's code much cleaner and readable! Next Week If everything goes to plan the game will be in a playable state by beginning 2019 (or so I hope). There's still some work to do with menus... For example, the options screen isn't fully there and so far no runs can be started. I didn't complete the actual level completion, and this might be a good thing to do afterwards... Afterwards, I think I'll be able to code at least one dummy boss, with a somewhat simple attack pattern and whatnot. After it's the usual suspects: Relics, Capacities, Activated items, Equipment... The list goes on.

jb-dev

jb-dev

Unity Weekly Update #18 - 【Gear Up】

Hello there, welcome the 18th edition of your favourite weekly update! 😃 Last week was really intense. A lot of things were going on at once, so without any further ado, let's cut to the chase! Pieces of equipment First, there's now pieces of equipment in the game. Players can now stumble upon t-shirts, runnings shoes, gloves and baseball caps during their run.  Here's a picture of pieces of equipment in malls: In essence, pieces of equipment give the player unitary stat bonuses (things like +1 or +3) when worn.  Pieces of equipment can also have a focus alignment: when worn by the player, his focus will be progressively pulled towards its focus alignment. There'll also be additional stats bonuses (and even capacities) when his focus is aligned with a piece of equipment.  This means that managing your equipment is critical to have a good run. The player can hold different kinds (or slots if you want) of pieces of equipment. These are: Headware (caps, hats and whatnot); Neckwear(necklaces, neck chains, etc.) Chestwear (T-shirts, chest plates and so on); Handwear (Gloves, rings, etc.;); Footwear (boots, shoes and whatnot). The player can only hold one piece of equipment per slot. He can, however, replace his equipment by simply grabbing another one. GUI refactored Second, I've also done a big GUI overall. Although often forgotten by both gamers and developers, the GUI has an important role in games: they are often the primary way for games to tell their player critical pieces of information like their current health, money or current stats. The GUI was actually a copy-paste from the game's previous iteration with Lemur and JMonkeyEngine. With this refactoring, I've tried to use Unity's GUI components at their fullest.  I personally think I've cut the mustard with this one. Status Screen Let's take a look at the status tab of the pause menu: As you can see, everything was kinda bare. There were no ways to tell where everything was, and quite frankly it was all over the place. Here's a look at the newly redesigned one: Now that's prettier! Things are nicely labelled, aligned and positioned. There are even components that were previously hidden, like the Relics section and the Focus section. There's even an Equipment section, along with a new Item section. Also, the status screen is more interactive than ever before! Some components have tooltips, showing useful things like name, description and many more. Relics Let's take a closer look at the relic section: This is where all collected relics go. If no relics were collected yet, a placeholder text is displayed. Each relic is displayed using a nice pictogram from my custom Open Type font. As a bonus, the section is scrollable. This means that if there's a whole lot of relics the view can be truncated and controlled using a scrollbar. (Keep in mind that I've enlarged the icons sizes to show the scroll bar) Equipment The display is quite simple: it's a minimal silhouette of a human body. Each equipment slots are placed according to their type (e.x. the headwear is on the head, etc.) When a slot is empty, a pale "X" is displayed. Otherwise, a glyph representing the grabbed piece of equipment is displayed. Each of these has tooltips attached to them, showing the pieces' name, description and quality. Focus This is a barycentric coordinate component rendered as a triangle representing the player's focus. The only thing new is that it's now properly aligned and labelled... (Now look how happy it is with its proper title!) Item This component shows the currently hold activatable item. Not unlike equipment slots, having no held activatable items yields a pale "X". It also has a tooltip displaying the item's name and description. Foods Previously, foods timers were rather obnoxious: their timers were displayed right in the middle of the screen. If many foods were eaten at once then all their timers would overlap. Now, food timers are properly displayed with tooltips. When the player eats a food item it will place itself to the right of the pause menu in a vertical stack. This is not unlike how Minecraft deals with its potions effects. Once a food timer runs out, the component is removed. Dialogue box Previously, dialogue boxes were of static sizes. They were really big with a whole lot of empty space everywhere. Now that I use Unity's GUI layout at their fullest, dialogue boxes can be resized according to their content. Gone are the static sizes! Here's how it looked before: As you can see, there was a lot of wasted space. It also arbitrarily breaks its text for no other reason than to keep its dimensions. And now look at the new one: Now there's almost no wasted space. Everything fits snuggly now and feels more believable. Restroom I've previously added a restroom room but it wasn't functional yet... With the inclusion of pieces of equipment, the toilet can now fulfil its role as intended. The idea is that the player can discard one of his equipment by flushing it down the drain. The toilet will obviously clog afterwards, as generally speaking toilets aren't made for this kind of stuff, making it a one-time use. Flushed pieces won't appear later on in landfills so this is permanent. Here's a look at its dialogue box: Within the dialogue there are some similar components to those used in the pause menu's Equipment section, but with a twist. Each of these components acts as toggles (or radio toggles if you want). When the player chooses one of his equipment to flush a visual queue is displayed within. Below that, there's a bit of text that indicates which piece is currently selected. After everything is said and done the player can then click the "OK" button at the bottom of the box. This will spawn a confirmation popup: The player can then just confirm everything by pressing "yes", after which the equipment is flushed and the toilet is clogged. Minor Updates Random collectables are now chosen by asserting how much the player needs a particular collectable: We then can do a luck test to see if the player actually gets to have what he needs or not: Yes, this is cruel for some, but also rewarding to others. Fixed some shader stuff; Optimized the GUI (Dhu 🙃😞 Previously I wanted to reuse dialogue boxes. This was however kind of hard and cumbersome, especially for dialogue boxes that were rarely used at all: It was also a pain to deal with this with the Restroom's dialogue (because the whole process uses TWO boxes). Abstracted GUI window controller classes: Horray for abstraction! 🙏 Re-added the Clothes Mall, which was removed due to lack of equipment; Added a bunch of placeholder notification everywhere: These would be polished later on. foreshadowing??? 😶 Added a whole lot of localized text: Now begone "Localized text not found"! 😉 New Music I've also had the time to compose some stuff during last week. Take a look: I'm not quite sure where to use this, even if I titled it as "Tutorial", I'm not even sure if there's gonna be one. Next Week Boy, this was a mouthful! But when it rains it pours, and this was really a necessary evil. I doubt the next one would be as filled to the rim as last one. However, there are still things to do. It ain't over till the fat lady sings. I think I'll work on notifications next: They are in a dire need of polish.  I also need to continue the polishing of GUI: I didn't walk the whole nine yards. Afterwards, it's the usual suspects: Rooms, Relics, Capacities, etc. But then again I have bigger fishes to fry. 😉

jb-dev

jb-dev

Unity Weekly update #17 - 禅 GARDENS

Last week was really productive. There were a lot of changes and refactoring and it was really worthwhile. Regular rooms Firstly, regular rooms got a major uplift.  Before, there were only two types of hardcoded rooms. Neither of which were interactable as they were placeholders. I've had a blog post on how these work, but in essence, we place several prop formations at anchor point around the room. We then create those props using those and by removing props outside the room. If you want to learn more, click here! Props Secondly, there are now new types of props. Because of the major room refactoring, I need better types of props than just ferns. Rocks These are regular rocks. There are three kinds of shape which are selected randomly. These are solid and cannot be walked over. The player can, however, use a bomb to remove these. There's also a chance that when a rock breaks common consumable items can drop (things like money, bombs, keys, etc.). I've also planned to have special types of rocks that can spawn uncommon items (like foods, activated items and whatnot) through it's not implemented yet... Boxes These are solid wooden boxes that the player can break using normal attacks.  Each box has a certain damage threshold, so the stronger the attack, the quicker the breaking occurs. If the attack isn't strong enough, multiples attacks could be needed. Everything that can deal damage can be used to break those, including bombs and laser beams, although some attacks are better than others. In the future, there would be a visual indicator that tells how much damage the box took. Like rocks, a broken box can drop common items. I also think that enemies could sometimes spawn out of these. I'm not sure however if there could be special boxes that could drop special items... (Rocks DO fill that role anyway...) Minor Upgrades Some special rooms, such as the Gym, can also spawn with props. Props that are inside room specific props, such as the gym mat in Gyms, are also removed... These special rooms include: Starting rooms; Ending rooms; Gym rooms ; Landfill rooms. There could be more types of special rooms with those in the future. Ferns now spawns using the new room layout algorithm, just like rocks and boxes
Palm trees don't spawn anymore as of now. Not sure if they're gonna be used as background props or actually used inside rooms... Sometimes chrysanthemum plants can be spawn rather than ferns. I don't think that these could fit within a level... These could be used as fallbacks, though...
Many new types of shaders have been created. There's a serious need of refactoring though... Next week I feel that next week will be about refactoring and upgrading UI elements like the pause menu and such. I really think that it's also about time to add at least a piece of equipment to test, even if it's a placeholder. After the GUI is done, back to relics and capacities. Now that regular rooms are nicely generated, about 25% of the game is done. Things are progressing, and bit by bit (literally or not if you would... 🙃) the whole picture is taking form.

jb-dev

jb-dev

Algorithm Flexible Room Layout algorithm

While making a roguelike game, procedural generation have to be quick and yet intriguing enough for the generated level to be fun to just pick up and play. There are many ways to generate and laying out procedurally generated rooms. In The Binding Of Isaac, for example, you have many different types of regular room presets.  The generator just picks a preset based on things like room placement and size. Because those rooms are always of fixed size, this is a nice compromise. By having handmade presets the generated level is somewhat believable (i.e. there are no gaps or obstacles below a room door or secret room and whatnot).      Another example would be Nuclear Throne.  The game takes a different approach to procedural generation by keeping it relatively simple. Because it's not room-based like The Binding Of Isaac, there are more things like caves and large open area.  The gameplay also plays into this, as the player needs to eliminate every enemy to spawn a portal to the next level.      Because my game is somehow more inspired by The Binding of Isaac, the right way to procedurally generate rooms would be to use presets, and this is how I make special rooms. However, there's a big difference between The Binding Of Isaac and my game: my regular rooms aren't always the same size. This means that rather than having presets of regular rooms as well as special rooms I need something more flexible and, most importantly, dynamic.. The anatomy of a Room In my game, as I've said in a previous post, levels are big two-dimensional arrays from which the level geometry is generated. Every room of a level is made using a BSP tree. I won't go in details much on how rooms are generated, but in essence, we create a grid from which we trace a path between two rooms and sparsely attach bonus rooms along the way. Because I already have rooms sizes and whatnot with that level generation, I could reuse the same idea for room layouts. Within rooms, I've also set special anchor points from which props (or more precisely, prop formations, more on that later...) could be generated. Basic Layouts The idea here is to have room layout presets. Within those, presets are an array of prop formations, and each of these formations is linked to a specific anchor point. A formation has a two-dimensional boolean array that indicates whenever or not there should be a prop here. Let's take, for example, a diamond array: The dimension of the array depends on its rooms' dimensions. Here's how it's done: \( size = \left \lceil \frac{2(max(RoomSize_{x},RoomSize_{y}))) }{ 3 } \right \rceil\) In order to change the array's content we actually use common image manipulation algorithms... Bresenham's Line Algorithm The first used algorithm is the Bresenham's Line Algorithm.  Its purpose is to simply render a line describe by two bitmap points onto a raster image. To put it simply, we get the deviation (delta, or "d" for short) in both X and Y of each point of the described line and compare both of them. Depending on the biggest, we simply incremate the point on that axis and colour it in. Here's the implementation: public void TraceLine(Vector2Int p0, Vector2Int p1) { int dx = Mathf.Abs(p1.x - p0.x), sx = p0.x < p1.x ? 1 : -1; int dy = Mathf.Abs(p1.y - p0.y), sy = p0.y < p1.y ? 1 : -1; int err = (dx > dy ? dx : -dy) / 2, e2; while (true) { m_propArray[p0.x][p0.y] = true; if (p0.x == p1.x && p0.y == p1.y) { break; } e2 = err; if (e2 > -dx) { err -= dy; p0.x += sx; } if (e2 < dy) { err += dx; p0.y += sy; } } } Midpoint Circle Algorithm The midpoint circle algorithm is an algorithm used to render a circle onto an image. The idea is somehow similar to Bresenham's Line Algorithm, but rather than drawing a line we draw a circle. To do this we also need, for simplicity sakes, to divide the circle into 8 pieces, called octants. We can do this because circles are always symmetric. (It's also a nice way to unroll loops) Here's the implementation: private void TraceCircle(Vector2Int center, int r, AbstractPropFormation formation) { int d = (5 - r * 4) / 4; int x = 0; int y = r; do { // ensure index is in range before setting (depends on your image implementation) // in this case we check if the pixel location is within the bounds of the image before setting the pixel if (IsValidPoint(center + new Vector2Int(x,y)) { formation.m_propArray[center.x + x][center.y + y] = true; } if (IsValidPoint(center + new Vector2Int(x,-y)) { formation.m_propArray[center.x + x][center.y - y] = true; } if (IsValidPoint(center + new Vector2Int(-x,y)) { formation.m_propArray[center.x - x][center.y + y] = true; } if (IsValidPoint(center + new Vector2Int(-x,-y)) { formation.m_propArray[center.x - x][center.y - y] = true; } if (IsValidPoint(center + new Vector2Int(y,x)) { formation.m_propArray[center.x + y][center.y + x] = true; } if (IsValidPoint(center + new Vector2Int(y,-x)) { formation.m_propArray[center.x + y][center.y - x] = true; } if (IsValidPoint(center + new Vector2Int(-y,x)) { formation.m_propArray[center.x - y][center.y + x] = true; } if (IsValidPoint(center + new Vector2Int(-y,-x)) { formation.m_propArray[center.x - y][center.y - x] = true; } if (d < 0) { d += 2 * x + 1; } else { d += 2 * (x - y) + 1; y--; } x++; } while (x <= y); } Flood Fill Algorithm This is quite a classic, but it's still useful nevertheless. The idea is to progressively fill a section of an image with a specific colour while  The implementation is using a coordinate queue rather than recursion for optimization sakes. We also try to fill the image using west-east orientation. Basically, we fill the westmost pixel first, eastmost second and finally go north-south. Here's the implementation: public void Fill(Vector2Int point) { Queue<Vector2Int> q = new Queue<Vector2Int>(); q.Enqueue(point); while (q.Count > 0) { Vector2Int currentPoint = q.Dequeue(); if (!m_propArray[currentPoint.x][currentPoint.y]) { Vector2Int westPoint = currentPoint, eastPoint = new Vector2Int(currentPoint.x + 1, currentPoint.y); while ((westPoint.x >= 0) && !m_propArray[westPoint.x][westPoint.y]) { m_propArray[westPoint.x][westPoint.y] = true; if ((westPoint.y > 0) && !m_propArray[westPoint.x][westPoint.y - 1]) { q.Enqueue(new Vector2Int(westPoint.x, westPoint.y - 1)); } if ((westPoint.y < m_propArray[westPoint.x].Length - 1) && !m_propArray[westPoint.x][westPoint.y + 1]) { q.Enqueue(new Vector2Int(westPoint.x, westPoint.y + 1)); } westPoint.x--; } while ((eastPoint.x <= m_propArray.Length - 1) && !m_propArray[eastPoint.x][eastPoint.y]) { m_propArray[eastPoint.x][eastPoint.y] = true; if ((eastPoint.y > 0) && !m_propArray[eastPoint.x][eastPoint.y - 1]) { q.Enqueue(new Vector2Int(eastPoint.x, eastPoint.y - 1)); } if ((eastPoint.y < m_propArray[eastPoint.x].Length - 1) && !m_propArray[eastPoint.x][eastPoint.y + 1]) { q.Enqueue(new Vector2Int(eastPoint.x, eastPoint.y + 1)); } eastPoint.x++; } } } } Formation Shapes Each formation also has a specific shape. These shapes simply define the content of the formation array. We can build these shapes using the previously mentioned algorithms. There are 9 different types of shapes as of now. Vertical line A simple vertical line of a width of one Horizontal line A simple horizontal line of a width of one Diamond A rather nice diamond shape, especially pretty in corners Circle The circle is rendered using the Midpoint circle algorithm. Especially pretty in the center of rooms Cross A simple cross shape, i.e a vertical and horizontal line align at the center.  X Shape An "X" shaped cross, i.e two perpendicular diagonal lines align at the center. Triangle An Isocele triangle. Square A solid block. Every cell of the formation is essentially true. Checkers A nice variation of the square shape. Every other cell is false. There might be more types of shapes as time goes by, but it's about it for now. Placing props Once the array is set, we simply need to place the actual props in the room. Each formation is of an actual type, i.e. rocks, ferns, etc.  (For simplicity sakes, let's say that every prop is a 1x1x1m cube. This would simplify future steps.) In order to find their position, we simply align the array's center to the formations' specified anchor point. For each prop formation, we then instantiate props for each true cells while checking whenever or not the prop would be outside its room. Afterwards, we do a precise position check to make sure no props are either partially or fully outside a room. Finally, we make sure every room connections aren't obstructed with props. And voilà, we have a nicely decorated room In Game Screenshots Here's a couple of screenshots of what it looks like in-game  

jb-dev

jb-dev

Unity Weekly Update #16 - 【Relaxation】

Last week, there was a lot of thinking going on... There's still is least one new room plus many different refactoring. The Spa Firstly, there's a new room: the spa. This is a relaxing and zen room filled with classical Vaporwave aesthetics.     I've based it on really generic Vaporwave images around the internet.      The gist is that the player can cure its status effect by interacting with either massage table in the back. You may or may not have seen the fountain in the middle of the room. Its water is purely refractive with a solid, almost emissive colour when perpendicularly facing its surface (like some kind of Fresnel). This shader is part of Unity's Standard Asset, so it wasn't a hassle to get it up and running. The water is also being used in the restroom's toilet. There might be other places where it might pop up in future rooms. Minor Changes I've modelled and imported a generic spherical light that makes lighting a tad more tangible and credible.
Most lights are now coloured using blackbody colour temperatures, adding a little bit more reality to most rooms. Changed the palette texture. Colours are now more distinct from each other and more contrasting for at least the default palette. This is due to some feedback saying that the palette was too much pink... Changed how most solid colours meshes are being rendered so that they rely more on the palette texture. This means that changing the current sub-pallette or even the texture itself will dynamically change the colour of those meshes as well. Made the palette initializing run within the Unity Editor. Now there's no need to run the game only to look how models are shown. This really speeds up room designs and model previews, mainly because I previously needed to compile the game and regenerate the levels until the wanted room was generated. Refactored the RNG. Now each level has its own isolated RNG state.  This means that actions taken in one level won't influence the next one anymore. This also means that a given seed at a given chance (or luck if you fancy) stat will always produce the same level with the same loot. There's still some tweaking to do, but overall the isolated RNG system is in place. Many bugs were corrected, particularly with shaders. Next Week Most significant rooms are now in the game. There are still some minor rooms left, but these can wait: those might not even make it into the game so my energy could be better used on more critical stuff. Right now, normal rooms are in dire need of polish. Like in The Binding of Isaac, there will be different types of regular rooms. Each room would have different types of decoration in them. For example, some might have loads of rocks while others won't. There are currently only two placeholders kind of regular room... I do not know how many kinds of disposition there'll be: all of this needs research, sketches and design... There's a lot of work ahead. The good news is that heavy modelling is momentarily stopped. The following week will be fundamentally a coding one...

jb-dev

jb-dev

Unity Weekly update #15 - 【Enlightened】

Like last week, the room development is still in progress. While there are two new rooms I've also had time to tweak the lighting a bit here and there. New Lights Basically, I've tried to change the lighting of most rooms. First thing first, In order to properly shade the inside rooms I've used invisible shadow casters. At the time, it was the cheapest and quickest way to deal with it when I've started.  I did find out that another quick way to do this was with layers and light culling masks. Basically, every game objects that are inside sealed rooms is given a specific layer. That layer, in particular, was made to ignore the global directional light altogether. This means that there were no more need of these shadow casters (except on some opened rooms like the temple; the directional light can actually illuminate the room if the angle is good enough) I've also tried to fix the lighting in most rooms. Although not completely finished, it is getting prettier: The VIRTUAL Clinical Research Center As one of the newest rooms, this one represents a fictional clinical research facility named VIRTUAL Clinical Research. While in this room, the player can actually take part in a dodgy clinical trial involving either a strange cream, pills of unknown content and glowing fluids inside syringes. Each test takes away part of the player's health in exchange for cold hard cash. The ratio of health and cash is actually one to one as of yet. Taking the cream gives 5% of damage, the pills are 10% and the syringes are 25%. This room is quite useful if you're in dire need of cash, just like in real life. (except you don't get hurt as often in real life...) The Restroom This room is quite special. It a rather small room that is actually a normal public restroom, complete with a toilet, a sink, a real-time working mirror, a hand dryer, etc.  Although not functional right now, the idea is that the player can flush down one of its piece of equipment down the drain. You can only flush one piece of equipment per restroom because, well, toilets aren't really made to be able to flush down metal armours really... For those who don't know, a piece of equipment acts like a relic but is actually set to a specific equipment slot. You can only have one piece of equipment of a specific slot (for example, the player can have only one pair of gloves because it would be overpowered otherwise).  Like most RPG, different pieces of equipment have different types of stats bonuses. Each piece of equipment also has a focus alignment. This means that while the player is wearing those, its focus will progressively be drawn to whatever alignment the equipped piece is. There will also be additional stats bonuses that are applied if the player's focus matches a worn piece of equipment. But anyways, the reason the restroom isn't functional is quite simple: there's no piece of equipment yet. So it's something I'll have to get back to once there's at least one piece of equipment in the game... Next week The game is progressively coming together. Especially when it comes to rooms. There's still a lot of relics and capacities to add. There are also some rooms to add an maybe add different types of enemies and whatnot. I still want to work on rooms as of right now. The thing is that those rooms are really modelling heavy, and I really want to get those out of the way as soon as possible. The rest won't be as heavy as those, but once they're out of the way it will be a pretty big chunk of modelling that will be done. If there's time, maybe I'll work on capacities and relics...

jb-dev

jb-dev

Unity Weekly Update #14 - High Stakes

Last week was another modelling one, although there were some coding to be made in the last 2 days. Basically, I've continued the implementation of the pawnshop. Also, I had time to add a new room. The Pawnshop Although already functional, the pawnshop still needed some details props here and there. Here's a bunch of pictures showing the (almost) final version: As of now, the pawnshop's stock mainly consist of either prop from previously added rooms or even models of previous blender scene that went nowhere (take it as recycling I guess) I also want to point out that the cash register is modelled after classical mechanical cash registers like these ones:   There are also various guitars hanged on the back wall... Here's the actual reference I've used for the whole room: There's still the lighting to take care of... Also, keep in mind that I want to add more props from other rooms in the shop. So I still need to keep on moving along and get back to it when new props were added in the game. The Casino There's also a whole new room: the casino. This room acts like a giant slot machine for stats. Like traditional slots machines, the player simply pulls its lever to stop the currently active slot. There are 3 slots: one that states which stats the bonus applies, another one stating whenever it's actually positive or negative and finally the actual bonus amount. I won't lie: I kinda wanted to mimic Mario Party's mythical Chance Time. For those who aren't familiar, Chance Time was an event in the Mario Party games in which two players are forced to give/exchange specific items between each other. The player involved and the actual items are given by a slot machine-ish process. Here's a compilation of Chance Time events: As for the casino, I'm not quite sure whenever the player needs to buy in before the slots start spinning. What I'm sure of is that this process is only once per casino and that the bonus/malus is permanent. Also, the room is not fully decorated nor is lighted, but as of right now the main goal is to debug the actual slot mechanic. Next week Like before, next week is going to be room-centric again. There are also bugs with those slots that need to be fixed. They don't always line up correctly and sometimes even decides to give the player a completely different outcome.  Once most rooms are either fully or partially implemented, then maybe the next step would be to either fix animations or complete AIs. Afterwards, we still need capacities and relics... Some code refactoring wouldn't hurt either.

jb-dev

jb-dev

Music New music track released - VIRTUAL 洞窟

I've recently released on YouTube a new track part of the game's original soundtrack. I have yet to choose how this track is going to be used, but chances are that this track will be used in a cave-like level (mainly due to its title) If you got any type of feedback, don't be shy! I'm always willing to get better and am always open to criticism. 

jb-dev

jb-dev

Unity Weekly Updates #13 - Serenity

Last week was a modelling one. There aren't a whole lot of new mechanics but it was still a productive week nevertheless. Custom Font Firstly, I've previously talked about creating a custom font to display some of the GUI icons. Well, with the use of FontForge, we were able to add vectorial art in a TrueType font. For those who don't know, FontForge is an open source font-making app. It's pretty advance and can actually make good looking fonts. There's a pretty acute learning curve though. If you're using it on Windows, you'll need to fiddle around with the setting though. Otherwise, it can really run with a whole lot of hiccups and crashes. With FontForge, you can actually import vectorial graphics right into the font. Because I've already had SVG files of most of my used icons, it was just a matter of a couple of clicks and everything was imported. However, it wasn't a piece of cake: although imported, we still need to properly align those graphics up so they could be properly displayed. With FontForge you can export the custom font to different file formats. Thankfully, we can export in TrueType, which is exactly the type of font file Unity uses. Once the TrueType file is created, we can then use Unity's dynamic font rendering to display our GUI icons at any resolution we need without rescaling and rerendering any texture. However, there's a big drawback: fonts are always monochromatic. If we want a coloured icon then we'll have no other option besides using a traditional bitmap texture. (Colour fonts do exits... However, their support isn't really widespread) But anyway, here's how it looks: New rooms Secondly, there are also two new rooms. All of these rooms are linked to crystals.  Now that the player can know the number of crystals they currently have, those rooms can safely be integrated and tested without any hiccups. The Temple When visiting a temple, players can donate their crystals to gain back health points. To do this, the player simply needs to interact with the box at the back of the room while holding a crystal. Temples are modelled after Japanese Shinto temple/shrine. I've taken some liberties here and there but the overall theme is Japan. They are also much more open compared to other rooms. When the sun is right, the lighting can be quite charming. The Pawnshop The pawnshop isn't finished yet, but it's functional nevertheless. The player can exchange their crystals for a small amount of money by interacting with the yet-to-be-modelled cash register. Once finished, the pawnshop will have some fancy props here and there much like a typical pawnshop: things like guitars, jewellery and, of course, crystals. But for now, the room is kinda bland and boring... Minor updates There are also some new models and code refactors. For once, the diner now has a nice sign up on its roof: Aside from that, there aren't a whole lot of minor differences. Next week Like I've stated before, a lot of rooms can be added into the game now that most gameplay mechanics are coded.  And there's still a whole lot of rooms to implement. Of course, I still need to model out the pawnshop and add its details. There might be some polishing to do with many gameplay mechanics and maybe a refactor or two.  There's a lot of work ahead of me.

jb-dev

jb-dev

Unity Weekly Updates #12 - Having a 【Midnight Special】

Last week didn't have any particular theme, although it still was a busy one... Statuses First off, all statuses now have effect textures. these are really abstract, but nice to look at. (From left to right: Bleeding, Burning, Damned, Frenzied, Frozen, Knocked Out, Poisoned, Paralyzed and Stunned) Also, I've perfected statuses effects on enemies. Now their current status is a lot more obvious. A nice status icon is displayed over their head to help identify that status. The Diner Secondly, I've added a new room: the diner.  The idea of it is quite simple: the diner offers food for the player to eat.  The room itself is modelled after classic 50s diners with a jukebox and checkered patterns all over the place. There's even a nice neon sign that is truly aesthetic.  The lighting is still a WIP, but the models themselves are pretty much done. There might be some details to add here and there, though... The exterior also needs some work. I was thinking of giving it a huge diner sign, but for now, there's nothing fancy... Crystals Lastly, I've given the player the ability to switch their active crystals. For those who didn't know, crystals are run-persistent collectables that can give the player the opportunity to take shortcuts that gives fame and fortune to whoever chooses to take them. A GUI element is displayed at the bottom of the screen. Within it, there are 3 crystal counters for each type of crystals. When the player switches their active crystal, the element rotates around to display the right counter at the right time. There's even a nice animation for it. I've only worked on this yesterday, so it still has rough edges here and there. Also, there's no discernable way to identify the active type of crystal on the GUI element alone as of yet... There are some icons that could be ready, but I want to try to put those icons in a custom font file. This way, I can use Unity's dynamic text display functionality to have scalable graphics. One of the drawbacks of this is that only monochrome icons can be used... Minor updates Modified the bank so that it spawns with a back wall Fixed bugs with MonoBehaviours scripts presets Fixed a whole lot of bugs with the map generator. Turns out that when the player was extremely lucky, they could remain trapped in the stating room because all other rooms would become secret rooms. Added a limit on how many secrets tunnel rooms can be spawned Added a ceiling to most room obstacles such as locked doors and cracked walls so that the lighting won't look weird anymore. Added back walls to special rooms. Thus, the design of those rooms will be applied continuously rather than abruptly end. Changed the tri-colour decal shader to add emission (mainly used with the diner's neon sign) This week Now that the diner is done, I can go ahead and continue the implementation of even more rooms.  Last time I've talked about status-themed rooms, but turns out that there are a lot of other more important rooms to be added beforehand. I will be adding these up progressively... Now that the player knows their current active crystal type and their remaining amount, I can also add rooms dealing with those. I could also try to spawn pickable crystals, but right now rooms seem to be more important than crystals: they add more opportunities and varies the gameplay a lot. And finally, another possibility is to actually create these custom font files I've previously talked about, although it's not that important... Before I forget! Last week I've forgotten to mention that I've also tried to compose some music for the game. Here's a preview: ohok.mp4

jb-dev

jb-dev

Unity Weekly Updates #11 - Ms. Liza, I don't feel so good...

Last week I've worked on implementing statuses in the game. To put it simply, statuses negatively affect entities. Things like poisoning or bleeding, for example, will continuously dish out damage for a specific amount of time. Statuses Here's a list of some statuses and their effects. Keep in mind that statuses times aren't final and will eventually change depending on the impact of their effects...  Poisoned This status is self-explanatory. It will damage the entity for about 20 seconds. The damage amount will increase linearly through time.  Burning In essence, the entity is burning. Not dissimilar to being poisoned, the burning status also damages the entity for 20 seconds. The difference here is that the damage will increase using a reciprocal function.  Bleeding The entity is bleeding heavily. Again, that status is like the previous two. The difference here is that the damage will increase logarithmically.   Frozen The enemy is frozen solid. It can still move but at a reduced speed. Can also attack, but at a slower rate than usual. It will go away after 20 seconds.  Damned The enemy is cursed. For 20 seconds, the entity will be extremely unlucky.  Any luck tests will fail regardless of the entity's current luck.  Paralysed The entity is paralyzed. For 20 seconds, the entity can't move.  Frenzy The entity is caught up in a violent frenzy fits. If the entity isn't the player, then they will ignore the player and attack its friends.  If the entity is the player, then the situation is reversed: every entity will attack the player. It lasts for 20 seconds. After then, the fits end. Here's a video of frenzied enemies fighting themselves: InAFrenzy.mp4  Stunned The entity is blinded and incapacitated. A big and blinding flash is produced. The affected entity retrains their mobility, but both vision and earing are temporarily lost.  Knocked out The entity is knocked out. it can't move or see... A mix between paralyzed and stunned, except that everything will black out rather that light up. Statuses visual effects Each of these effects will have their own visuals to help to identify what type of effect is induced in who. If the effect is applied to the player, then a vignette effect is applied to the screen.  This effect actually has a nice wavy effect among other things... Here's a video of it: wavy.mp4 When inflicted by the frozen status, the player will also see ice crystals forming on their screen, just to be fancy.  If otherwise an AI is given a status, then the same pattern will be applied to it. The pattern is also screen aligned, making it really abstract. New Relics and Activated items Because statuses are now fully implemented in the game, there's now even more relics and activated items. These are directly related to statuses and give the player unique capacities like to those as well. Relics There are 4 new relics. These are all related to statuses in one way or another... Hot dreams This is an abstract representation of a sunset. It's actually quite cliché in 80s aesthetics... This relic also does billboarding. There are just some shapes that don't translate well in 3D... With this, the player is able to set entities on fire (thus giving the burning status) to attacked enemies. These attack can be direct (like a hit) or not (like a laser beam).  As long as it originated from the player, it's all right. Here are its modifiers: -5% ATK +5% AGL Ice drop This is an ancient artifact resembling a raindrop. While holding it, any attack received or given will result in the other party to receive the frozen status. Here are its modifiers: +10% DEF -5% ATK Crystal Cola This is a clear cola. It's supposed to represent a Crystal Pepsi. This relic gives the Purifier capacity. In essence, it can make the player resistant to status changes. Here are its modifiers: +10% LCK -5% ATK Crystal Tea A nice tea beverage. It's a reference to Arizona green tea. It has the Purifier capacity and also speeds up attacks. Here are its modifiers: -25% ATK +25% AGL Activated Items There's only one new activated item: the Lipstick. Lipstick Alignment: Future Funk This is a lipstick. A red one in fact. While holding it, the player will experience a small growth...  When activated, the item will make any hostile entities in a 25m radius receive the frenzy status. Here are its modifiers: -20% LCK Minor changes There weren't a whole lot of other changes. But the AI was considerably changed to include status effect in their behaviour (ex: stunned enemies can't spot the player or frenzied enemies will attack other enemies)... Next week There's still a lot of work on status effects. For example, not all statuses have patterns, and there's also more effects to be added and tweaked here an there. If there's anything new, it could be better props or even more specials rooms... After all, now that statuses are in, there's a lot of things that can be implemented.

jb-dev

jb-dev

Unity Weekly Updates #10 - yum ゝ彙ヶ

Last week I've worked on two things: Foods and Activated Items. I can safely say that my goal was achieved, and even surpassed. I've managed to add three working Activated Items and a whopping 9 foods in total. So let's dive right into it. Focus system crash course Before we dive right into activated items, we first have to know about the focus system. The focus system is like the classes or specializations system in most RPGs. Except that the focus system is actually quicker and is overall much more simpler than traditional RPG class system. (Because it's in a roguelike game and permadeath exists) In essence, each time the player uses those items, then its focus will shift through three poles: Vaporwave (Rogue/Assasins), Future Funk (Marksmen) and Hardvapor (Brawler). Having a certain focus can results in additional bonuses in certain stats, and can even give weapons and other items different type of bonuses and capacities. As of right now, no actual bonuses are implemented. This is because the focus system is primarily linked to the player's equipment... These aren't in the game just yet... Activated items If you played The Binding of Isaac, then you may be familiar with this concept. The idea is to have an item that can have an effect when manually triggered. Activated items work just like this: they are items that the player can activate. Most of the time, these give additional abilities to the player, like becoming temporarily invisible. Activated items can also have relic-like capacities that apply as long as the item is held, and can also have modifiers. Items can also have a focus alignment. Right now, only three of these are functional in the game. The Cellphone Alignment: Vaporwave This is an old piece of junk. It's supposed to represent an old Motorola brick phone. With this phone, the player is able to set up a one-way teleportation trip. First, the player needs to set up an exit point by activating it. This will create a weird sphere of spatial distortion Afterwards, when the player activates the item once more, they will be instantly teleported to it. Useful when you're in a huge level and want to get back to a specific room like a mall after getting more dosh. Here are it's modifiers: -5% ATK -10% HP Survival Gear Alignment:  Hardvapor This activated item is supposed to represent a survival backpack. With this item, the player can sacrifice its health for foods. Here are its modifiers: -20% AGL -10% HP This Alignment: None This is this or at least my interpretation of it. In my head, an object always was a big red specular sphere. Maybe it's because I started making games with Game Maker? Perhaps... With This, the player can reroll all items in a 25 meters radius for 10$. Here are the modifiers: +25% LCK -10% HP Foods Foods are like temporary relics. They sometimes have capacities like relics and also have modifiers that are usually out of this world. When the player eats foods then a countdown is initiated. When the countdown is finished, all modifier and capacities given to the player are removed. Right now every food lasts for about 5 seconds. This will be individually tweaked based on things like modifiers and capacities... Here's a list of foods in the game: Pineapple This is a simple pineapple. Nothing special here Here are the modifiers: -10% LCK +25% ATK +50% DEF -10 AGL  Banana A normal banana. Here are the modifiers: +75% LCK +68% DEF +50% AGL Lime A normal lime, cut in half. Here are the modifiers: +10% LCK +25% ATK +75% AGL -10% HP Pineaburger A burger made of a slice of pineapple. There's also a lettuce leave thrown in there for good measure. Here are the modifiers: -10% LCK +25% ATK +50 % DEF -10% AGL Double Deluxe A plain waffle topped with whipped cream and glazed with some kind of syrup (claimed to be raspberry, but sure doesn't taste like it) Here are the modifiers: +75% LCK +10% ATK -25% DEF +10% AGL +5% HP Instant Ramen A normal instant ramen bowl. chopstick included. Here are the modifiers: +50% ATK +50% AGL -25% HP Bento box A somehow 80s bento box, with crazy shapes, lines and colours. Comes with chopsticks. Here are the modifiers: +25% LCK +10% DEF -10% AGL +75% HP Toast Sandwich A somehow plain looking sandwich. It appears to have a heavily buttered toast in the middle. This is one of the food that can give you a capacity. When eaten, it gives the capacity to do a double jump. Here are the modifiers: -10% LCK +25% DEF -50% AGL -5% HP Minor updates There are now proper debug tools, such as spawning folders and so, making the testing phase so much quicker Resolved some bugs with mall inventory not being properly chosen Finally added relic/foods/equipment/weapon spawning to folders items. This means that the player can finally get good loot from folders. Fixed an infrequent bug that gives wrong orientation to some rooms (i.e. some breakable wall used to spawn perpendicular to the rooms) Added a bunch of things to add effects like 2d drop shadows and outline rendering Next week Next week I planned to add statuses to the game. Statuses like poisoned of stunned. There's already a list of statues that was previously prepared. Now it's just a matter of implementing those. Otherwise, if I have the time I'm probably going to continue the implementations of items/capacities... I also realized that while testing things out I just forget I'm testing and I just play the game (even though there's only one unfinishable level) I genuinely had fun... I wish this feeling will get bigger as this is developed.

jb-dev

jb-dev

Unity Weekly Updates #9 - Relic Mania

In my previous update, I've said that the next step would be to integrate relics in the game. I'm proud to say that I've managed to implements some of the planned relics. What are Relics? If you played The Binding of Isaac, you may recall it's Passive Collectibles. Relics are the equivalent in this game. In other words, Relics are run-scoped upgrade the player either find or (if they're lucky) buys in malls. These give stats percentage bonus (i.e. +25% bonus in attack) and also give the player special capacities. What are Capacities? Capacities are passive (i.e. not explicit, or don't need special inputs) abilities the player gain. For example, one capacity could be the capacity to shoot laser beams at each attack. There's a science to it, though. They need considerable balance tweaks here and there just to make sure the game won't break with these capacities. Some capacities are linked to relics, and others not. For example, a capacity can be linked to a specific Item or even Foods. Right now, there are no items or Food in the game, so we'll talk about those in due time... Stats crash course Before we continue with the relics, we first need to understand stats. Stats are exactly what you think they are: just like in most RPG, they quantify the skills of a given entity. In the game, there are 5 base stats : Chance (or Luck if you're fancy): This stats dictates the probability of a player to have good things happen to them (e.x. good loots spawns after an enemy is killed or a lot of special rooms and tunnels are spawned).
It also dictates your chance of doing a critical hit (when so, the total damage output are 50% stronger) Attack: it's self-explanatory. This simply gives how much damage is given at each hit Defence: Also self-explanatory. This simply says how much damage is subtracted from an attack Agility: This stats dictates how fast your character goes. there might be more in the future, but for now, it only affects this Vitality (or Health if you're fancy): This stat simply represents your maximal health. These make CADAV. I don't know if it's clever enough, but it's catchy. (Not as good as SPECIAL, but good enough) For each stat, there is two different type of bonus/malus. These are a unitary bonus (or simply bonuses) and a percentage bonus (or modifiers). Bonuses usually come with pieces of equipment (things like armour and/or weapons), while modifiers are usually applied with capacities as a counterweight. Relics List Here's a small list of relics that are fully functional as of today: Laser Gem The laser gem is a relic resembling an abstract transparent cube with an opaque core. When the player picks up that relic, it gives them the ability to fire penetrating laser beams that deal damage to enemies when the player attacks. When the laser collides with anything but entities (like enemies) it will be reflected. This can be a quite powerful tool to quickly dispatch large amounts of enemies. The beam itself last for about 10 seconds, and only 3 beams can be fired at a time. Here are the modifiers: -10% of Attack +5% of Luck Modern Computing This relic is also abstract, but it's nevertheless more meaningful than the previous relic. Both its name and its model references something really vaporwave. But I'll let you figure it out. When the player grabs this relic, a combo system is activated: for every enemy killed, drops that cames from defeated enemies will linearly increase in number. Of course, being a combo system, if the player is hit then the combo is reset. Here are the modifiers: -5% of Luck -4% of Attack Credit Card The credit card is a credit card. (I didn't know what you expected) With this cool relic, the player can actually purchase anything they want anywhere even if they lack the money for it.  Buying an item without the needed money creates a debt in the player's funds. After each 10$ of debt, a random amount of negative modifiers are applied to the player's stats. When the player pays off their debts then these nerfs are progressively removed. Because of this special capacity, no base modifiers are applied when this relic is grabbed. DOUBLE-VISION This relic is rather abstract. It's actually a pair of eyes. When the player grabs this relic, every loot that are consumables (i.e bombs, keys or money) are doubled. Here are the modifiers: -5% of Attack -10% of Luck +5% of Agility Extension Cord This relic is simply a North American electric extension cord. There are two capacities attached to this relic. The first one simply makes the range of your attacks bigger. Its just actually the game resizing your weapons... Nothing special here. The second one is more a nerf than anything else: It slows down your attack speed by half. Here are the modifiers: -25% of Attack -25% of Agility Boxed Copy This relic is a Software box. It's supposed to mimic the Windows 9x boxes. With this relic, on the first successful hit by the player to an enemy, the latter has a chance to get "Boxed". When being "boxed", enemies are transformed into a similar box like the relic itself. However, that box is able to be opened by the player. It then spawns a random amount of consumables. It essentially one hit enemies if your lucky and gives you loot too. This only works on the first hit: subsequential hits won't work. Here are the modifiers: -25% of Attack Atk-booster 2000 This relic is a computer chip, presumably a CPU. It simply increases your attack speed by half. Here are the modifiers: -25% of Attack +10% of Agility Watch Out! This relic is a simple watch. With this one, you gain the ability to backstab other enemies. (not unlike the TF2 backstab) This means that if you hit their back they get one hit. In essence, this works by using the same algorithm that my vision field Here are the modifiers: -40% of Attack -25% of Health +5 of Agility Minor Updates Items that are in malls, along with relics and pieces of equipment, now rests on pedestals. These get removed when the item is picked up or otherwise get removed
There's now a key collectible that can spawn with any type of loot. Picking these up simply increments the player's total amount of keys
The Big Mall (the generic one) now has a chance to spawn a buyable relic in its inventory Fixed many bugs with a whole lot of things Thrown items now properly trigger AIs: they will look at the player that has thrown said projectiles rather than the projectile itself What's next? This week I'm planning to add more capacities and maybe add either Foods or Items in the game. Same goal as before: at least one Food or Item. Just to be clear: Items are like The Binding Of Isaac's Activated Collectibles except that they also change the player's stat and may also add passive capacities while the item is being held. As for food, think of relics, but temporary (a bit like Minecraft's potions). Here comes another big week I guess...

jb-dev

jb-dev

Unity Weekly Update #8 - Locked down

I've decided to change the frequency of these updates: most of the times, I just do some minor updates and graphical tweaks here and there. Therefore, if I do these updates weekly, then I'll have a lot more content to write about. So, yeah... Last week, I've been working on adding many different types of rooms in the level. You may or may not know that I use BPS trees to generate a level, and previously, only 5 types of rooms spawned in a level: starting rooms, ending rooms, normal rooms, tunnel rooms and Malls. It was very static and not flexible, so I've changed it to make it more dynamic. Malls Variations First, I've added two different variations for Malls: Blood Malls and Clothes Malls. These were originally planned and already built. Big Malls These are your typical type of Malls. You can find everything here. This is where, for example, you'll find hearts, keys and/or bombs. They were already in the game, but now they're more specialized (or generalized in this case) Blood Malls The Blood Malls specialized in bloody activities. (meaning that you'll mostly find a selection of weapons here) Clothes Malls The Clothes Malls are specialized in clothes, which in our case are actually pieces of equipment the player can have New Rooms Aside from these new type of malls, I've also added 3 new types of rooms. These rooms, however, are guarded by a locked door: the player must use a key to enter. In order to unlock a locked door, the player just needs to touch it. If the player has enough keys, then a key is used and the locked door disappears. There's also an event that triggers that can do things when the player unlocks the door (like revealing hidden models and what not) The Gym The gym is a room resembling some of these outside gyms you can see in some places.  The player can use up to tree gym equipment to get a permanent stats bonus to a randomly selected stat.  The prices of usages of these gym equipment doubles after each use. (i.e. if using one piece is 10$, then after buying it the others will cost 20$ and so on) I've planned that NPC would use non-interactive gym workstations for decoration, but it's not really important as of right now... The Bank The bank is not fully functional at the moment, but it still spawns. The idea is to give the player a way to store money persistently throughout runs. The player can then withdraw money (with a certain transaction fee) from that bank. That means that you can effectively get previously deposited money back when you'll need it the most. The Landfill The landfill gives you the opportunity to gain back previously thrown away pieces of equipment. Basically, the game stores the last three thrown away pieces of equipment. When the rooms spawn, it simply displays you those pieces of equipment. you can then pick them up for free. This, however, comes with a caveat: pieces of equipment that will be switched from a previously thrown away pieces of equipment won't reappear in another landfill. Also, once the landfill despawns, the items in that landfill will be discarded. (Think of it as a last chance opportunity) There aren't any props at the moment, but it's fully functional. Minor Tweaks Aside from that, there are also some minor tweaks: Bombs now damage the player if the latter is within its blast radius; Player jumps are now more precise: letting go of the jump button early makes a smaller jump than if it was held down longer; Ground detection (that was previously done with raycasting) now uses Unity's CharacterController.isGrounded property; When the player is hurt, a knockback is applied to him; The strength of said knockback is actually the total amount of damage the player took. Coins and money items now emit particles to help the player localize those important items;
They're now keys (left) and bombs (right) counters in the HUD;
The key one still needs a specific icon, but it's fully functional; There were many shader optimizations and adjustments: Many shaders were merged together and are now sharing most code; I've also changed the shaders so that we can use GPU instancing for most props, I also now use MaterialPropertyBlock for things like wetness; Also, now the palette texture and its palette index are now global variables, this effectively means that I only need to set these values once and everything else follows; A small "Sales" sign is placed in front of most types of malls. This sign has a random orientation and position each time it's spawned. ;
Props that obstruct a passage are removed from the room; This way no prop can obstruct the room so that the player cannot exit it. Some rooms now spawn ferns instead of palm trees;
Lianas also have different configurations based on which prop spawns. Next week Over the next week, I've planned to integrate the first relic. Relics are items that give the player capacities and stats boosts. It's common to have something similar in most roguelite and roguelike games. That type of thing needs to have a good abstraction in order to work: there are many different types of capacities that affect the player in radically different ways. There's a lot of work ahead. But I'm confident it'll be easy. Just need to get in the groove.

jb-dev

jb-dev

Unity Daily Update #7 - Another plane of being

During the past days, lots of shaders were updated and other visual things did too. Firstly, I've added lights effects when the crystals get shattered. There's also a burst of particle emanating from the broken crystal on impact. Also, enemies now leave a ragdoll corpse behind when they die. I love some of the poses those ragdolls make. On another note, I've toyed around with corpse removal and got captivated by the shrinking effect it created. It can sometimes be off-putting, but I'm still captivated. I've also added a nice VHS-like effect from layering two VHS shader together; namely "more AVdistortion" and "VHS pause effect". I've already ported the former and it's already active and the latter was just a matter of porting GLSL shaders to HLSL. No biggie. I did change the code a bit to make the white noises move through time. And there's nothing like trigonometry to help us with that fixed4 frag (v2f i) : SV_Target { fixed4 col = fixed4(0, 0, 0, 0); // get position to sample fixed2 samplePosition = i.vertex.xy / _ScreenParams.xy; float whiteNoise = 9999.0; // Jitter each line left and right samplePosition.x = samplePosition.x + (((rand(float2(_UnscaledTime, i.vertex.y))-0.5)/64.0) * _EffectStrength ); // Jitter the whole picture up and down samplePosition.y = samplePosition.y + (((rand(float2(_UnscaledTime, _UnscaledTime))-0.5)/32.0) * _EffectStrength ); // Slightly add color noise to each line col += (fixed4(-0.5, -0.5, -0.5 , -0.5)+fixed4(rand(float2(i.vertex.y,_UnscaledTime)),rand(float2(i.vertex.y,_UnscaledTime+1.0)),rand(float2(i.vertex.y,_UnscaledTime+2.0)),0))*0.1; // Either sample the texture, or just make the pixel white (to get the staticy-bit at the bottom) whiteNoise = rand(float2(floor(samplePosition.y*80.0),floor(samplePosition.x*50.0))+float2(_UnscaledTime,0)); float t = sin(_UnscaledTime / 2); if (whiteNoise > 11.5-30.0*(samplePosition.y + t) || whiteNoise < 1.5-5.0*(samplePosition.y + t) ) { // Sample the texture. col = lerp(tex2D(_MainTex ,samplePosition) , col + tex2D(_MainTex ,samplePosition), _EffectStrength); } else { // Use white. (I'm adding here so the color noise still applies) col = lerp(tex2D(_MainTex ,samplePosition), fixed4(1, 1, 1,1), _EffectStrength); } return col; } It's nice to have HLSL code, but a video is better:  

jb-dev

jb-dev

Unity Daily Update #6 - Dynamically colored decals

Today was kind of a slow day too. I've haven't got a lot of sleep lately (thanks little hamster wheel in my head) But at last, I was still able to add (and also fix) some graphical components here and there. In short, I've made the first and last rooms of the level more distinct from every other room. For example, I've added a room flow on these rooms to properly align props and, in the case of the starting room. the spawning rotation. I've also added a little decal-like plane that tells the player what to do (take it as a little tutorial, if you may) The important thing is that this decal is, not unlike my palette shader, dynamic in terms of colours. What I've done is quite simple: I've mapped each channel of a texture to a specific colour. Here's the original texture: After inputting this texture in my shader, it was just a matter of interpolating values and saturating them: Shader "Custom/TriColorMaps" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 _RedMappedColor ("Mapped color (Red channel)", Color) = (1, 0, 0, 1) _GreenMappedColor ("Mapped color (Green channel)", Color) = (0, 1, 0, 1) _BlueMappedColor ("Mapped color (Blue channel)", Color) = (0, 0, 1, 1) } SubShader { Tags { "RenderType"="Transparent" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows vertex:vert decal:blend // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _RedMappedColor; fixed4 _GreenMappedColor; fixed4 _BlueMappedColor; void vert (inout appdata_full v) { v.vertex.y += v.normal.y * 0.0125; } // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader. // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing. // #pragma instancing_options assumeuniformscaling UNITY_INSTANCING_BUFFER_START(Props) // put more per-instance properties here UNITY_INSTANCING_BUFFER_END(Props) void surf (Input IN, inout SurfaceOutputStandard o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex); c.rgb = saturate((lerp(fixed4(0, 0, 0, 0), _RedMappedColor, c.r) + lerp(fixed4(0, 0, 0, 0), _GreenMappedColor, c.g) + lerp(fixed4(0, 0, 0, 0), _BlueMappedColor, c.b))).rgb; o.Albedo = c.rgb; // Metallic and smoothness come from slider variables o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" } Also, note that I've changed the vertices of the model. I needed a way to eliminate the Z-Fighting and just thought of offsetting the vertices by their normals. In conclusion, It's nothing really special, really. But I'm still working hard on this. EDIT: After a little bit of searching, I've seen that you can give a Z-buffer offset in those Unity shaders by using the Offset state.  So I've then tried to change a bit my previous shader to use that functionality rather than just offsetting the vertices: SubShader { Tags { "RenderType"="Opaque" "Queue"="Geometry+1" "ForceNoShadowCasting"="True" } LOD 200 Offset -1, -1 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Lambert decal:blend // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; fixed4 _RedMappedColor; fixed4 _GreenMappedColor; fixed4 _BlueMappedColor; // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader. // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing. // #pragma instancing_options assumeuniformscaling UNITY_INSTANCING_BUFFER_START(Props) // put more per-instance properties here UNITY_INSTANCING_BUFFER_END(Props) void surf (Input IN, inout SurfaceOutput o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex); c.rgb = saturate((lerp(fixed4(0, 0, 0, 0), _RedMappedColor, c.r) + lerp(fixed4(0, 0, 0, 0), _GreenMappedColor, c.g) + lerp(fixed4(0, 0, 0, 0), _BlueMappedColor, c.b))).rgb; o.Albedo = c.rgb; // We keep the alpha: it's supposed to be a decal o.Alpha = c.a; } ENDCG }  

jb-dev

jb-dev

Unity Daily Update #5 - Eternal Ethernet

Today, I've worked on level exits. When the player arrived at the last room before, nothing awaited him. He was stuck for eternity on the same level. Kinda boring, actually... But today this is no more! Now a big Ethernet port awaits the player at the end of the level. He just needs to jump in it to clear the level.  I've had to create two new shaders: one that can fade the screen to black according to the player's y coordinates. I've also needed to modify my main shader to add a new parameter that can create a gradient from the usual colours to pitch black. This way, I can simulate a bottomless pit.  

jb-dev

jb-dev

Unity Daily Update #4 - Crystal updates

Today, I've fixed some bugs with the crystal throwing algorithm. Basically, crystals will be used by the player to get to those alternative paths I've mentioned in my BPS tree entry. There'll be at least 3 type of crystals : Fire, Water and Life. Each will be thrown to eliminate obstacles at the entry point of each alternatives paths. I've also planned them to be persistent throughout runs. This means that the amount of crystals are linked to a save file rather than a run. So if the player didn't used their crystal during the run, then they'll have the opportunity to use them in another one. As you can see, each type of crystal has a particular particle effect attached to them. I've tried to simulate how each type of elements would react. So the fire crystal particles behaves like flames, life one like fireflies and water one like drops of water. I still have to give them a distinctive shape... For now, I've used the default particle sprite provided with Unity. Also, after a crystal hit something, it'll generate other type of particles. These particle will move accordingly to the impact force. So, to recap, I've been working on particles for the past days... Kinda slow, but I think it's worth it...    

jb-dev

jb-dev

Algorithm The power of the vector cross product, or how to make a realistic vision field

In the previous iteration of our game, we decided to use an actual cone as a way to make an AI "see". This implementation was hazardous, and it quickly became one of the hardest things to implement. We eventually were able to code it all, but the results were really static and not really realistic. Because of the reboot, I took the time to actually identify what constraint one's vision has. The visual field First of all, a cone isn't really the best in therm of collision checking. It required a special collider and could have potentially been a bottleneck in the future when multiple AI would roam the level. In actuality, the visual field can be represented as a 3D piece of a sphere (or more like a sector of a sphere). So we're gonna need to use a sphere in the new version. It's cleaner and more efficient that way. Here's how I've done it: foreach (Collider otherCollider in Physics.OverlapSphere(m_head.transform.position, m_visionDistance / 2, ~LayerMask.GetMask("Entity", "Ignore Raycast"), QueryTriggerInteraction.Ignore)) { // Do your things here } Pretty simple, really... Afterwards (not unlike our previous endeavour), we can just do a simple ray cast to see if the AI's vision is obstructed: // Do a raycast RaycastHit hit; if (Physics.Raycast(m_head.position, (otherPosition - m_head.position).normalized, out hit, m_visionDistance, ~LayerMask.GetMask("Entity", "Ignore Raycast"), QueryTriggerInteraction.Ignore) && hit.collider == otherCollider) { // We can see the other without any obstacles } But with that came another problem: if we use a sphere as a visual field, then the AI can surely see behind his back. Enters the cross product. Vectorial cross product The cross product is a vectorial operation that is quite useful. Here's the actual operation that takes place: \(\mathbf{c} = \mathbf{a} \times \mathbf{b} = ( \mathbf{a}_{y}\mathbf{b}_{z} -\mathbf{a}_{z}\mathbf{b}_{y}, \mathbf{a}_{z}\mathbf{b}_{x} -\mathbf{a}_{x}\mathbf{b}_{z}, \mathbf{a}_{x}\mathbf{b}_{y} -\mathbf{a}_{y}\mathbf{b}_{x} )\) This actually makes a third vector. This third vector is said to be "orthogonal" to the two others. This is a visual representation of that vector: As you can see, this is pretty cool. It looks like the translation gizmo of many 3D editors. But this operation is more useful than creating 3D gizmos. It can actually help us in our objective. Interesting Properties One of the most interesting properties of the cross product is actually its magnitude. Depending on the angle between our two a and b vectors, the magnitude of the resulting vector changes. Here's a nice visualization of it: As you can see, this property can be useful for many things... Including determining the position of a third vector compared to two other vectors. But, however, there's a catch: the order of our a and b vector matters. We need to make sure that we don't make a mistake, as this can easily induce many bugs in our code. The funnel algorithm In one of my articles, I've actually explained how pathfinding kinda works. I've said that the navigational mesh algorithm is actually an amalgamation of different algorithms.  One of these algorithms is the Funnel algorithm, with which we actually do the string pulling. When the Funnel algorithm is launched, we basically do a variation of the cross product operation in order to find if a certain point lay inside a given triangle described by a left and right apexes. This is particularly useful, as we can actually apply a nice string pulling on the identified path. Here's the actual code: public static float FunnelCross2D(Vector3 tip, Vector3 vertexA, Vector3 vertexB) { return (vertexB.x - tip.x) * (vertexA.z - tip.z) - (vertexA.x - tip.x) * (vertexB.z - tip.z); } With this function, we get a float. The float in question (or more particularly its sign) can indicate whether the tip is to the left or to the right of the line described by vertexA and vertexB. (As long as the order of those vectors are counterclockwise, otherwise, the sign is inverted) Application Now, with that FunelCross2D function, we can actually attack our problem head-on. With the function, we can essentially tell whether or not a given point is behind or in front of an AI. Here's how I've managed to do it: if ( FunnelCross2D((otherTransform.position - m_head.position).normalized, m_head.right, -m_head.right) > 0 ) { // otherTransform is in front of us } Because this is Unity, we have access to directional vectors for each Transform objects. This is useful because we can then plug these vectors into our FunnelCross2D function and voilà: we now have a way to tell if another entity is behind or in front of our AI. But wait, there's more! Limit the visual angle Most people are aware that our visual field has a limited viewing angle. It happens that, for humans, the viewing angle is about 114°. The problem is that, right now, our AI viewing angle is actually 180°. Not really realistic if you ask me. Thankfully, we have our trusty FunnelCross2D function to help with that. Let's take another look at the nice cross product animation from before: If you noticed, the magnitude is actually cyclic in its property: when the angle between a and b is 90°, then the magnitude of the resulting vector of the cross product is literally 1. The closet the angle gets to 180° or 0°, the closest our magnitude get to 0. This means that for a given magnitude (except for 1), there are actually 2 possible a and b vector configurations. So, we can then try to find the actual magnitude of the cross given a certain angle. Afterwards, we can store the result in memory. m_visionCrossLimit = FunnelCross2D(new Vector3(Mathf.Cos((Mathf.PI / 2) - (m_visionAngle / 2)), 0, Mathf.Sin((Mathf.PI / 2) - (m_visionAngle / 2))).normalized, m_head.right, -m_head.right); Now we can just go back to our if and change some things: if ( FunnelCross2D((otherTransform.position - m_head.position).normalized, m_head.right, -m_head.right) > m_visionCrossLimit ) { // otherTransform is in our visual field } Then we did it! the AI only reacts to enemies in their visual field. Conclusion In conclusion, you can see how I've managed to simulate a 3D visual field using the trustworthy cross product. But the fun doesn't end there! We can apply this to many different situations. For example, I've implemented the same thing but in order to limit neck rotations. it's just like previously, but with another variable and some other fancy codes and what not... The cross product is indeed a valuable tool in the game developer's toolset. No doubt about it.

jb-dev

jb-dev

Unity Daily Update #3 - AESTHETIC++

Today was kind of a slow day: I had many things to do, so development was kind of light... Nevertheless, I've still managed to do something... I've added a way to highlight items through emission (not unlike how we did it previously) and make enemies blink when they get hurt. It wasn't really hard: because this is Unity, the surface shader got us covered. It was just one simple line of code.  #ifdef IS_EMISSIVE o.Emission = lerp(fixed3(0, 0, 0), _EmissionColor.rgb, _EmissionRatio); #endif  

jb-dev

jb-dev

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!