Three things drive final gravity. Grist composition, yeast type and mash temperature.
The most prominent of the 3 istist composition. Home brewers use too much crystal malts which contain high levels of dextrin. Its’s something the beer needs, but too much can cause higher finish gravity and the beer to taste sweeter than it should. If you happen to brew a mild or something similar, then that’s a good thing. German, Belgian and most American styles are generally dry in the finish, with lower finishing gravities. Substitute darker base malts for crystal malts, such as Munich.
The second being yeast. Some yeast will produce lower attenuation, others need more attention to get it out of them. Still others just finish high, Windsor, Wyeast 1318 are some that finish high. To coax the yeast to finish lower, aeration, pitch rates and temperature all play a role. The biggest mistake homebrewers make is to not properly aerate wort when using a liquid yeast. Dry yeast performs much better then liquid yeast when oxygen levels are low in wort, which is a consideration. If the yeast get too warm, they may quit or more likely too cold and drop out before they’re done or just stall. Stalled fermentation are most often caused by pitch rates that are too low or by oxygen levels that were too low at the time of pitch.
The last thing is the mash. I have found that if I mash between 144-148F, the mash needs more time, up to 90 minutes. If I mash above 150F, I stick to one hour. I also do step mashed, but it may not have any bearing on final gravity. The longer time at lower temperatures allow the beta amylase to produce highly fermentable wort with simpler sugars that the yeast can easily metabolize.