Skip to content

Instantly share code, notes, and snippets.

@JimmyCushnie
Last active October 31, 2025 04:34
Show Gist options
  • Select an option

  • Save JimmyCushnie/e998cdec15394d6b68a4dbbf700f66ce to your computer and use it in GitHub Desktop.

Select an option

Save JimmyCushnie/e998cdec15394d6b68a4dbbf700f66ce to your computer and use it in GitHub Desktop.
Exposes some Unity URP graphics settings that are (for some stupid fucking bullshit reason) private.
using System.Reflection;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using ShadowResolution = UnityEngine.Rendering.Universal.ShadowResolution;
/// <summary>
/// Enables getting/setting URP graphics settings properties that don't have built-in getters and setters.
/// </summary>
public static class UnityGraphicsBullshit
{
private static FieldInfo MainLightCastShadows_FieldInfo;
private static FieldInfo AdditionalLightCastShadows_FieldInfo;
private static FieldInfo MainLightShadowmapResolution_FieldInfo;
private static FieldInfo AdditionalLightShadowmapResolution_FieldInfo;
private static FieldInfo Cascade2Split_FieldInfo;
private static FieldInfo Cascade4Split_FieldInfo;
private static FieldInfo SoftShadowsEnabled_FieldInfo;
static UnityGraphicsBullshit()
{
var pipelineAssetType = typeof(UniversalRenderPipelineAsset);
var flags = BindingFlags.Instance | BindingFlags.NonPublic;
MainLightCastShadows_FieldInfo = pipelineAssetType.GetField("m_MainLightShadowsSupported", flags);
AdditionalLightCastShadows_FieldInfo = pipelineAssetType.GetField("m_AdditionalLightShadowsSupported", flags);
MainLightShadowmapResolution_FieldInfo = pipelineAssetType.GetField("m_MainLightShadowmapResolution", flags);
AdditionalLightShadowmapResolution_FieldInfo = pipelineAssetType.GetField("m_AdditionalLightsShadowmapResolution", flags);
Cascade2Split_FieldInfo = pipelineAssetType.GetField("m_Cascade2Split", flags);
Cascade4Split_FieldInfo = pipelineAssetType.GetField("m_Cascade4Split", flags);
SoftShadowsEnabled_FieldInfo = pipelineAssetType.GetField("m_SoftShadowsSupported", flags);
}
public static bool MainLightCastShadows
{
get => (bool)MainLightCastShadows_FieldInfo.GetValue(GraphicsSettings.currentRenderPipeline);
set => MainLightCastShadows_FieldInfo.SetValue(GraphicsSettings.currentRenderPipeline, value);
}
public static bool AdditionalLightCastShadows
{
get => (bool)AdditionalLightCastShadows_FieldInfo.GetValue(GraphicsSettings.currentRenderPipeline);
set => AdditionalLightCastShadows_FieldInfo.SetValue(GraphicsSettings.currentRenderPipeline, value);
}
public static ShadowResolution MainLightShadowResolution
{
get => (ShadowResolution)MainLightShadowmapResolution_FieldInfo.GetValue(GraphicsSettings.currentRenderPipeline);
set => MainLightShadowmapResolution_FieldInfo.SetValue(GraphicsSettings.currentRenderPipeline, value);
}
public static ShadowResolution AdditionalLightShadowResolution
{
get => (ShadowResolution)AdditionalLightShadowmapResolution_FieldInfo.GetValue(GraphicsSettings.currentRenderPipeline);
set => AdditionalLightShadowmapResolution_FieldInfo.SetValue(GraphicsSettings.currentRenderPipeline, value);
}
public static float Cascade2Split
{
get => (float)Cascade2Split_FieldInfo.GetValue(GraphicsSettings.currentRenderPipeline);
set => Cascade2Split_FieldInfo.SetValue(GraphicsSettings.currentRenderPipeline, value);
}
public static Vector3 Cascade4Split
{
get => (Vector3)Cascade4Split_FieldInfo.GetValue(GraphicsSettings.currentRenderPipeline);
set => Cascade4Split_FieldInfo.SetValue(GraphicsSettings.currentRenderPipeline, value);
}
public static bool SoftShadowsEnabled
{
get => (bool)SoftShadowsEnabled_FieldInfo.GetValue(GraphicsSettings.currentRenderPipeline);
set => SoftShadowsEnabled_FieldInfo.SetValue(GraphicsSettings.currentRenderPipeline, value);
}
}
@JimmyCushnie
Copy link
Author

JimmyCushnie commented Jun 28, 2020

I hereby release this code into the public domain. Do whatever you want to with it.

@victorlapin
Copy link

Dude, thank you very much for this solution =) and indeed, it's UnityGraphicsBullshit

@JimmyCushnie
Copy link
Author

Cheers, I'm glad it helped you.

@Shrimpey
Copy link

Thank you dude, awesome you fixed something Unity struggled to fix for eternity (and still struggles). Also love the naming convention.

@Twirl1511
Copy link

Thank you!

@coty-crg
Copy link

coty-crg commented Apr 1, 2023

Thanks for this! Saved me some time (shipped a game with this file haha)

@JimmyCushnie
Copy link
Author

Happy to be of service 🫡

@haplane10
Copy link

Thank you so much!!

@stuw-u
Copy link

stuw-u commented Jun 11, 2023

Coming back to this every month.
Shipped 2 projects with this, used it in 4 projects, even extended it a bit.
I am forever thankful but.... HOW IS THIS STILL NEEDED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

@JimmyCushnie
Copy link
Author

It truly boggles the mind how the simplest one-line changes at Unity take a decade to be implemented.

@DanjelRicci
Copy link

Shipped two games with this and about to ship a third with it. Thank you so much!

@JimmyCushnie
Copy link
Author

💜💜💜 I'm very happy it's useful to you!

@AnthonyDemanueleFSG
Copy link

Thanks @JimmyCushnie!

Any ideas how I can extend this to access the GraphicSettings too?
Tried this so far without any luck.

var graphicsSettingsAssetType = typeof(GraphicsSettings); var graphicFlags = BindingFlags.Instance | BindingFlags.NonPublic; LightmapKeepStrippingFieldInfo = graphicsSettingsAssetType.GetField("m_LightmapStripping", graphicFlags); //Lightmap stripping LightmapKeepPlainFieldInfo = graphicsSettingsAssetType.GetField("m_LightmapKeepPlain", graphicFlags); //Baked Non-Directional LightmapKeepDirCombinedFieldInfo = graphicsSettingsAssetType.GetField("m_LightmapKeepDirCombined", graphicFlags); //Baked Directional LightmapKeepDynamicPlainFieldInfo = graphicsSettingsAssetType.GetField("m_LightmapKeepDynamicPlain", graphicFlags); //Realtime Non-Directional LightmapKeepDynamicDirCombinedFieldInfo = graphicsSettingsAssetType.GetField("m_LightmapKeepDynamicDirCombined", graphicFlags); //Realtime Directional LightmapKeepShadowMaskFieldInfo = graphicsSettingsAssetType.GetField("m_LightmapKeepShadowMask", graphicFlags); //Baked Shadowmask LightmapKeepSubtractiveFieldInfo = graphicsSettingsAssetType.GetField("m_LightmapKeepSubtractive", graphicFlags); //Baked Subtractive

@Vivian-A
Copy link

Legendary. Love the name of it too!

@AnthonyDemanueleFSG
Copy link

If anyone else needs this, here's how we ended up changing graphic settings in our case:

public static void SetToHDSettings()
{
    var graphicSettingAssetDataPath = Application.dataPath.Replace("Assets", "ProjectSettings/GraphicsSettings.asset");
    var graphicSettingsFileData = File.ReadAllText(graphicSettingAssetDataPath);
    graphicSettingsFileData = graphicSettingsFileData.Replace("m_LightmapStripping: 0", "m_LightmapStripping: 1");                              //Lightmap stripping - Always 1 - Custom
    graphicSettingsFileData = graphicSettingsFileData.Replace("m_LightmapKeepPlain: 1", "m_LightmapKeepPlain: 0");                              //Baked Non-Directional
    graphicSettingsFileData = graphicSettingsFileData.Replace("m_LightmapKeepDirCombined: 0", "m_LightmapKeepDirCombined: 1");                  //Baked Directional
    graphicSettingsFileData = graphicSettingsFileData.Replace("m_LightmapKeepDynamicPlain: 1", "m_LightmapKeepDynamicPlain: 0");                //Realtime Non-Directional 
    graphicSettingsFileData = graphicSettingsFileData.Replace("m_LightmapKeepDynamicDirCombined: 1", "m_LightmapKeepDynamicDirCombined: 0");    //Realtime Directional
    graphicSettingsFileData = graphicSettingsFileData.Replace("m_LightmapKeepShadowMask: 0", "m_LightmapKeepShadowMask: 1");                    //BakedShadowMask
    graphicSettingsFileData = graphicSettingsFileData.Replace("m_LightmapKeepSubtractive: 1", "m_LightmapKeepSubtractive: 0");                  //BakedSubtractive

    File.WriteAllText(graphicSettingAssetDataPath, graphicSettingsFileData);
    Debug.LogWarning($"Set shader stripping to HD settings.ShadowMask ON. Subtractive OFF");
}

@anomal3
Copy link

anomal3 commented Dec 30, 2023

I love you

@wonkee-kim
Copy link

Thank you!

@xiang-valcano
Copy link

does this really work in player build? I understand that shader variants will be stripped during the build process, and this script should not take any effect.

@MintUnreal
Copy link

Я ХОЧУ ОТ ТЕБЯ ДЕТЕЙ

@avi6111
Copy link

avi6111 commented Sep 18, 2024

Great Job! Somehow I did think that probably the staff did these shit for Commercial Thinking, they may not want UE copied them. but after these years, I think, may be the staff in Unity are just Dummy

@VEETEEGames
Copy link

VEETEEGames commented Oct 31, 2025

You just saved me from a break down

i wanted to contribute something so i added more options to change
and also if anyone wants to expand it you can just follow a similar layout

FInd a property you want to change on the RP asset ,right click ,copy property path
paste that in the constructor when you initialize it ,and set up the getters and setters

    public static class UnityGraphicsBullshit
    {
        private static readonly FieldInfo MainLightCastShadows_FieldInfo;
        private static readonly FieldInfo AdditionalLightCastShadows_FieldInfo;
        private static readonly FieldInfo MainLightShadowmapResolution_FieldInfo;
        private static readonly FieldInfo AdditionalLightShadowmapResolution_FieldInfo;
        private static readonly FieldInfo Cascade2Split_FieldInfo;
        private static readonly FieldInfo Cascade3Split_FieldInfo; // ← NEW
        private static readonly FieldInfo Cascade4Split_FieldInfo;
        private static readonly FieldInfo CascadeCount_FieldInfo; // ← NEW
        private static readonly FieldInfo SoftShadowsEnabled_FieldInfo;
        private static readonly FieldInfo ShadowDistance_FieldInfo; // ← NEW
        private static readonly FieldInfo ShadowQuality_FieldInfo; // ← NEW (Soft Shadow Quality)

        static UnityGraphicsBullshit()
        {
            var pipelineAssetType = typeof( UniversalRenderPipelineAsset );
            var flags = BindingFlags.Instance | BindingFlags.NonPublic;

            MainLightCastShadows_FieldInfo = pipelineAssetType.GetField("m_MainLightShadowsSupported", flags);
            AdditionalLightCastShadows_FieldInfo = pipelineAssetType.GetField("m_AdditionalLightShadowsSupported", flags);
            MainLightShadowmapResolution_FieldInfo = pipelineAssetType.GetField("m_MainLightShadowmapResolution", flags);
            AdditionalLightShadowmapResolution_FieldInfo = pipelineAssetType.GetField("m_AdditionalLightsShadowmapResolution", flags);
            Cascade2Split_FieldInfo = pipelineAssetType.GetField("m_Cascade2Split", flags);
            Cascade3Split_FieldInfo = pipelineAssetType.GetField("m_Cascade3Split", flags); // ← NEW
            Cascade4Split_FieldInfo = pipelineAssetType.GetField("m_Cascade4Split", flags);
            CascadeCount_FieldInfo = pipelineAssetType.GetField("m_ShadowCascadeCount", flags); // ← NEW
            SoftShadowsEnabled_FieldInfo = pipelineAssetType.GetField("m_SoftShadowsSupported", flags);
            ShadowDistance_FieldInfo = pipelineAssetType.GetField("m_ShadowDistance", flags); // ← NEW
            ShadowQuality_FieldInfo = pipelineAssetType.GetField("m_SoftShadowQuality", flags); // ← NEW (Soft quality)
        }
        private static UniversalRenderPipelineAsset CurrentAsset => GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;

        // === EXISTING ===
        public static bool MainLightCastShadows
        {
            get => (bool)MainLightCastShadows_FieldInfo.GetValue(CurrentAsset);
            set => MainLightCastShadows_FieldInfo.SetValue(CurrentAsset, value);
        }

        public static bool AdditionalLightCastShadows
        {
            get => (bool)AdditionalLightCastShadows_FieldInfo.GetValue(CurrentAsset);
            set => AdditionalLightCastShadows_FieldInfo.SetValue(CurrentAsset, value);
        }

        public static ShadowResolution MainLightShadowResolution
        {
            get => (ShadowResolution)MainLightShadowmapResolution_FieldInfo.GetValue(CurrentAsset);
            set => MainLightShadowmapResolution_FieldInfo.SetValue(CurrentAsset, value);
        }

        public static ShadowResolution AdditionalLightShadowResolution
        {
            get => (ShadowResolution)AdditionalLightShadowmapResolution_FieldInfo.GetValue(CurrentAsset);
            set => AdditionalLightShadowmapResolution_FieldInfo.SetValue(CurrentAsset, value);
        }

        public static float Cascade2Split
        {
            get => (float)Cascade2Split_FieldInfo.GetValue(CurrentAsset);
            set => Cascade2Split_FieldInfo.SetValue(CurrentAsset, value);
        }

        public static Vector3 Cascade4Split
        {
            get => (Vector3)Cascade4Split_FieldInfo.GetValue(CurrentAsset);
            set => Cascade4Split_FieldInfo.SetValue(CurrentAsset, value);
        }

        public static bool SoftShadowsEnabled
        {
            get => (bool)SoftShadowsEnabled_FieldInfo.GetValue(CurrentAsset);
            set => SoftShadowsEnabled_FieldInfo.SetValue(CurrentAsset, value);
        }

        // === NEW: 1. Shadow Max Distance ===
        public static float ShadowMaxDistance
        {
            get => (float)ShadowDistance_FieldInfo.GetValue(CurrentAsset);
            set => ShadowDistance_FieldInfo.SetValue(CurrentAsset, Mathf.Max(0.1f, value));
        }

        // === NEW: 2. Cascade 3 Split ===
        public static Vector2 Cascade3Split
        {
            get => (Vector2)Cascade3Split_FieldInfo.GetValue(CurrentAsset);
            set => Cascade3Split_FieldInfo.SetValue(CurrentAsset, value);
        }

        // === NEW: 3. Cascade Count (1, 2, 3, 4) ===
        public static int CascadeCount
        {
            get => (int)CascadeCount_FieldInfo.GetValue(CurrentAsset);
            set => CascadeCount_FieldInfo.SetValue(CurrentAsset, Mathf.Clamp(value, 1, 4));
        }

        // === NEW: 4. Soft Shadow Quality (Low/Med/High) ===
        public static SoftShadowQuality SoftShadowQuality
        {
            get => (SoftShadowQuality)ShadowQuality_FieldInfo.GetValue(CurrentAsset);
            set => ShadowQuality_FieldInfo.SetValue(CurrentAsset, value);
        }
        public static void SetToUltra()
        {
            MainLightCastShadows = true;
            AdditionalLightCastShadows = true;
            MainLightShadowResolution = ShadowResolution._2048;
            AdditionalLightShadowResolution = ShadowResolution._1024;
            ShadowMaxDistance = 80f;
            CascadeCount = 3;
            Cascade4Split = new Vector3(0.08f, 0.20f, 0.45f); // Near, Mid, Far
            SoftShadowsEnabled = true;
            SoftShadowQuality = SoftShadowQuality.Medium;
        }

        public static void SetToHigh()
        {
            MainLightCastShadows = true;
            AdditionalLightCastShadows = true;
            MainLightShadowResolution = ShadowResolution._1024;
            AdditionalLightShadowResolution = ShadowResolution._512;
            ShadowMaxDistance = 50f;
            CascadeCount = 2;
            Cascade2Split = 0.10f; // Near, Mid (Far = rest)
            SoftShadowsEnabled = true;
            SoftShadowQuality = SoftShadowQuality.Low;
        }

        public static void SetToMedium()
        {
            MainLightCastShadows = true;
            AdditionalLightCastShadows = false;
            MainLightShadowResolution = ShadowResolution._512;
            AdditionalLightShadowResolution = ShadowResolution._256;
            ShadowMaxDistance = 20f;
            CascadeCount = 1;
            SoftShadowsEnabled = false;
        }

        public static void SetToLow()
        {
            MainLightCastShadows = false;
            AdditionalLightCastShadows = false;
            MainLightShadowResolution = ShadowResolution._256;
            ShadowMaxDistance = 0f;
            CascadeCount = 1;
            SoftShadowsEnabled = false;
        }

        public static void SetQuality(int savedIndex)
        {
            switch (savedIndex)
            {
                case 0:
                    SetToLow();
                    break;
                case 1:
                    SetToMedium();
                    break;
                case 2:
                    SetToHigh();
                    break;
                case 3:
                    SetToUltra();
                    break;
            }
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment