Don’t expose public fields. I know a lot of tutorials (and even Unity Tech themselves) does it, but it creates highly coupled code. Don’t be afraid of using interfaces.
Instead of:
// add to GameObject:
public class HealthComponent : MonoBehaviour { public float value; }
// then to deal damage:
HealthComponent health = target.GetComponent<HealthComponent>();
health.value -= 10;
Use an interface:
public interface IDamageable { void TakeDamage(float amount); }
public class HealthComponent : MonoBehaviour, IDamageable
{
protected float value;
public void TakeDamage(float amount) { value -= amount; }
}
// then to deal damage:
IDamagable damageable = target.GetComponent<IDamageable>();
damageable.TakeDamage(10);
Now if you want to add on say, damage types (physical, fire, ice, etc.) and resistances, you can just change the interface and fix the errors instead of finding every single GetComponent() and making the appropriate changes. Much more future proof and debug friendly.
Make everything private. Then assume that anything public can be called or changed at random. You can further restrict this by using properties.
You’ll end up fighting Unity’s serialisation system a bit with this approach. But its worth it. If you want something to turn up in the inspector use [SerialiseField] instead of public.
Makes maintaining systems a lot easier, if you want to change the logic, modify the “model” script. If you want to change how something behaves on screen, modify the “view” script, if you want to modify how a user interacts with the system, modify the “controller” script.
That is completely dependent on what you want the function to do! BUT for value types like int,float etc, you can’t modify that directly within a function anyway, unless you pass it explicitly by reference.
Depends. Strictly speaking in traditional programming the best practice is to keep scopes as small as possible. Class level fields should only be used for information that needs to be shared with other classes.
In unity it’s not that clear cut. You have the GC to worry about. Creating and abandoning a lot of data every frame can cause havoc in memory.
I was just wondering if there is some reason that is better for maintainable code… returning values to set local scope fields so that you can avoid modifying class scope fields and also avoiding ‘ref’ parameters.
Ref parameters should be avoided. They are difficult to maintain. In some cases they are the best solution, but in most cases there are better ways. Ref parameters force your method and it’s caller to know something about each other, thus breaking encapsulation.
Polling, or checking for a value change at some regular frequency, can be useful in some circumstances, like input. But generally its a pretty expensive operation. Not that checking the value is expensive. But that checking a value that hasn’t changed is just a waste of time.
Informing on a change can be useful. Properties are a good way to do this. But requires your class to know about every class that is watching it. This sort of dependency is not good practice.
The next solution is to use events. Events let classes subscribe and listen, without the class triggering the even knowing a thing about the class that is listening for it. Event based systems require the subscriber to know what classes its listening too.
Then you can go into full blown design pattern messaging systems. There are a bunch of ways for classes to communicate value changes without any dependency at all. I’ll let you explore this one later. Design patterns are very useful, but they can be overkill for small projects.