Mouse Control Tutorial
The mouse control is centered around a huge invisible plane marking the zero-Z level. The PlayerController uses a channel line trace to find the XY-position on the reference plane under the mouse cursor. While the ‘MoveTo’ button is pressed the difference in the mouse’s Y positions is used to determine a Z-level that is used for navigation. Releasing the mouse button registers the target position and communicates the position to the controlled object.
The same line trace that scans the reference plane also interacts with all objects in space. If the current line trace hits an object other than the reference plane, a click on the ‘Context’ mouse button triggers the drawing of a context menu by the HUD blueprint. An appropriate variable of the object can be used to tell the HUD what elements should be included in the menu. A ‘MoveTo’ button click on an object triggers a target selection event in the HUD blueprint that causes the HUD to keep a reference to the selected object that is used to trigger the appropriate events of that object when HUD buttons are pressed.
The PlayerCharacter blueprint is basically the default PlayerCharacter with a camera component attached to a spring arm. The Playercharacter has no visual representation and moves on the invisible reference plane while ignoring all other collisions. Standard WASD controls are used to move the character. The mouse wheel is used to control the length of the spring arm and while the middle mouse button is pressed, the mouse movement rotates the spring arm around both axis perpendicular to the camera view direction.
For a more dramatic camera perspective it is possible to attach the player character to an object in space. To do so the HUD blueprints triggers an interface event in the objects blueprint telling the objects to set the characters location to its own location on every tick.
If the camera is focused on the player ship, the movement control mode changes because the ship might be below the reference plane. In this mode a double click on the ‘MoveTo’ button causes the ship to move a point a few thousand units in the direction of the mouse cursor.
To get a feeling how this all works you can watch the first gameplay video I made: https://www.youtube.com/watch?v=rOUSq0GYzUA
The focused camera mode was not implemented at that point but the rest of the interface should become clear.
The tutorial will explain the events in the controller class as well as the HUD blueprint in detail. Screenshots of all important custom blueprint functions are included but only occasionally commented.
The ‘Tick’ event
- The ‘Handle Roll’ node is a custom blueprint function to handle the the input controlling the ships ‘roll’. This part is probably irrelevant for most other applications.
- The ‘Toggle Input Side Bar’ node is a custom blueprint function that checks whether the mouse cursor is currently over the the side bar menu and deactivates input events for the player controller if that is the case.
- The boolean ‘Context Down’ is set to true if the ‘Context’ button (right mouse button) is pressed. If the boolean is true, the HUD blueprint is told to draw the context menu via a blueprint interface.
- The boolean ‘Move to Down’ is set by the ‘MoveTo’ button (left mouse button) input event.
* If 'MoveTo' is down, it is checked whether the button was pressed while hovering an object. The boolean 'Move to Down Over Target is also set by the 'MoveTo' button down event.
– If the mouse button was pressed while over an object a debug line is drawn from the objects location to a location calculated by the ‘Get Orbit Move to Location’ function of the hovered target. The debug line is of course preliminary. The ‘Get Orbit Radius’ function is part of the Playercontroller and calculates an orbit radius from the relative screen positions of the hovered object and the cursor.
– If the mouse button was pressed while not hovering an object, a function is called to calculate the a Z value from the mouse position when the button was pressed and the current mouse position. This code is only executed if the control mode is the standard mode (not focused on the player ship.)
* If 'MoveTo' is not pressed a line trace by channel is carried out (hidden in the 'Update Trace' function.) Depending on the current control mode the hit result is processed accordingly.
The ‘Cursor Instance’ variable is a reference to an object created in the ‘Begin Play’ event. Is is the visual representation that is moving over the reference plane. In my case it is a glowing crosshair.
This function is not working as intended but I was too lazy to fix it yet.
This should be self explanatory.
Doing a simple line trace by channel. I created a custom channel that is only used for this purpose.
Handling the line trace result. ‘Set Cursor Position’ tells the cursor instance to move via a blueprint interface. ‘Get Space Object Under Cursor’ is a custom function that is storing a reference to the object hit by the trace. There is some more code there checking for tags on the object that are used to tell the controller to omit these objects. e.g. the playership is not supposed to be selectable.
Sets the destination of controlled ship to a point far far away if a double click was registered. If it is expected that the ship might actually reach the point, this should be handled differently but it works for my purposes.
The ‘MoveTo’ Event
This one is a little messed up. There are most certainly more elegant ways to do this but this one worked for me so far.
The blueprint is a little bit confusing here: The 'Handle MoveToDown' is executed before the double click check is performed to because the delay in the check part would cause strange behavior.
Not much happens during this event. If the cursor is currently hovering an object, as determined in the 'Tick' event, it is simply noted that the button was pressed while hovering an object. (The MovetoDown-setter could be moved in front of the branch to safe one node. I should probably do that.)
If the mouse is currently not hovering an object the position of the reference plane where the line trace hit the plane is stored.
The mouse's screen position is stored as well for future reference.
The double click checking should be straight forward.
- This is the part connected to the ‘Released’ pin of the MoveTo button event.
The variable 'Move to Down Over Target' was set when the button was pressed. If the button is released, the appropriate variables are reset to 'False'.
If the button was pressed while hovering an object the upper branch is executed:
-- Depending on difference in screen coordinates between the button down and the current mouse's screen position an orbit radius is calculated.
-- If the determined radius is very small, the object will not be orbited and the target is selected instead.
-- If the the radius is above a certain threshold, an interface message is send to the controlled ship telling it to orbit the target while keeping the determined distance.
The lower branch is only executed if the camera is not focused on the player ship:
-- Tells the controlled ship to move to the 'Move to Position' as determined by the 'Get Relative Height' function.
The ‘Context’ button event
The ‘Context’ button (right mouse button) is used to trigger the drawing of a small context menu.
Not much is happening here:
While the button is pressed, a blueprint interface is used to tell the HUD to draw the menu beginning at the current mouse position.
A reference to the hovered object is handed to the HUD as well.
If the button is released, the HUD is told to no longer draw the menu.
This is all for now. I will add the HUD blueprint within a few days.
Feedback and comments are welcome. If I did something stupid, please tell me.