Hi,
You might not like my answer, but what you’re looking for is called “experience” 
There is no answer that we can provide here that will make you able to write perfect code on your next project (I wish there was), as it takes time, pratice, trial and error, etc.
Do not look for perfect code, as it simply does not exist. You have to commit yourself to some code architecture to do some progress on your project, and later on, you may realize that your decisions may have some flaws, or that your architecture is not working. At that point, what matters is how you handle the situation: you can either delete all of your code and start it all over, or, you can take some time to think about your code, trying to understand why it does not work, and refactor it, or start it all over, but this time with insight.
Keep in mind that refactoring code is normal, you just cannot avoid it. I’ve been working as a programmer for 5 years and refactoring code is a large part of my tasks. Iterating on code is what’s expected from game developers; it’s litterally a part of the job.
Cool thing is, the more you’ll work on different games over the years, the better your codes will be and the less painful your refactoring will be.
Imagine you’re doing a pixel art illustration. You cannot paint each pixel one by one at get a nice result, you need to start with a sketch, try to apply some basic colors, cleanup the line, and then maybe you’ll rollback a bit because something’s off and you want to draw it again, etc. until you reach a nice final result.
Although experience is key, there are some existing stuff that can provide some help regarding writing a clean code.
First thing that comes to my mind is design patterns. The idea of design patterns is that, for a given type of problem, there’s a re-usable solution, applicable to any langage/game engine. For instance, one of the most used pattern in games - I think - is the Singleton pattern, which you may know.
I’ve read that book like 2 years ago: https://gameprogrammingpatterns.com/ and I liked it, I think it does a good job at explaining some simple patterns.
There are lots of resources online for design patterns, I don’t know them all, but you can look for the ones you find helpful.
Also, you can develop some good code habits, simple things, but that can make a difference: do not duplicate code but refactor it inside functions, try to apply some of the SOLID principles, etc.
Anyway, I wish there was a magical solution to your problem, but really it’s just about practicing and iterating. You can also share some of your codes here once you feel you’re struggling too much, so that people can try to see why your architecture is bad and tell you how to improve it.