Mark non-movable objects as static. Unity doesn't batch skinmeshes. If objects transform are affected by animator, don't make it static.
Enable mipmap levels for textures. It is always a trade-off, see how it influence on the size of the scene.
ASTC textures. Have different block compression sizes, faster at build-time. 4-20x faster than ETC2
if postprocessing is not used(not active effects) we should disable it, otherwise it will add one more Graphics.Blit into pipeline, which is expensive
Better always use RenderTexture.GetTemporary for rendering because it doesn't need to keep expensive texture restore operation every frame
In Xcode shader profiler, see which textures are not used and marked with warning sign

Avoid mathematical functions in custom shaders
Move all uniform computations from shader to CPU
if shader uses discard
Use 4x MSAA it is almost free on mobile devices
If your device supports ASTC, use it to compress the textures in your 3D content. If your device does not support ASTC, try using ETC2.
enable mipmaps when possible, disadvantage is only 33% more memory
enable depth prepass to reduce overdraw
// extra pass that renders to depth buffer only
Pass {
ZWrite On
ColorMask 0
}
You can try to reduce the precision of shader variables to mediump, rather than highp, with no noticeable change on-screen https://docs.unity3d.com/Manual/SL-DataTypesAndPrecision.html?_ga=2.18724593.951916351.1615565447-1861978321.1598131182
use Mali Offline Shader Compiler to check shader cycles
mobile tile base rendering is very sensitive to resolving GPU memory back to main memory. stay on tile as much as possible
geometry and tesselation shaders are expensive on tile based because it uses external memory for storage
arm mali recommendation max 500 drawcalls for optimal cpu power consumption
shader optimisations to check
