Here’s how you can make a top-down style camera that - while in “aiming mode” - pans when you move mouse to screen edge. One game that uses this style is Project Zomboid.
Features:
- Camera panning with limits
- Two styles of aiming mode: click and hold or toggle
Prerequisite:
- I am using a node from the free Low-Entry extended library (Get Mouse Position(Percentages)). Grab it on the marketplace for many helper nodes.
Preparation:
- Make a new project using the Top Down Template.
- For panning, on the TopDownCharacter, we will be adjusting the camera spring arms TargetOffset and SocketOffset parameters. It seems a little confusing to use two different parameters like this, but I found it to make for simpler code compared to adjusting the position of the spring arm directly, or a few other methods.
Step 1:
Get your mouse position on the screen. Plug in a print string so that you can see what numbers are equal to the edges of the screen. These numbers I have put into the variables ScreenEdgeHi and ScreenEdgeLo.
(I am using the values 0.9 and 0.1)
Note:
You should probably just work on one mouse axis at a time. Once you setup one, the others are mostly the same. Make sure you use Print Strings to understand what you are doing as you go along.
Also be aware during your testing that if the PIE window is not maximized, you’ll have jumpy behavior if you go off the screen edge. Press WindowsKey+Up Arrow x 2 to maximize the window.
Step 2:
For the Mouse Y - If the mouse position is above the ScreenEdgeHi threshold, then we are going to increase the Spring Arms TargetOffset.
Here’s how that is done:
PanSpeed I have set to 1800. Note that we are multiplying by Delta Seconds to ensure frame independence. Ensure that you are using the TargetOffset here, not the SocketOffset. When you test this out, if the camera flies up into the air, you used the wrong parameter.
If the mouse position is below the ScreenEdgeLo threshold, we are going to do the same thing but note a couple key details:
In the TargetOffset function I have the Invert input parameter unchecked. You don’t need to think too hard on that - just if you are panning in the opposite direction as expected, check the box.
But what about that Branch inbetween? Checking for a view distance limit? If you don’t want your players to be able to pan forever, this is where you can set a limitation. Set it to something low like 500 for quick testing to get started.
Pay special attention to the Great than and Less than comparison nodes - if you are having trouble getting panning to go the way you expect, look over those nodes carefully. Invert one at a time to find the problem spot if you need to.
Step 3:
Mouse X is the same deal, except note that we are using the SocketOffset here:
That takes care of the panning behavior.
But right now it is going to pan anytime you hover to the edge. We want to only pan if in aiming mode.
Step 4:
Make a custom event:
For now, disregard the ResetCam. Just make the boolean and set it to toggle using a NOT.
Step 5:
You’ll call this custom event with Right Mouse button, or w/e input you want:
Again, disregard the other nodes for the moment. Just call the custom node.
Step 6:
Now use the AimMode boolean to flag entry to your MouseX and MouseY events:
Awesome. Now you have a function toggle for aim mode. Next let’s make it so that when you toggle off aim mode, the camera will reset smoothly.
Step 7:
Make a custom event called ResetCamFeeder. Call it from Tick.
If you want, you can add this PrintString helper to tell you when AimMode is on. Click the dropdown on the print string node and set the duration to 0.
Step 8:
“Feeder” is a name I give to custom events updated from tick that’s sole purpose is to feed a gate. Maybe there is a real programming term - I dunno. It’s mostly to keep my blueprint graphs clean and legible.
Setup a custom event for open and close the gate. You don’t have to use custom events for this, but if you try to do it the other way with many different noodles stepping over each other to get into the gate, you’ll start feeling like a moron pretty fast trying to figure it all out.
Inside the ResetCamPosition collapsed node:
Just setting the SocketOffset and TargetOffset parameters back to 0,0,0. The Vinterp node is what makes it smooth. ResetCamSpeed is what you can use to control how fast or slow it resets. Lower is slower.
Instead of a tick gate, could you use a timeline instead?
I am not sure. I tried it but couldn’t get predictable results. I have not really used timelines so I might have done it wrong.
Step 9:
Now you can call that ResetCam event when AimMode is toggled to false. Test it out!
Awesome. Now you have a fully function aimmode panning functionality. But some players don’t suffer from RSI like us developers do. They probably would like a click-and-hold aim-mode option.
Step 10:
Make a blueprint enumerator and add two elements to it:
- Hold
- Toggle
Add that enumerator as a variable to your character blueprint.
Now you can switch on that enumerator on the right mouse click like this:
That’s it!
Note that for simplicities sake, I just do all this work directly on the character blueprint and am using raw key events. That might not be the approach you’ll need to use for a full game project, but it makes for easier experimentation when you are trying new things out. It helps to figure new systems out in a fresh project. That way you don’t get side-tracked with the extraneous complications of integration into your larger system.
It’s two step process - figure out the nuts and bolts of new system in isolation, then figure out how to integrate into the larger project in an organized way.