Northmen Winter's Howl

Game Design Document

Analysis Report

Game Trailer

Gameplay Video

Tags

  • Unreal Engine 4
  • Blueprint Scripting
  • Landscaping
  • Level Design
  • Black and Behaviour Trees
  • Animation Blueprints
  • Mesh Retargeting 
  • Procedural Generation
  • Event Handling
  • Data Tables, Interfaces, Enums, Structs, etc. 

Responsibilities

  1. Downloaded real world terrain height maps using L3DT to create the island.
  2. Used a free modular character asset and replaced the mesh for the Unreal mannequin with it
  3. Created the blueprint system for spear throw and animal damage system
  4. Used the volumetric clouds system and new sky to give better lighting
  5. Created a day night system by updating the rotation vector of the primary and secondary lights in the atmosphere
  6. Navigation Invokers were used to optimize the game’s AI
  7. World Machine was used to create the level map

Project Creation Description

This section is being Improved and Updated....Please Wait. Thank you!

Map

In order to create a proper atmosphere for the player character and lead into a proper Immersive mood, research had to be done on the creation of the playable map level. This required looking at the topography of the region in which the Vikings had resided. Particularly the area around Norway, Iceland and Poland. As our game was taking Inspiration from the T.V. series, “Vikings” I researched where was the main area where the Vikings was shot. 

As it turned out, the area where the main Village of Kattegat was situated was neither of the areas that I had researched as aforementioned.  The series stage was set in Ireland at Lough Tay, near the Wicklow Mountains. However, as the topography of that area matched with the Norwegian landscape I was easily able to take inspiration without any setbacks.

I had three options regarding the creation of the map. The first option was to, as in previous projects, take the real world location of Lough Lake. However a drawback of this was that there would be a very abrupt end to playable location and the area’s shown in the series Viking’s were cast in multiple areas with a lot of VFX editing. 

As such it would become very counter-intuitive to take the real world location.

The second Option was to create the landscape area inside of Unreal Engine by sculpting. This would give me greater control over how I wanted my landscape to be. However, one of the biggest problems regarding this would come from the fact of the sheer scale of the landscape in question. A small area could be implemented rather quickly but for a large area that was in the plan of the game it would become almost impossible to create the whole game in the deadline. It would furthermore, require a lot of knowledge regarding the geology of that area and how natural elements affected and created the features that exist in areas like Norway, Poland and the rest.

As such the third option, which I opted for, was to design the tool in a third party software. With my previous knowledge of World Machine and its limitations, I begin to look towards an alternative software. The two alternatives I had were Gaia and World Creator. Choosing them was a matter of personal preference so I decided to create the level in World Creator.

The level bounds were decided and after looking at the features and the workflow of the program I started crafting my game Environment.

Screenshot 1

Map Full View

Screenshot 2

View From Village Area

Screenshot 3

Mountain covering from right side

Screenshot 4

Mountain covering from left side

Screenshot 5

Scale of humanoid to landscape

Screenshot 6

Some of the erosion and topological features in the map

Screenshots from inside World Creator

The following screenshots are form the finished product of the map in World Creator. As it is visible, the map was made large so that the player has enough places to explore while having the thrill of finding scenic spots to enjoy the game world from. There are many topographical features on the landscape that were implemented using hydro erosion and wind erosion from the landscape coming into contact with the natural elements. These were researched after looking at the climate of the relevant areas.

World Creator

Unreal Engine

A comparison after import into Unreal Engine

After the finalization in World Creator, the map was imported into Unreal Engine. A thing to remember while importing maps into Unreal Engine from World Creator is to note the Game Engine Scaling Settings inside of World Creator and tick on Flip Y in export settings. 

The final version of the map came out to be a 4064×4064 texture. Detailed enough to allow good tessellation. 

Map: Inside of Unreal Engine

After the import of the map, I began working on setting the map bounds of the level. There was a clean cut off from the two hills at the side of the Village which would show the map being hollow. So in order to cover them up, I used a 3D rock cliff from Quixel Bridge which with different rotation and scale values, I made a cliff face. This would cover up the rock face and allow the player to interact with the area without losing immersion.

However due to the shear amount of cliff faces, it would become prevalent that there would be a lot memory draw from rendering the high poly cliffs. This is where my team and my, decision to use Unreal Engine 5 came into effect. Due to the new feature implementation, called Nanite we were able to implement thousands of high poly assets, with minimal draw call due to better vertices draw calls.

 

Lighting and Weather

The next step in the game development process was the creation of the lighting and weather system. I had previously experimented with the lighting system and tried implementing a rain system for the player however, for the purpose of balancing the scale of what we should make vs what we should use readily available to us, my team and I decided to purchase the Ultra Dynamic Sky and Weather system. Which came ready with a lot of presets and ability for integration into other aspects of your games such as wet and snow weather effects on your landscape and asset materials. This rid us of the complexity of designing the complex weather and lighting presets which would be optimized and be scalable.

Default Unreal Lighting System

Ultra Dynamic Sky Lighting and Weather

Foliage and Landscape Textures

As usual the method for foliage implementation was through the use of Procedural Foliage Volumes. First the Blocking volumes were laid around the map, where the residence of the buildings was supposed to be. Then for the foliage I had to search for trees that were local to the region. On searching I was able to find those trees.

The list of them being 

  1. Birch
  2. Alder
  3. Pine
  4. Sorbus
  5. Aspen
  6. Willow
  7. Oak
  8. Common Hazel
  9. Prunus

The problem however arose from finding high quality trees that could be available. There were several attempts at the beginning by using tree’s from old asset packs, however their graphical fidelity was not up par with the rest of the landscape and they had to be quickly dropped. 

I moved towards creating custom trees in a third party software called “Tree It”, however the it was also very low poly and did not match the consistency of the scene.

Through the Unreal Market’s Learning tab I was able to find the course for the Haunted Village through which I extracted the Pine Cone trees and implemented them into the game. They worked perfectly and had fake placeholders for the far viewing LOD’s. 

However, later on I was able to find better trees with the release of Quixel Mega trees pack which I quickly implemented into my game. they had the option of changing their tree colours and the amount of leaves visible according to weather control settings, which would latter allow integration with the UDS plugin for scalability purposes.

Further foliage was implemented in through the landscape material where the grass was changed and shrubs were added for grassy areas.

Brushify’s Moorlands pack was used for the landscape material and with a few changes in the beach material’s and material functions I was able to cater the pack to our personal need. The UDS system was also integrated into the landscape material in order to allow snow and rain weather effects for the game.

Another step taken was the implementation of Heightfield mesh system in the game as the old system of tessellation was deprecated especially with the use of Virtual Textures. The new system was the Virtual Heightfield Mesh system which would take into account the world location of the object on which the material was applied as well as the height of the material through the World Height Texture.

Old

The old landscape material from my game, “Tribal Wars”.

New

Brushify Moorlands Material with heightfield mesh implementation. 

Player Character

Creation and Retargetting

As in our game’s direction, we had decided to implement the new Meta-humans in our Game. The reason for doing so was inline with our goal of Immersion. The new meta-humans completely changed the way characters were designed. Their realism at such low an cost of entry in terms of experience was very beneficial for our group who did not have a large pool of experience and time to create realistic characters. 

The attempt to start the creation of the metahuman began inside of the metahuman creator from Quixel. I created a basic template for a very stereotypical Norse Viking character which I imported into the game. 

However from here on, the task of creation just became expensively more difficult. With my previous experience of just changing the body of the base mannequin character in Unreal Engine incompatible with the new character, I had to learn all about the retargeting system in Unreal Engine. At that time, Unreal Engine 5 was in Beta, and as such the previous system was much more difficult with manual bone mapping and creation of Animation blueprints. However later on with the full release of the Engine, I was able to to create utilize the new system in which I create the IK Rig for the Meta Human and the default mannequin and then created an IK Retargeter to chain map their bones and shift all animations on to the new Character.

I also started from scratch for creating the Third Person character template which then I had to change in the world setting. There were several problems furthermore in the metahuman character such as the LOD levels of the character removing the hair and the facial animation blueprint which would not work and cause problems due to the implementation of the live link plugin for facial capturing. I had to edit the facial Anim blueprint by removing all connecting pins to the TLL link so that the animation would not depend on it however this caused the hair on the groom to not work as well

Animation Blueprints

After the creation of the Animation blueprint I had to work on the import of animations. For this I used Mixamo. 

The initial process, which worked in the beta, involved uploading my mannequin character to Mixamo and then downloading animation to it and then retargeting them when importing them into unreal to the new metahuman base skeleton. However this caused problems later on as the there was no root bone for the old Mannequin (Not Lyra) which meant no root motion which was essential to some of the animations. 

In order to change this and make the animation retargeting work again after the full release I downloaded the Xbot character from Mixamo and then brought into Unreal Engine as a completely new Character. I then created an IK Rig for the Xbot character and using the IK Retargeter mapped the bones from the Xbot to the metahuman character. 

 

After which the process of animations involved downloading the animations from Mixamo on top of the Xbot character and then importing them on to the character skeleton in Unreal Engine. This was then used in the Retargeter to retarget those animations on the character. Some problems that may appear during this process were the incorrect placement of the arms and rigs as the IK Retargeter did it’s best to map an Unequal number of bones in the Xbot to the metahuman. A quick fix was to change the base pose of the metahuman in the IK Retargeter and change the FK and IK Adjustment Interpolation for translation or rotation depending on your problem on a selected mapping.

The process after that was to import all relevant animations in to the character and retarget them. I furthermore decided to use the Kobold Sword Animation pack in order to improve the animations for the attacks which were limited and very much non-consistent from the Mixamo webpage.

These animations were also retargeted from the kobold skeleton on the Unreal Skeleton.

My knowledge at the start of the project regarding Animation Blueprints was very limited and I wanted to improve on that by working on a more complex system than the basic implementation of playing animations from the character on a key-press using Play Animation or Play Animation Montage.

This led me to delve into a animation system by AngelV, called AGR Pro, which was essentially a group of tools to extend and open up the animation system. I used this system to completely overhaul the main Character’s animation Blueprint system. Through which I was able to learn about Conduits, Transitions, Bone Blending and other essential concepts to make sure the character remains in a position according to its state machine. This new system was also implemented in the Animals AI, as the previous system was very erroneous where animations would get cancelled and have no fall back behaviour and the character would be stuck in a loop. Same was the case previously for the player character.

Animation Notifies and skeletal animation notifies were also used to make sure that certain events were only triggered in a certain stage of the animation. 

Player Character Logic Setup

Event Graph of the Player’s Character

The landing event for the animation blueprint was handled inside of the player character’s blueprint.

In Event begin play the Character’s weapons which were attached on default to the weapons sockets were saved as references by casting to their parent class. Several other variables were casted and saved so that they could be used later when required and not be casted numerous times.

The health UI for the character was initialized from the very beginning so that the UI could reflect the player’s health at all times.

Basic Input Template

For the Input the, the code was copied form the mannequin’s template. The few additions made were the use of an Interface call to switch the “Can Move” bool on and off, which was linked to the “MoveForward” and “MoveRight” InputAxis Mapping. This was added as a failsafe and for control in certain aspect’s of gameplay where the chracter’s movements needed to stopped. Such as when the character was stunned or performing a certain heavy attack or was in the midst of an Animation

Custom Inputs and Event Tick

The next area of updates are the custom additions to the input actions and the custom Input Action Mappings. 

In the Event tick off setting we have a sequence of events firing off one after the other. The first one being the LockOn mechanism. As I will explain further on, the LockOn mechanism is only triggered if the bool for locking on is triggered through an interface call. If it is set to true then the position between the player character and the locked on Enemy is R interp’ed.

Initially I had set the character’s rotation to be changed however this caused problems in which the player’s controller would not change the direction and there would be some funky movement. As such, I decided to change the control rotation of the player’s controller, which would change the controlled mesh’s rotation as well as the player’s camera rotation towards the Locked Actor/Character.

The next sequence of event’s were in the case if the player character sits. Throughout the world there are places where the character can sit and enjoy the view while the music in the game plays. This was to allow for a sense of immersion and enjoyment and furthermore, make the player want to explore more areas. The sitting bool was triggered when sit colliders in the world would send information to the level blueprint to search for player input to sit down. If returned true, the bool in the character would be changed stopping the player from moving and setting the IsSitting boolean on in the character’s animation blueprint which would lead to the IsSitting State.

The last sequence is the set Timer by Event node which was bound to the custom UpdatePlayerState event. This event would trigger after every 1 second and increase the player’s hunger aka decrease satiation and if given necessary conditions of fulfillment regenerate the players health.

The InputAction for Crouch does what it is named after. However, in order to add a bit of smoothness to the switching between the two states, a  camera lag was added

The Input buffer was one of the most technical works implemented in order to allow caching of the attack actions. As such the buffer will be described in detail in a separate section

The OpenInventory Action mapping is very simple in which the created inventory was added into viewport and the game mode was changed accordingly.

The PickUpObject Action starts with the validation of the food item that would be picked up in case it became out of reach. After this the next step of validation was to compare the price of the object and the current loot the player had, in the case he was buying an object from a shop. Given those scenarios, relevant actions would take place, such as the playing of an animation and adding the object to inventory or showing a tooltip warning regarding the lack of loot of the player. 

the ToggleHandIK is an interface call which allows given a Boolean output whether the IK adjustment should be done or not. Again after validations regarding the food object, information is sent to another interface call which is attached to the character’s animation blueprint which then assigns the location of the alpha and IK target location for the movement of the hand.

The last InputAction is for interacting with the shops that are available. These shops would then show the menu to player from which the player can buy food or other items.

Weapon Equip And Unequip

The next stage of player character’s setup involved the creation of the equipping and unequipping of weapons. From the very beginning of the game play the player is given a sword, a spear and a torch for him/ her to utilize. Each of these tools are equipped and unequipped through a separate Input Mapping i.e. 1,2, and 3 for the sword, spear and torch respectively.

For each of the respective mapping’s the process starts by first check if a previous weapon is equipped, if it is equipped then it is firstly unequipped, unless if it is a torch, and then the procedure follows by initializing the proper animation by alternating the state in the animation blueprint using AGR Pro’s tag system. After this the custom event for equipping the tool is called where the socket information is fed into the “AttachToComponent” Node and the weapons are switched from the weapon’s placeholder sockets to the appropriate holding socket in the hand. All of these sockets created in the skeletal mesh of the player character.

Heavy and Light Attack System

I would like to apologize for the spaghetti links, I use a node plugin to keep my nodes more clean. I promise!

The system’s implemented above follow through by firstly checking if the player has a weapon equipped or not. Given the condition that the player has the weapon equipped, it then distinguishes whether the weapon is a spear or sword leading to last check which is to see if the player is in a state where they can attack. 

The last check was introduced in order to stop the animations from playing and canceling each other out. After which the movement of the player is stopped to stop animation interruption.

I tried to implement a function using a mapping for the animations and integer values however due to errors I set forward towards a suboptimal solution which was to use a random attack (heavy or light depending on the Input) to play the animation.

Theoretically, the function would assign a a float value between 0 to 1 to give each attack a percentage chance to be done. However, due to logical errors (quite possibly, the implementation was not perfect) hence due to a limited availability of time and resources, I moved on to the next part. The next part of the sequence was to play the animation montage on the skeleton and in those animations which had a skeleton notify, I added the player’s input into the system and activated the collisions for the weapon. This was so that the collisions would take place only in the case of attacking and not when the player is just holding his weapon. The latter was seen to cause damage to NPC’s randomly walking by.

At the beginning of the notify, the input buffer was switched on so that the player’s input could be stored and at the end of the buffer, the player’s input was not taken into account but checked form the command list whether the player had any input or not. 

The command list array was a custom data struct that was created in order to name the Input commands that the player had to use in order to do a certain attack. The first entry was for light attacks and the second was for heavy attacks. If the player had used the light attack command then, it would remove the input from the buffer and play the next attack animation, if it wasn’t a light attack then it would check for the second command which was for heavy attack and move on to that or end the process entirely.

At the end the next execute was to play the attack grunt sound which is undesirably simple to say the least.

Combat Continuation

This continuation starts with a very simple event which is the take damage event. I will not go in to much detail regarding this as all of it is very descriptive however I will elaborate on the collapsed graph for the TakeDamage Sequence which if you double click on will expand and show the information that I will explain. In summarization the collapsed graph starts with the playing of a audio cue for the player from an array of sound cues. After which it is checked whether the attack from aggressor is a light attack or a heavy attack. 

In the case of a light attack, a counter is set-up so that the player is not stun locked and an iterator checks and increments the value of light attacks. Once the light attack value reaches the stun value the on hit animation is played which a root motion animation. and the counter is reset to 0 so that the player is not stun locked in combat due to a bad move.

I will explain the Aim and Throw Events at the end of this segment as they are related to the weapons system which will be the next topic of discussion.

The PickUpSpear Event is very simple and is called form the actual spear blueprint on collision. This event just adds the spear BP to the inventory and toggles the spear thrown bool to off in order to allow the spear to be thrown once again. it must be noted that the spear itself does not go into the players hand as then it would require the case of making sure the player is not equipped with a weapon and delay the combat process leading to undesirable gameplay especially in the midst of combat due to animation and state switching.

The second event is majorly utilized in the inventory system for the player (Elaborated later) where on usage the spear which has been saved in the item slot in the AGR Equipment manager is made visible and added to its relevant weapon socket on the player. The collisions are also henceforth disabled to make sure that the spear does not cause damage in a holstered position.

The GainReward Event feeds information into the RewardToBeGained interface function, which is attached to all NPC’s. All of the NPC’s carry rewards or Punishments. On Receiving the information the reward is showcased on the player’s screen as a tooltip to give information while all relevant prestige and loot bonuses or cuts are adjusted into the player’s stats.

The player prestige calculation function works by using an integer to integer map which checks if the acquired prestige is below a level’s threshold and then formally adjusts and increases or decreases the prestige value and/or level.

If the level was upgraded then a tooltip is presented to the player showcasing his increase in the prestige level.

The last two events to cover are the Aim and Throw events. The aim event is an InputAction Mapping which checks if the held weapon is a spear and then adds the aim widget to the screen and on release removes it. It furthermore lerps and changes the player rotation speed, movement speed and camera view angle. The latter being smoothly lerped based on a timeline.

The Throw event is also very simple and basically based on the event notify for the throw animation detaches the spear from the actor and set’s its throw damage. After which it calls on the relevant event on the spear itself.

Lock On Mechanism and DamageBPI

In order to better understand the logic behind this my recommendation to the reader is to pan the above blueprint frame to the right.

On the right side, we start from the input action event for locking on, which is the scroll button on the mouse, on clicking that button a sphere trace is done for all pawn objects, this array of objects is checked to see if they implement the BPI_NPC_Info Intercace call and in that call if the interface function isAttackableByCharacter returns true. Given these prerequisites are fulfilled, the LockOn interface function is called and set to true with the LockedOnEnemy argument being filled with the traced actor. After which the camera position is offset allowing for a more cinematic combat experience. In the case where the trace does not return an attackable actor, the reverse is done. 

In the interface call, Lock On, the conditions are checked and the Aim offset using the AGR Pro plugin is set up to properly setup the rotation of the character towards the enemy.

The Event DamageAmount, is an interface called from the aggressor, in the case of a successful hit on the player. The damage values and the bool for light attack is set after which the previously mentioned Take Damage Event transpires.

Weapons System

Models created by:

Meraal Mathar

Meraal Mathar

Asset Designer and Researcher

Meraal was the lead asset designer due to which we were able to create the designs for the sword and spear as well as the UI. She furthermore, majorly contributed to the documentation and User Testing report.

Explanation

Spear Parent Blueprint

The spear blueprint is more technical in its implementation. the implementation was primarily taken from the work of Lewis Fiford. Whose work can be accessed by clicking on the image.

Sword Parent Blueprint

The Sword base Blueprint Class is very simple. The mesh component of the blueprint has a begin overlap and end overlap event which checks if the overlapped actor has the damageable by weapon blueprint interface implemented or not and then given that uses a do once node to apply damage via the Damageable by weapon BPI which was mentioned prior in the "Lock On Mechanism and DamageBPI" heading.

Explaining the Spear implementation

The Component Begin Overlap node checks for the implementation of the relevant so Interface so that the damage is only applied to actors that can be damaged.

If the condition is set true then it is checked if the overlap actor is the owner of the spear. If it is not the owner then information is passed to the Damage amount Interface to the target hit actor so that damage can be applied.

In the case that the overlap function is triggered for the owner character it is checked to see if the actor is the player character or not. If it is the player character and he has thrown the spear then the relative rotation of the spear is corrected (this is done so that on attachment there are no issues with the parent socket transforms) , if it isnt the player character then the owner character is casted to the NPC parent class and checked to see if the spear was thrown and the same process is repeated.

After correcting the relative rotation, the pickup spear event is called for the player character.

Explaining the Spear throw event

The Spear throw event starts by setting all the appropriate variables and then snapping the trajectory of the spear to the player’s perspective from the camera HUD. Corrections are made to the throw axis so that the spear is thrown in a straight line.

After the spear has been set to the initial position the projectile movement component is activated and the velocity of the throw is set by taking the throw vector and multiplying speed to it.

A timeline is created which stops the movement of the throw if the stop spear function is called. Upon the throw, a line trace is started from the actor to a certain area ahead of it in order to trace any collisions that might happen. 

On successful collision hit data regarding the location, normal and if a skeletal mesh, bone name is stored. The spear is also stopped from movement by turning off the projectile component from the stop spear function as well as the timeline for the spear trace.

The hit actor is casted to the base animal blueprint and on success the Hit AI ref variable is stored which is used in the lodge spear function and attach to actor collapsed graph.

The lodge spear function works by setting the actor rotation to player’s camera rotation which we previously stored. After which it changes the relative rotation of the lodge point to the hit location by changing the x and y value from a random range. The spear location is also adjusted to the hit actor/object’s normal.

Inventory System