Follow camera diagonal movement issues

Einar 5 months ago in Game Creator updated 5 months ago 12

Hi, it seems that the diagonal movement of the character is directly influenced by the rotation of the camera (when using a Follow Camera). This is especially noticable when going for an isometric or almost top-down view. Looking through similar topics on the forum it seems that this is by design and not a bug. For instance, look at https://support.gamecreator.io/communities/1/topics/391-directional-movement-not-working and https://support.gamecreator.io/communities/1/topics/382-character-controller-diagonal-movement-issues for previous discussons on this.

But I would expect an eight-direction movement to be on degrees +/- 0, 45, 90, 135, 180. With a camera at an approximate 45 degree angle from above they are instead at +/- 0, 55, 90, 125, 180. The more overhead the camera gets, the closer the diagonal angles get to 90. Is there a way to force movement to use a set forward vector that is not influenced by the camera downward angle? Or do I have to hack the code?

Unity version:
Game Creator version:
Satisfaction mark by Einar 5 months ago

Unfortunately, not without using custom code. It would be very strange though that moving the joystick upwards makes the character move 45 degrees to the north-east point of the screen.

You misunderstand the problem. Moving upwards works correctly, moving sideways works correctly, moving backwards works correctly. BUT diagonally does not. I suspect it is because it follows angles created by a plane projected along the forward axis of the camera, instead of following the ground plane. Which I am pretty sure is what the other threads tried to put into example as well.

So to reiterate: when using a follow camera that looks at the character from an above angle, diagonal movement suffers. The sharper the angle, the more skewed diagonal movement becomes (it becomes more and more like sideways movement)

Here are some quick test results with a standard player (Face direction movement and input type directional) and a Follow camera motor. I've given the Anchor Offsets I've tried and the resulting rotation of the player for each eight way movement:

Anchor offset: X:0 Y:0 Z:-10

Up: 0

Up+Right: 45

Right: 90

Down+Right: 135

Down: +/-180

Down+Left: -135

Left: -90

Up+Left: -45

Anchor offset: X:0 Y:5 Z:-10

Up: 0

Up+Right: 48

Right: 90

Down+Right: 132

Down: +/-180

Down+Left: -132

Left: -90

Up+Left: -48

Anchor offset: X:0 Y:15 Z:-10

Up: 0

Up+Right: 61

Right: 90

Down+Right: 119

Down: +/-180

Down+Left: -119

Left: -90

Up+Left: -61

I think I understand what you mention, but I still believe it's fine. What we do is to get the vector direction from the camera towards the player. Then, we project this vector onto the character's horizontal plane. This way, the resulting vector has no diagonal skew due to different camera angles.

We then normalize the vector, because its magnitude depends on the angle of the camera, which we don't want. So, once we have this unitary vector, it gets multiplied by the maximum speed achievable by the character (and then we apply the necessary transformations for acceleration and delta times, but that's out of the scope).

This last step, is where if the camera looks straight down could cause problems. Because projecting a vector perpendicular to a plane results in a vector with a magnitude of 0. Hence the problems in the post you posted.

Bah, I give up, your first answer had nothing to do with what I was asking, and your second answer clearly has not read the actual numbers I gave. I'll fix the bug myself (and yes, it is a bug, I know of exactly zero eight-directional movement type games where you want the diagonal directions to be anything else than in 45 degrees increments, or arbitrarily affected by camera downward angles).

For reference, if anyone else struggles with this issue, this is what I had to do to fix it. First, find the following lines in PlayerCharacter.cs and delete/comment them out (probably lines 138-142):

            Vector3 moveDirection = maincam.transform.TransformDirection(this.direction);

            moveDirection *= this.direction.magnitude;

Then replace them with this instead:

            moveDirection = Quaternion.Euler(0, maincam.transform.rotation.eulerAngles.y, 0) * this.direction;

This will of course get overwritten if you update the asset package, and it might not play well with the other camera motors, but for a follow camera it works much better.

If you don't want the camera to affect player movement and rotation at all, which can be highly useful for games with camera shakes, multiplayer games with focus features etc etc, it's even simpler, just replace the single line above with the following:

moveDirection = this.direction;

If you want to ignore the camera, but use a different direction as permantly upwards, use something like this (replace 45f with whatever angle you want):

moveDirection = Quaternion.Euler(0, 45f, 0) * this.direction;

Of course, this stuff can be optimized and put into global variables and such, but for prototyping needs this is more than sufficient, and gives a lot more flexibility than the current options.

Under review

Sorry if that came out rude, was far from my intention. I currently have a big pile of emails to answer, but I've opened a ticket to take a more in-depth look at this ticket when I get the time.

Yeah, I apologize for my tone as well, this worldwide cabin fever makes me a bit more grumpy than necessary. I sent you an example project by mail an hour ago to easier demonstrate exactly what I mean regarding the diagonal movement.

Thanks for that! No worries :-) I'll look into it asap.


Quick heads up. Einar, you're totally right. In fact, I would like to post a small GIF of the problem, since you've sent me one of the most clear bug reports I've ever received, which perfectly illustrates the problem.

The solution you propose is what should have been done from the beginning. I'm closing this ticket as the fix will be available in the next update. If any issues arise after that, feel free to reopen this thread. Cheers!

Awesome, thanks!