Forum rules - please read before posting.

Camera projection matrix change undone on camera switch

edited March 7 in Technical Q&A

Dear community, dear ChrisIceBox,

I'm manipulating the projection matrix of the active camera at certain points of my game, but whenever the camera is transitioning, the change becomes undone. Now I know that there is the OnCameraSwitch event, but I wasn't able to solve the problem using it (I thought I could change the projection matrix of the "toCamera" in the subscribed method, but that doesn't work and I'm not quite sure why, maybe the transitions are changing/resetting the projection matrix?).

I solved my problem with a Coroutine that uses the transition time of the OnCameraSwitch delegate parameter to change a variable (_isCameraTransitioning) to false that is set to true at the beginning of the subscribed method and in Update, it keeps setting the projection matrix of the active camera every frame if the variable is set to true. That works but I'm not super excited about this solution.

Is there a better way to do this?

Comments

  • Welcome to the community, @Psychonaut.

    What are your AC/Unity versions, and what kind of Cameras are you using?

    AC will affect the projection matrix of the camera under certain conditions - the main one being 2D Cameras that use Perspective projection. This is to ensure perspective doesn't shift when such cameras scroll.

    Alternatives may be to either instead affect the MainCamera (which ultimately what performs the rendering) in LateUpdate, or to use a custom camera script (attach AC's Basic Camera to a new Camera and use a separate script to move it as needed).

    If you can share more details on exactly how/what you're manipulating things though, I'll see if I can give more specific advice.

  • edited March 7

    Thank you so much for the quick reply, your dedication never ceases to amaze me!

    I'm using Unity 2022.3.19 and AC 1.79.3. My game is 3D and my Cameras are all set to Perspective, although I'm not certain what you mean by "2D Cameras", but I guess it's because I'm not using them.

    My exact manipulation looks like the following:

    There are two states of the game, one where the camera is normal and one where it is flipped horizontally. The player can interact with a hotspot to switch between the two. All cameras should be manipulated in "flipped mode". Pseudocode:

    SwitchStateToFlipped()
    {
    _isFlipped = true;
    Camera.main.projectionMatrix = GetFlippedProjection();
    }

    When this method is called, the projection is flipped, but when I move my character into a trigger that transitions the camera, it immediately gets switched back to the original projection (right before the transition).

    To be honest, maybe it's okay to just do it in Update or LateUpdate, I'm usually very keen on avoiding code that runs every frame if it doesn't have to, but I don't want to make a big deal out of it.

  • Yes, I think if you have things at least working, it may be best to leave as-is.

    Though, for a 3D Camera the projection matrix should typically only be updated at the start of a camera switch - even if switch has a transition time.

    As the OnSwitchCamera event is called before the effects of it are actually applied, you could try running the code at the end of that frame, i.e.:

    private void OnSwitchCamera (_Camera old, _Camera newCamera, float transitionTime)
    {
        StartCoroutine (FlipEndOfFrame ());
    }
    
    private IEnumerator FlipEndOfFrame ()
    {
        yield return new WaitForEndOfFrame ();
        SwitchStateToFlipped ();
    }
    
  • That almost works, but I can see the unflipped render for a split second. Maybe I will play around with it some more, I think you gave me enough material to understand the problem, but updating for the time of the transition is also acceptable I guess :) Thanks Chris!

  • @ChrisIceBox I'm sorry to bother you again with this, but there is still a weird problem and I was wondering if you had an idea on why this is happening.

    I noticed that when I flip the projection matrix while transitioning between cameras with different field of views, the field of view seems to be screwed up or it is not changing or something like that. I removed my update code and used the Coroutine way to see what happens when I add an extra second before flipping the projection matrix and the field of view seems to stay correct:

    private void OnCameraSwitch(_Camera fromCamera, _Camera toCamera, float transitionTime)
    {
    StartCoroutine(FlipEndOfFrame());
    }

    private IEnumerator FlipEndOfFrame()
    {
    yield return new WaitForEndOfFrame();
    yield return new WaitForSeconds(1f);
    FlipCamera();
    }

    This way I see the transition and one second later it correctly flips the projection.

    Any ideas why manipulating the camera projection matrix while transitioning between cameras could change the field of view or prevent it from changing?

  • The MainCamera will read the FOV each frame and apply it to itself, but I'm not sure why the referenced GameCamera would be affected. Though, waiting 1 second is probably causing it to run once the transition is complete.

    I'd still recommend switching to LateUpdate so that you can be sure it always gets run after other changes applied by AC. We can see about optimising later, but first it's important to get the behaviour correct.

  • Thanks Chris, actually after writing my request I've noticed that flipping the camera projection also flips the normals of the 3D models and I find it unexpectedly difficult to get this to work so alas I will have to shelve this feature for now anyway.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.