Flip/Mirror > Camera?

Is there a way to flip the Camera (let's say in X position), so the whole scene is "mirrored" for example to the right side,?

You can use something like this (Once in start should do it):

Matrix4x4 mat = Camera.main.projectionMatrix;
mat *= Matrix4x4.Scale(new Vector3(-1, 1, 1));
Camera.main.projectionMatrix = mat;

Just use the attached script in your camera, it will flip the image according to the editor selection and fix the culling accordingly.

using UnityEngine;

[RequireComponent(typeof(Camera))]
[ExecuteInEditMode]
public class MirrorFlipCamera : MonoBehaviour {

	new Camera camera;

	public bool flipHorizontal;

	void Awake () {
		camera = GetComponent<Camera>();
	}

	void OnPreCull() {
		camera.ResetWorldToCameraMatrix();
		camera.ResetProjectionMatrix();
		Vector3 scale = new Vector3(flipHorizontal ? -1 : 1, 1, 1);
		camera.projectionMatrix = camera.projectionMatrix * Matrix4x4.Scale(scale);
	}

	void OnPreRender () {
		GL.invertCulling = flipHorizontal;
	}
	
	void OnPostRender () {
		GL.invertCulling = false;
	}
}

If you have render to texture (pro only) you could easily achieve this by rendering a texture and then flip that texture before it's displayed.

URP and HDRP have deprecated the On…Render events. Here is a version of @ApenasVB s script which will work for URP and HDRP. I also added mirroring for both axis.

using UnityEngine;
using UnityEngine.Rendering;
using UnityEditor;

[RequireComponent(typeof(Camera))]
[ExecuteInEditMode]
public class MirrorFlipCamera : MonoBehaviour
{
	Camera _camera;
	public Camera Camera
	{
		get
		{
			if (_camera == null)
			{
				_camera = this.GetComponent<Camera>();
			}
			return _camera;
		}
	}

	[SerializeField]
	protected bool flipHorizontal;
	public bool FlipHorizontal
	{
		get => flipHorizontal;
		set
		{
			flipHorizontal = value;
			UpdateCameraMatrix();
		}
	}

	[SerializeField]
	protected bool flipVertical;
	public bool FlipVertical
	{
		get => flipVertical;
		set
		{
			flipVertical = value;
			UpdateCameraMatrix();
		}
	}

	protected float aspectRatio = 0;

	void Awake()
	{
		RenderPipelineManager.beginCameraRendering += beginCameraRendering;
		RenderPipelineManager.endCameraRendering += endCameraRendering;
	}

	void beginCameraRendering(ScriptableRenderContext context, Camera camera)
	{
		// Flip only if ONE of the two axis is mirrored but not if both are mirrored.
		if (this == null || !this.gameObject.activeInHierarchy)
			return;

		GL.invertCulling = flipHorizontal ^ flipVertical;

		// update is aspect ratio changed
		if (Mathf.Abs(aspectRatio - Camera.aspect) > 0.01f)
		{
			aspectRatio = Camera.aspect;
			UpdateCameraMatrix();
		}
	}

	void endCameraRendering(ScriptableRenderContext context, Camera camera)
	{
		if (this == null || !this.gameObject.activeInHierarchy)
			return;

		GL.invertCulling = false;
	}

	public void UpdateCameraMatrix()
	{
		Camera.ResetWorldToCameraMatrix();
		Camera.ResetProjectionMatrix();
		Vector3 scale = new Vector3(
			flipHorizontal ? -1 : 1,
			flipVertical ? -1 : 1,
			1);
		Camera.projectionMatrix = Camera.projectionMatrix * Matrix4x4.Scale(scale);

	}

	void OnValidate()
	{
		if (Camera == null)
			return;

		UpdateCameraMatrix();

#if UNITY_EDITOR
		RenderPipelineManager.beginCameraRendering -= beginCameraRendering;
		RenderPipelineManager.endCameraRendering -= endCameraRendering;
		if (!EditorApplication.isPlayingOrWillChangePlaymode)
		{
			RenderPipelineManager.beginCameraRendering += beginCameraRendering;
			RenderPipelineManager.endCameraRendering += endCameraRendering;
		}
#endif
	}
}

Since another answer mentioned the Unity wiki (which no longer exists), here is the linked page from the archives: InvertCamera - Unify Community Wiki

There is the answer: http://wiki.unity3d.com/index.php?title=InvertCamera

any ideas why the vertical flip cant work together with the horizontal one (in conjunction)?
it causes render issue.

Vector3 scale = new Vector3(-1, -1, 1);

do not use scripts and shaders - you just need to reflect vertex positions of your model in a 3D graphic editor like blander 3d or 3dMax into the UNwrap tab

I’m sorry for resurrect this fairly old topic / issue - but in case that anyone is having the same issue, here is what currently works best for me, hope it works for you as well. I reworked based on the solutions provided by @Mike_3 and @buenacolombia - Note that I just performed basic tests but this should* flip the camera output in the X axis at (before) render time, then prevent the normals from being rendered incorrectly by inverting the Culling and restoring it afterwards (not quite sure if you need to restore it, I have not tested, but I guess just in case). It should work in any of the Scriptable Pipelines via the current (at the time of this writing) via using UnityEngine.Rendering and related Delegates approach. I’m using Awake() instead of Start() as to attempt ensuring as earliest interaction with the Camera.main.projectionMatrix as possible, but it should work on Start() as well:

using UnityEngine;
using UnityEngine.Rendering;

public class FlipCameraOutput : MonoBehaviour
{   

    void Awake() { 
        Matrix4x4 mat = Camera.main.projectionMatrix; 
        mat *= Matrix4x4.Scale(new Vector3(-1, 1, 1)); 
        Camera.main.projectionMatrix = mat; 
    }

    void Start()
    {
        RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
        RenderPipelineManager.endCameraRendering += OnEndCameraRendering;
    }

    void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
    {
        // Put the code that you want to execute before the camera renders here
        // If you are using URP or HDRP, Unity calls this method automatically
        // If you are writing a custom SRP, you must call RenderPipeline.BeginCameraRendering

        GL.invertCulling = true;
    }

    void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) 
    {
        GL.invertCulling = false;
    }

    void OnDestroy()
    {
        RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
        RenderPipelineManager.endCameraRendering -= OnEndCameraRendering;   
    }
}