The User Interface was built using Unreal Motion Graphics which allows for overlaying and animating textures.
FishGibble has many UI systems, including:
- Player HUD
- Compass and Waypoints
- Journal UI
- Level Up UI
- Skill Tree UI
- Main Menu
- Graphics Settings
- Pause Menu
- Conversation UI, including viewing previous conversations.
- Active and Completed Quests UI
Video of Breakdown Here
Some of these systems can bee seen below.
UMG supports animating properties of widget transformations ( translation, orientation and scale ) and brush/texture properties like color and opacity and others.
For the screen alert a texture with some opactiy was created using photoshop.
The alert overlay image was then created as a UMG widget, and placed in the Player HUD widget panel.
Animations play over an animation timeline, that is expressed in seconds. Keys can then be placed at various points on the timeline for various tracks, as mentioned above, the UMG aniamtion system wil then interpolate between these keys as the animation is being played. Animations may be blended by playing multiple animations at the same time, and this is the power of UMG.
An animation was then created with 3 keys on opacity:
- Key 1: 0 opacticy at 0 seconds
- Key 2: 0.7 opactiry at 0.5 seconds
- Key 3: 0 opacity at 1 second.
So the screen tint will flash and then go back to being invisible, over one second. Because the texture has a yellow tint colour on it, specified in the widget, it will flash yellow, but any colour may be used.
This animation was named: ScreenTint
The screen tint animation is played when the character is being hunted, or detected by the AI and being chased. From the FishGibbleUE4Character C++ class, the BroadCastPrey function is called when this state is detected, on the AI character.
This will then in turn calls the HuntingPartyStartedEvent on the player character, or the character being hunted/chased , this is a blueprint event, which is implemented in the blueprint, and not in C++.
This will then invoke the BeingHunted blueprint function. Which will then in turn, invoke the AlertScreenTint blueprint function.
The AlertScreenTint blueprint function, uses a cached reference to the Player HUD widget, and gets a reference to the ScreenTint animation, and calls the PlayAnimation blueprint function, which will play the animation with some properties.
The compass widget is visible at the top of the player HUD, and indicates world orientation of the camera, not the player, because the camera can orbit around the player, the compass will also overlay waypoints on top of the direction markings, to show in which direction relative to the camera, the waypoints are.
The compass widget is made up of the following:
- Compass Background Image ( dark green )
- Compass material instance ( contains compass heading markings ) – parent material : CompassMaterial
- Waypoint Material Instance ( contains waypoint arrow ) – parent material : CompassMaterial
The CompassMaterial parent material exposes 2 material parameters:
- Pan – A Colour ( R, G B and A, where B,A is ignored ) that allows the texture to be panned across the U and V texture space, meaning it can pan the texture left, right, up and down. The texture must be seamless so that no seams can be seen as it moves, and it will appear to wrap around itself ad infinitum.
- Texture – Allows the image itself to be replaced, because the WayPoint material instance also uses this as the material parent, and can also move around independently from the compass markings, but still be represented in the same heading/directional space.
The CompassMaterial will extract the first 2 components from the Pan parameter, and then simply add these values to the UV’s of the texture. The values must always be between 0 and 1. Where 0 sees the N in the middle, and 1 sees the S in the middle ( 0 = North, 1 = South, 1/2 = East, -1/2 = West ) .
The PlayerHUD contains blueprint graph nodes, that it uses to set these material instance parameter values during gameplay, by creating Dynamic Material Instances of each. Dynamic Material Instances, are just fancy words for Material Instances where the parameters may be set during game play, normally material instances parameters can only be set during design time. This is because of the way shaders work, and how they are optimized. We are still somewhat limited with regards to how many parameters may be changed in a given shader and Unreal Engine detects which capabilities your shader will require from graphics based on these parameters, and if they are dynamic or not.
The PlayerHUD creates dynamic material instances from the Compass Material Inst, and the Waypoint Material Inst materials in the event construct of the PlayerHUD widget, and caches these instances for later use into variables that were created in the blueprint of the widget, this is only done if they have not been set, or created already. Creating dynamic material instances is expensive and should be done sparingly, and at the right life cycle of the asset, not in the tick function of the actor or widget for example, that is how your game will run at 2 frames per second.
The PlayerHUD event tick is called every frame, and is used to set these dynamic material instance parameters by calling the AdjustCompass widget function. This function will get a reference to the character player, and then use the CurrentWorldDirection property ( between 0 and 1 ) and set the ‘Pan‘ parameter of the dynamic material instance of the Compass.
Only the first component ( R ) is populated for Pan , as we do not need B,G and A, they are left 0.
It will then do the same ( set the ‘Pan‘ material parameter ) for the Waypoint dynamic material instance, but using the CurrentWorldDirectionToWaypoint property, only if the Player, has a current waypoint set. The waypoint is set from the Quest System.
CurrentWorldDirection and CurrentWorldDirectionToWaypoint float values, are calculated from the tick function of the FishGibbleUE4Character C++ class by calling the CalculateWorldDirectionToWaypoint C++ function.
The CalculateWorldDirectionToWaypoint function uses the Camera attached to the player, and retrieves the Camera Rotation’s Yaw. ( This is expressed in values between 0 and -/+ 359.999… ), this value is then passed to the MinMaxNormalize function, which returns a parametric value between 0 and 1, where 0 = 0, and 360 = 1. If the heading was negative, a value between 0 and -1 will be calculated.
This value is then used for CurrentWorldDirection.
If the quest system, has set a waypoint for the current objective, the CurrentWorldDirectionToWaypoint will be calculated by calling the FindLookatRotation Unreal/Kismet function, and passing the camera and waypoint location as parameters. This returns an FRotator from which the yaw is subtracted from the yaw of the camera’s rotation. This yields the value between 0 and -/+ 360, but if the value is less than -179.999, it means the waypoint will be behind us, and thus not be rendered on the compass markings, so 360 is added to bring it within view of the compass, and then the same MinMaxNormalize function is called to return the values between 0 and -/+ 1 for the waypoint heading.
The MinMaxNormalize function implements a function that yields a value between 0 and 1 from an input value and where it lies in it’s extents ( maximum and minimum ), if the result is:
- 0 means the input value was equal to or less than the minimum value.
- 1 means the input value was equal to or greater than the maximum value.
- 0.5 means the input value, was half way, between the minimum and maximum values.
Negative numbers may also be used for any of the input values. The idea is to find a parametric value ( between 0 and -/+ 1 ), which can then be used to scale something else relative to the input value and it’s extents.