Alright, so today I wanna share something kinda cool I messed around with in Baldur’s Gate 3 – getting that edge panning thing working. It’s not rocket science, but it took a bit of fiddling, and I figured I’d walk through the steps in case anyone else is trying to do the same.
First off, I started by just thinking about what I wanted. I wanted the camera to move when the mouse cursor got close to the edge of the screen. Simple enough, right? So, I jumped into Unity (since that’s what BG3 is built on), and started a new project just to test things out. No need to mess with the actual game files until I knew it worked.
The Basic Idea:
Get the mouse position.
Check if it’s near the screen edges.
If it is, move the camera.
Okay, so getting the mouse position is easy peasy. gives you that. Then I needed to figure out how close to the edge was “close enough.” I decided to use a variable called edgeThreshold – something like 20 pixels or so, just to start. That way, if the mouse was within 20 pixels of the edge, the camera would move.
Then came the fun part – figuring out the screen boundaries. and are your friends here. I set up some simple if/else statements to check if the mouse X position was less than edgeThreshold (left edge) or greater than * - edgeThreshold (right edge). Did the same thing for the mouse Y position for the top and bottom edges.
The Code (kinda):
I’m not gonna give you the exact code, ’cause it’s messy and I’m still tweaking it. But it looked something like this (in pseudocode-ish C#):
void Update() {
Vector3 mousePos = *;
if (mousePos.x < edgeThreshold) {
// Move camera left
} else if (mousePos.x > * - edgeThreshold) {
// Move camera right
if (mousePos.y < edgeThreshold) {
// Move camera down (BG3 has inverted Y, so down is less than)
} else if (mousePos.y > * - edgeThreshold) {
// Move camera up
Now, for moving the camera, I just used . I created a panSpeed variable to control how fast the camera moved. Something like panSpeed = 10f *; Using makes sure the camera moves at the same speed regardless of the frame rate.
So, inside those if/else statements, I added the camera movement code. For example, to move the camera left, I’d do something like *(* panSpeed);. Simple enough.
The Tweaking Begins:
Okay, so it worked… kinda. The camera was moving, but it was janky. First problem: the camera kept moving even after I moved the mouse away from the edge. Duh! I needed to stop the movement when the mouse wasn’t near the edge anymore.
So, I added some else statements to zero out the camera movement when the mouse wasn’t near the edge. That helped a lot.
Next problem: the camera was moving too fast. panSpeed was too high. I messed around with that value until it felt right.
Then I noticed that the camera was moving diagonally when the mouse was in the corner. I didn’t really want that. I wanted it to prioritize horizontal or vertical movement. So, I changed the order of the if/else statements. I checked the horizontal movement first, and then only checked the vertical movement if the mouse wasn’t near the left or right edge. That fixed that problem.
Making it Smoother:
It was still a little jerky, so I added some smoothing. Instead of directly setting the camera position, I used to smoothly interpolate between the current position and the target position. This made the camera movement much smoother and less abrupt.
Next Steps (the BG3 part):
Okay, so I got it working in my test project. The next step is to try and get it working in Baldur’s Gate 3. This is where it gets tricky, ’cause I gotta figure out how to access the game’s camera and modify its behavior. I’m planning on using something like Harmony to patch the game’s code and inject my edge panning logic.
That’s where I’m at right now. I’ll probably post an update once I’ve made some progress with the BG3 integration. Wish me luck!
Update
After fiddling around with Harmony I managed to patch the camera script and inject my code. Turns out the camera script was way more complex than anticipated and required a lot of reverse engineering and debugging. Turns out also that some code were asynchronous and I had to use a different method to change the camera transform.