0
\$\begingroup\$

I'm working on an exercise using fixed cameras like how they work in the PSX final fantasy games. I have the camera scripts working fine but it's an aspect of the character control that I'm struggling with.

My character moves relative to the cameras facing position, but when the camera suddenly changes to another angle, my running direction instantly and abruptly changes too. In the final fantasy games it sort of keeps going roughly in the same direction you were briefly.

input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
input = Vector2.ClampMagnitude(input, 1);

// get camera direction
// need to add something here for in between camera switches! 
camF = Camera.main.transform.forward;
camR = Camera.main.transform.right;
camF.y = 0;
camR.y = 0;
camF = camF.normalized;
camR = camR.normalized;

transform.position += (camF * input.y + camR * input.x) * Time.deltaTime * 8;

I saw someone with a similar game comment on an article with his solution, but I don't quite know how to put it into code. The quote;

"Player just gets a rotation based on where the camera is looking and multiplies the character’s motor force by that .forward and .right. I only update that rotation after a big delta in input so you can smoothly move between shots."

This is his small (online) game which he's talking about, I'm trying to mimic the movement basically; https://ocias.com/games/foggy-shore/

Can anyone give me some pointers?


Updated:

It doesn't quite play how it does in the demo game, but it's getting there.

    input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
    input = Vector2.ClampMagnitude(input, 1);

    if (!cameraChanged) {
        _lastCameraInput = input;
        camF = Camera.main.transform.forward;
        camR = Camera.main.transform.right;
        camF.y = 0;
        camR.y = 0;
        camF = camF.normalized;
        camR = camR.normalized;
        
    } else if (Vector3.Dot(input, _lastCameraInput) <= -0f) {
        cameraChanged = false;
        }
    
    transform.position += (camF * input.y + camR * input.x) * Time.deltaTime * 8;
\$\endgroup\$
1
  • \$\begingroup\$ This would be easier to answer if you can more precisely define "It doesn't quite play how it does in the demo game" — what specifically is different? \$\endgroup\$
    – DMGregory
    Jul 1, 2020 at 20:32

1 Answer 1

0
\$\begingroup\$

Here's one potential implementation of this behaviour:

Quaternion _lastCameraFacing;
Vector2 _lastCameraInput;

void Start() {
    _lastCameraFacing = Camera.main.transform.rotation;
}

void Update() {
    var input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
    input = Vector2.ClampMagnitude(input, 1);

    var cameraFacing = Camera.main.transform.rotation;
    // If our camera angle has changed abruptly, 
    // store our current input to compare against in future frames.
    if (Quaternion.Angle(cameraFacing, _lastCameraFacing) > 30f) {
        _lastCameraInput = input;
    } else if (Vector3.Dot(input, _lastCameraInput) <= 0f) {
        // If we let go of the stick, or turn 90+ degrees,
        // switch to using the latest camera angle.
        _lastCameraFacing = cameraFacing;
    }

    // Keep using the saved camera angle for movement.
    var camF = _lastCameraFacing * Vector3.forward;
    var camR = _lastCameraFacing * Vector3.right;
    camF.y = 0;
    camR.y = 0;

    camF = camF.normalized;
    camR = camR.normalized;

    transform.position += (camF * input.y + camR * input.x) * Time.deltaTime * 8;
}
\$\endgroup\$
3
  • \$\begingroup\$ thanks, but there seems to be a bug. In my code it never changes to the new angle after the camera switch. I added a debug.log where the comment 'If we let go of the stick, or turn 90+ degrees' is and that code doesn't run. I am also panning the camera to lookAt player, maybe that is causing it. Edit: On examining the games i'm trying to mimic more, I think its as simple as the new relative camera direction isn't registered until your input changes direction. \$\endgroup\$
    – herewego
    Jul 1, 2020 at 18:27
  • \$\begingroup\$ You likely want to change your way of detecting a camera angle change then. Since you didn't put your camera logic in your question, we had to guess. For a simple approach, you can try changing the threshold angle at which a camera change is detected. For a more robust approach, you can set a flag when your camera changes, and check/clear that flag here instead of comparing angles. \$\endgroup\$
    – DMGregory
    Jul 1, 2020 at 18:49
  • \$\begingroup\$ Thank you, I've been playing at it for an hour or so now based off your suggestions and adding a 'cameraChanged' bool - it's getting close. Edited original answer. \$\endgroup\$
    – herewego
    Jul 1, 2020 at 20:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .