Don't wanna be here? Send us removal request.
Text
Thesis Week 8 - 12
Since our third critique has a lot of overlap in regards to this particular blog post I’m going to go over in more detail what was accomplished specifically on a week by week basis.
Week 9: This week in particular saw the implementation of as the lock-on camera and target switching system as well as minor additions such as the enemy UI and pop up damage text. The lock on camera was surprisingly more complicated than I thought; although the implementation of the third cinemachine camera that handled the lock on camera was simple enough to figure our the target switching system was not as simple.
Essentially, the targeting system worked through a spherecast added all objects with the ‘enemy tag’ into a list, I would then use a LINQ ForEach method to calculate the distance from the player to each of the enemies and then use a LINQ orderby (and tolist) method to order the indexes from shortest distance to greatest distance. Then naturally, the first enemy targeted when the player clicks the right thumbstick will be the firstordefault value in said list (which should be the closest enemy). The camera is simply a group composer that rotates and centers the targeted enemy on screen while also keeping the player character in the frame.
Okay, now to the more complicated stuff. So basically, the target switching system involves constantly checking the current targeted enemy’s local x-axis through an inverse transform point and calculating which enemy is closest to its positive and negative value on the x-axis (positive being right, negative being left). So when the player flicks left or right on the right thumbstick then it pushes the left or right target to the current target and recalculates the new left and right target according to the new current target. Of course, this calculation is being constantly done so if enemies move further away from the current target’s left and right on the x-axis then the left and right target will adjust and change accordingly.
Week 10: Since the next three weeks cover the animation system and advanced combat system there will be a bit of overlap but I will try to explain what I did specifically in which week. So anyways, this week in particular saw the implementation of the animation system in the player and enemy types as well as the advanced melee system. Firstly, I set up the mechanim node system for the player character as well as corresponding scripts; the animation states that would be added this week in particular would include idle, walking, running, rolling, aiming, and jumping.
Firstly, walking and running is handled by getting the absolute value of the combined values on the x and y axis from the left joystick. This is because I only needed the forward movement velocity and since the character rotated in the direction of movement it didn’t really matter whether or not I used the x or y axis in particular. Anyways, this would get pushed into a blend tree wherein a certain value meant that the player was walking and if it pushed past that then it meant the character was running. The jumping animation worked in a similar manner in that it just got the isGrounded and isJumping bool values from the player controller and used those as animation parameters. The rolling system used the same idea except I switched to root motion during the animation so that the player character transformed along the movement of the animation.
Finally I used an IK Aim Constraint for the aiming animation so that I can blend a strafing animation along with the upper body animation of Donato’s aiming animation.
The melee system would also see a ‘re-mastering’ of sorts as it added its own proper animations as well as a melee combo system and blocking system, I wont explain the former part regarding animations as it works in a similar manner to the locomotion animations mentioned above. Anyways, the blocking system works in that it acts as a collider that instantiates when the player presses the left bumper (which pulls up the block animation). The shield will absorb enemy attacks at the cost of stamina, but if the player should run out of stamina then the player enters a ‘stun’ state where a stun animation is played and controller input is temporarily disabled, leaving the player susceptible to attacks. The melee combo system works in that melee attacks have a counter, so if the counter is 0 and the player attacks it increases the counter to 1 and the next attack should correspond to the next animation. When the counter reaches 3 then the player performs a spin attack for extra damage and the counter is reset back to 0.
Week 11: This week saw the addition of the ‘Basic Enemy Melee Type’ and more additions and refinement to the animation system; in particular, animations for the enemy units. I wont go over the enemy animations specifically in that it works in a similar manner to the player’s animations but the ‘Basic Melee Type’ is probably the most complex enemy type to date.
So basically, this particular enemy type has the ‘Melee Attack State’ which is comprised of many different actions. Firstly, the enemy type has a combo system similar to the player’s but it’s randomized in a way similar to the ‘Heavy Type’. Enumerables ranging from 1-4 get added and randomized in a list using a unique GUID; a specific attack gets played depending on the index of the list. In order to attack however, the enemy needs to get within melee range of the player, so if the enemy isn’t within range then it will attempt to do so. After attacking, the enemy retreats to a certain distance away from the player character, blocks, and either strafes left or right (also randomized). After a coroutine is finished, the enemy enters melee range again and repeats the process. However, the number 5 is ALWAYS added to the end of said attack order and corresponds to a devastating 3 hit combo attack, so every 5th attack the player should expect and react accordingly to this move.
Week 12:
Finally, week 12 saw more work on the animation system as well as general bug fixing. Progress during this week halted for the most part as individuals within the group prepared for finals in other classes, I however, was able to do a lot of generic bug fixing. Mainly, this would mostly be in regards to fixing prominent bugs the animation system such as rotation and timing issues within the code and mechanim node system itself.
0 notes
Link
Well, it certainly has been a while since my last upload; I pretty busy with the build that I didn’t have much time to record gameplay and write out a detailed synopsis. Anyways, in the essence of saving time I decided to combine both week 7 and 8 into one entry as they both involve Enemy AI and have a few overlap between them. Firstly, we have the addition of the NavMeshAgent to the Enemy AI, effectively replacing the old gameObject.transform locomotion method. By baking a NavMesh surface onto the environment, the Enemy AI is able to receive a destination and calculate the closet route while maneuvering through walls and obstacles. Interestingly enough, it also seems to be a lot smoother than the more rigid procedural transform method I used in it’s earlier version. Next, we have the ‘Investigate’ state, I briefly went over this in the Critique two weeks ago but I’ll go over it in more detail here. Essentially, if the AI is in an ‘Attack’ or ‘Chase’ state and he loses sight (the raycast from the enemy to the player is broken) then he will save the player’s last known location and travel towards it. If the player is within detection range and the enemy sees the player then the enemy will re-enter a ‘Chase’ or ‘Attack’ state. If the AI doesn’t detect the player by the time it reaches the destination then the investigation is marked as ‘complete’ and the AI calls the ReturnToSpawn method from the ‘Wander’ state. The next big implementation from week 7 was the ‘Aggro’ state. It’s not exactly a state per se but it works by forcing the AI into a ‘Chase’ state when it takes damage from the Player. It works off a coroutine timer that ‘de-aggroes’ after a set amount of time if it isn’t attacked again. Moving on to the implementations for week 8 we have the first enemy types, starting with the Overwatch, Medic, and Heavy. The Overwatch Type acts as a sort of recon-sniper that feeds information to nearby enemies. Essentially how he works is that once he detects and targets the player, he spherecasts and adds nearby enemies to a list and pushes them into a ‘Chase’ state. Furthermore, the recon also pushes its ‘Target’ reference to the enemies it ‘alerts’. As long as the Overwatch Type can see the player, then so too can the enemies, and if the Overwatch Type loses sight of the player then the alerted enemies will return a ‘Wander’ state and return to their original location. Next is the Medic Type, it acts as a healer that replenishes the HP of nearby enemies. The Medic Type takes the Linq implementations from the Overwatch Type a step further by adding nearby enemies to a list using the same method but it dynamically sorts them by current HP value with the lowest being the first in the list. If any enemy in the list has its current HP lower than its max HP then it stops attacking the player, rotates towards said enemy, and gradually replenishes its HP (visually depicted by a red placeholder line renderer). When every enemy is at full health then the Medic Type returns to an ‘Attack’ state. Furthermore, the Medic Type is able to dynamically switch between targets, for example, if a different enemy’s HP is lower than the one that it is currently healing then it will switch to said enemy. Finally, we have the Heavy Type. The Heavy Type is the prototype for how the boss AI mechanics will work as it works off of an ‘Attack Stack’. Essentially, the Heavy Type has three different attacks (Sweep Right, Sweep Left, and Attack Forward) that is added to a list (through delegates) and randomized through a Linq method. With every 8th attack, the Heavy Type’s gun will ‘jam’, returning a ‘blank’ action that allows the player a chance to counterattack while the Heavy Type can’t shoot. Furthermore, the Heavy’s attack works on coroutine timers; with the attacks themselves being set on a timer so they play out the entire animation/sequence and a short delay in between each attack. During these ‘delay’ phases the Heavy Type will rotate himself and his gun towards the player as he prepares his next attack. Indeed, that was a lot of stuff to go over, but the good news is that the Enemy AI is progressing at a good pace and is working as intended with little to go bugs. The next stage after this is to work on the melee system (on both the player and Enemy AI) and some more UI elements such as enemy health bars and pop up damage text.
0 notes
Link
A little bit late with this week, was busy with the build that I forgot to upload I recorded earlier but I will detail the changes I made up to Wednesday of this week (or last week since it’s 1AM on a Monday right now!). Anyways, this week saw the integration of Enemy AI, handled through a finite state machine. The state machine works by using a custom abstract state class that every state will inherit from, building a dictionary to contain each state (unique instance to every enemy), handling them through a state manager script, and blending between different states by returning other states determinant on specific conditionals. Right now there are three states: Wander/Idle, Chase, and Attack. Firstly, the Wander state doesn’t do much right now but it’s checking if the player is within detection range (visualized by the green sphere) and if the player is in sight. The sight detection is handled through a raycast when the player is within detection range, if the player isn’t in sight (for example if there’s a wall between the player and enemy) then it returns a Wander state, if the player is within sight AND is within detection range then the enemy enters a Chase state. The Chase state is pretty simple, as long as the enemy can see the player and they’re within detection range then the enemy will move towards the player. However, if line of sight is broken then the Wander state is returned and a ReturnToOrigin method is called where the enemy returns to their original location before entering a Chase state. Anyways, when the player is within attack range then the enemy enters a Ranged Attack State. Within this state, the enemy will aim their gun and attack the player. The yellow line indicates a raycast originating from the gun to the player, it rotates the gun towards the player and ensures that the projectile that is instantiated from the gun will perfectly launch towards the player (and right now with 100% accuracy). Of course, a state machine relies on blending between different states. If the player moves out of the attack range then the enemy will enter a chase state and attempt to re-establish attack distance. And if the player exits chase range and isn’t in sight then the enemy will enter a Wander/Idle State.
0 notes
Link
This week saw more improvements to the inventory system, namely consumable items and equipable items. To compliment the equipment system I also added a player stat database which holds certain values that will effect the player’s combat capabilities. And finally, I added the first projectile based weapon in the form of a neat little crossbow. Firstly is the inventory system improvement. To be honest, it’s been quite the unexpected headache as it was more complicated than I originally thought but it works perfectly so I’m pretty happy about it. Anyways, I added a detail panel to the left that pulls the item’s name, enum type, and description from that item’s specific scriptable object. When you click a button it calls the item’s onUse override function; they’re unique for every item but some don’t necessarily have one such as the junk items. The first item I added this week was the health potion, as per it name it restores the player’s HP. I had to beef up the inventory system for this by checking if a specific item’s stack went to 0 in the decreaseAmount method in the inventory system script, when it reaches 0 then it looks up that specific key/value instance in the inventory dictionary using a linq method and removes it. Naturally, the potion uses 1 amount per use and is only usable when the player’s health isn’t at maximum, when the player’s health is at maximum then the potion won’t be used. Secondly, I added an equipment system. Of course, this works through another dictionary (I have a nauseating amount at this point but they’ve been really useful). It works by taking an a key/value of the item’s enum type and a scriptable object. If the item’s enum type doesn’t exist in the dictionary then it’s added, if there’s another enum of the same type as the one you’re equipping then the old one is swapped out with the new one. The equipment items also have stats which are added to the player’s stat database when equipped. In works in the same way with swapping out items in that if there’s an enum type match then the old item’s stats are deleted from the player’s stats and replaced with the new one. This works through a method in the player stat script that takes in a new and old item as a parameter and loops through the stats either adding or removing them. The equipment UI also works in the same way in that a switch statement checks the enum type of the incoming equipment item and adds it to a corresponding panel with the same enum type. Right now it only instantiates the two hats right now for testing purposes as we don’t have the prototype model that we’re going to animate and use yet. Finally, I also added a crossbow. It wasn’t too hard to add since the raycast script already had a script that rotated the currently equipped gun to the center of the screen so all I had to do was pull the Vector3′s (position and rotation) and reference it on the arrow projectile script. After that I add force to the rigidbody and send it flying like a rocket in the Vector3 directions/rotation. The sticking to objects thing was a little thing I added where I froze all movement in the arrow’s rigidbody when collision was detected.
0 notes
Link
This week’s build saw more improvements to the ranged weapon system as well as the implementation of the inventory system and menu.
First, the inventory system was implemented through a list in a scriptable object; this allows for items to be retained through exiting the application or switching through different inventories (such as a tutorial and normal inventory loadout). The objects are kept in a custom class that contains the scriptable object item (which holds data such as the name, prefab, and various unique methods and variables unique to the item type) as well as its current amount. New objects are added to a list through an AddItem method that checks if the item already exists, if it does then it increases its amount instead of adding a new item. Next, items that are added to the inventory instantiate a new panel (with corresponding images) and is referenced to its correct inventory index through a FindIndex Linq method. New panels are also added to a dictionary (class, and panel prefab) so it also works in the same way by not adding a new panel if it detects the same object it picks up through checking keys within the dictionary. The first object in the list is automatically selected as shown by being highlighted by green. When opened the player is able to navigate through the items using the d-pad.
Finally, I added in a shotgun. The raycast script now works by checking how much bullets are shot when fired and if the weapon is full auto or not. I also added some additions to the ranged weapon system to make it look a little cooler. I finally removed the raycast line renderer and added in two particle effects for the weapon; a muzzle flash and bullet impact.
0 notes
Link
Week 3 was a pretty productive week, it saw the additions of the base melee and ranged weapon combat system as well as the accompanying modular scriptable object system to easily add new weapons. On another less exciting note, I also added the basis for interactable objects.
So anyways, the melee weapon system works by using another button press to play an animator that does a slashing motion. The weapon’s trigger collider is only activated for a brief time during this animation and when it collides with an enemy object it deals a set amount of damage. There are currently three different animations: idle, swing, and holster (they’re not final and will be eventually replaced). The animations blend pretty fluidly between each other and are transitioned between each other upon certain trigger events.
As we are probably going to add a sizable number of weapons to the game I transitioned the player’s weapons to a scriptable object data system; this will allow for the easy creation of new weapons and quick implementation into the game without the use of clunky prefabs with a veritable smorgasbord of override/virtual methods and copy/paste functions and variables. Swapping out these datasets are less taxing in runtime and the update loop; it is also more easily indexed and called upon in a database such as a list or dictionary.
0 notes
Link
Thesis Project 2020/2021 - Week 2 Week 2 saw the implementation of the player resource system; several scripts working behind the scene to keep track and change the player’s current health and stamina. So far in terms of stamina I have a simple drain and regeneration mechanic; if the player activates a certain ability then stamina is drained, when stamina reaches a certain threshold (or is cancelled) then the action performed is forced into a false state and stamina regenerates. So far the only stamina draining action is a simple sprint but it shouldn’t be difficult to link other actions to the resource. Next is health, it doesn’t really do much for now except take damage when the player touches something bad. I put the damage method on a simple corutine so there’s a small delay between damage ticks. The last thing are the sliders at the top; they are linked to a public float that holds the player’s current health. It’s nothing final and in the future we can change it to something more animated and snazzy.
0 notes
Link
Thesis Project 2020/2021 - Week 1 With my schedule cleared up and the fall semester starting; work has officially began for our game. With the base mechanics looking fairly good so far I decided to build upon the projectile system. Using the ADS system from the previous build, a raycast is now fired from the camera to the center of the screen. Another raycast (one that is visible) is now fired from a transform point (I placed it on the character’s eyes for now) to that center point on the screen. It doesn’t do anything so far but in the future it wouldn’t be too difficult to sprint a simple hit cast weapon (like a sniper or beam weapon) or set the starting trajectory for a projectile based weapon that is affected by a downward velocity (like a cannonball).
Next, I also fixed a very frustrating and longstanding bug. Unity comes with its own ground check with the character controller component and it’s a buggy mess; both fellow Unity developers and the Unity team themselves know this so it’s a bit of a hit or miss. I myself ran into some problems as the ground check wouldn’t work if the player walked backwards. I implemented a more reliable ground check using a raycast sent from the center of the player to the ground. It’s just longer than the player’s radius so when the raycast hits something with a specific tag (the environment) then the player is grounded and their downward velocity is halted. Finally, with this fixed I was able to add a simple double jump using an ‘isJumped’ conditional within the initial jump method.
Interestingly enough, I found certain flaws with the new input system when coding the double jump. During my initial tests I found that the jump would fire twice and this was because of a set of phases that happens when a button is pressed; started, performed, and cancelled. It’s weird, but I put a temporary band-aid on it for now by putting a passthrough and tap interaction on it to skip past the started phase.
0 notes
Link
Thesis Project 2020/2021 - August
To start off our thesis for the fall term we decided to get a good head start and build a good foundation for our game; for my role as the main game dev/programmer that would include creating the core mechanics, controls, and scrips so I have something to build upon in the future. The goal for this month was to set up the main character controller. This would be made using the new input system within Unity. The new input system is both good and bad in many regards but this is something I might touch upon in a bonus post. Anyways, the input system works through getting values through a controller (with different actions and interactions) and using it within your scripts. You can interact with these values as a callback context as a parameter within a method and call on it through an event in runtime or use to get the Vector2 value of a joystick for example. Anyways, back what was added in August. I was able to add the more fundamental gameplay components such as basic movement through a flat plane (2 axis), a jump (through the y axis), gravity/velocity so that the player is always pulled down when not grounded, a ground check (using the character controller component), and player rotation (player will rotate towards the direction they are moving in). Lastly, I also added a third person camera using cinemachine. Currently, it rotates around the player in an orbit and collides with walls (so it doesn’t go through the wall or gets stuck). In addition, I also added a basic ADS (aim down sight) system for utilization at a later date.
1 note
·
View note