Casing: PascalCase
public namespace Company.Product.Module
{
public class SomeClass : MonoBehaviour
{
}
}
Casing: PascalCase
public void SomeMethod()
{
}
Casing: PascalCase
public int Charisma;
public int Health { get; private set; }
Casing: camelCase
private int health;
Casing: camelCase
public void SomeMethod(int someParameter)
{
}
Casing: camelCase
...
int counter = 1;
...
- Minimize dependencies
- e.g. Instead of direct calls, often events can be used like
HealthChanged
(useAction
orUnityEvent
)
- e.g. Instead of direct calls, often events can be used like
- Not all classes need to be MonoBehaviours (which needs to be attached to a GameObject in the scene)
- Plain C# classes are more portable than classes which are based on the Unity platform and engine code
- Define interfaces for exchangeable classes
- Interfaces also help to be aware of which part of a class is exposed to the outside and which not
- Use runtime assertions to formulate assumptions and method preconditions which can help to detect bugs early
- e.g.
Assert.IsNotNull(obj)
orAssert.IsTrue(condition)
- e.g.
- Write unit tests to ensure correct behaviour
- Avoid the overuse of events wired inside the inspector
- Renaming and other operations can loose link between components
- Hard to track down and hard to debug
There are two ways: make the fields public, or make them private and mark them as [SerializeField]. We decide for the second option because it is tempting to change this public fields by script. Therefore, making it private and deciding when to expose methods or fields to the outside is more precise about the public interface of a component.
// private field which is exposed inside the inspector
[SerializeField]
private int count;
// properties can be used to expose private fields
public int Count { get { return count; }, private set; }
If a field should be exposed and indeed be part of the public interface, the use of public fields is fine.
- Avoid heavy calculations in
Update()
(runs every frame) - Avoid unnecessary assignments of local variables in
Update()
(garbage collector will run every frame)- e.g. Instead of calling
obj.GetComponent()
inUpdate()
, cache the components you want to access
- e.g. Instead of calling
- Remove MonoBehaviour methods like
Start()
,Update()
if not needed - Avoid overuse of
GameObject.Find()
,GameObject.FindObjectOfType<T>()
as it traverses the whole scene - Use profiling after heavy code changes to avoid performance bottlenecks (lookout for spikes)