How to clamp tiling of texture to units rather than surface size of object?,How to clamp repeating texture based off units and not surface size?

Sorry if the question was poorly written, I wasn’t sure how to word this. So I want to know if there is a way to make the tiling of a texture on an object be based off of units rather than the surface size of the object itself. The reasoning is because in a game I am working on I have a seamless wall texture that I would like to use on all my walls. However, each wall has a different size, which means tiling won’t work because the texture will look different on each wall. To better illustrate what I am trying to do, I made some examples:


The three planes in the middle of the screen are 1x1, 2x2, and 4x4 units. Once I apply the texture to each, (using the standard shader on the material, and the texture is the albedo map of the material), the texture stretches to fill the entire surface. What I want is this look:

The texture, which is a red outlined square with a blue dot, is consistently 1x1 unit size on all three planes. To do this, I had to duplicate the original material and give each material it’s own tiling to match the size of the plane. Is there a way to do this without having to make a separate material for every differently shaped object?
Just some information:
The size of the texture is 512x512, and the black outline isn’t on the direct edge, just near it. So there is red on the edge of the textures.
The texture type is default, with the repeating wrap mode.

You can’t do it with the Standard shader I’m afraid. It sounds like what you want is a triplanar shader. Here’s one:

Shader "Custom/Triplanar" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Bump ("Normal", 2D) = "bump" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0

        struct Input {
            float3 worldNormal; INTERNAL_DATA
            float3 worldPos;
        };

        sampler2D _MainTex, _Bump;
        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
        float4 _MainTex_ST, _Bump_ST;
        
        UNITY_INSTANCING_BUFFER_START(Props)
        UNITY_INSTANCING_BUFFER_END(Props)

        inline float4 triplanar(sampler2D tex, float3 position, float3 normal, float2 textureScale) {
            normal = abs(normal);
            float3 weights = normal / (normal.x + normal.y + normal.z);
            float4 x = tex2D(tex, position.yz * textureScale);
            float4 y = tex2D(tex, position.xz * textureScale);
            float4 z = tex2D(tex, position.xy * textureScale);
            return weights.x * x + weights.y * y + weights.z * z;
        }

        void surf (Input IN, inout SurfaceOutputStandard o) {
            float3 position = IN.worldPos;
            float3 normal = WorldNormalVector(IN, float3(0, 0, 1));

            float4 c = triplanar(_MainTex, position, normal, _MainTex_ST.xy) * _Color;
            float4 n = triplanar(_Bump, position, normal, _Bump_ST.xy);

            o.Normal = UnpackNormal(n);
            o.Albedo = c.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

The important part is the function “triplanar”. It samples a texture once for each of the three coordinate planes and then blends between them based on a normal vector.