In the first installment of the franchise, we used what I'd call a "whack a mole" approach to anticheat.
We'd procure cheating tools that were sold for our games, figured out how they worked (most were standalone trainers built with cheateengine and I made a small tool to extract the .CENGINE file from them which I could then open in cheateengine. I could figure exactly which piece of code they were patching and in which way they changed it), and then figured how to prevent them from working anymore
We had an arsenal of tricks at our disposal, one of them was to wrap some values in such a way that they were crudely encrypted in memory, so that finding them with things like cheateengine wouldn't work. We did other things such as randomizing the location of pointers to singletons to try and defeat some tricks used to locate variables on the heap (that didn't have fixed addresses) by following pointers from static variables (which are at fixed addresses).
This approach was time consuming and not very effective. We'd spend days of work to analyze and block some cheats, it then took weeks for the patch to go live, and then only days again for cheaters to find new ways of cheating.