Universal | C# |
---|
- Use a serialized public property to cut down a serialized private field
// 👎 non-compliant
[SerializeField] private int _level;
public int Level => _level;
// 👍 preference
[field: SerializeField] public int Level {get; private set;}
// 👍 preference: use UsedImplicitly attribute if only assign in Inspector
[field: SerializeField] public int Level {get; [UsedImplicitly] private set;}
[field: SerializeField] [UsedImplicitly] public int Level {get; private set;}
- Refer directly to specific component when Instantiate new GameObject
// 👎 non-compliant
GameObject bullet = Instantiate(bulletPrefab, transform.position, transform.rotation);
bulletBody = bullet.GetComponent<Rigidbody>();
bulletBody.velocity = transform.forward * speed;
// 👍 preference
Rigidbody bulletBody = Instantiate(bulletPrefab, transform.position, transform.rotation);
bulletBody.velocity = transform.forward * speed;
- Declare
public
members which don't need to modify in Playmode w/[HideInInspector]
attribute
Reason: clean up Inspector
- Pass individual vector components without creating new vector (Unity API usually has overloading method for this, otherwise, create extension method)
// 👎 non-compliant
_ballRigidbody.AddForce(shotPoint.transform.TransformDirection(new Vector3(0f, 0f, _powerToRoll)));
// 👍 preference
_ballRigidbody.AddForce(shotPoint.transform.TransformDirection(0f, 0f, _powerToRoll));
- Use hash id to change animator state
Reason: do not need to validate string each time -> improve performance
// 👎 non-compliant
void Update(){
if(attackKey.IsUp()) anim.SetTrigger("Attack");
}
// 👍 performance
private readonly int ATTACK_HASH = Animator.StringToHash("Attack");
void Update(){
if(attackKey.IsUp()) anim.SetTrigger(ATTACK_HASH);
}
- Wrap asset API usage in its conditional compiling symbol (directive) to avoid error on its absence.
Use CCU to automatically detect and add asset symbol.
- Create a wrapper/adapter for commonly-used class/attribute from 3rd-party asset
// 👎 non-compliant
public class MyClass1 : MonoBehaviour {
#if USING_SERVICE
[SerializeField] private ServiceClass _service;
#endif
public void DoSomething() {
#if USING_SERVICE
_service.Execute();
#endif
}
}
// and many other classes using ServiceClass...
// 👍 preference
[Serializable]
public class ServiceWrapper {
#if USING_SERVICE
[SerializeField] private ServiceClass _service;
#endif
public void Execute() {
#if USING_SERVICE
_service.Execute();
#endif
}
public class MyClass1 {
[SerializeField] private ServiceWrapper _service;
public void DoSomething() {
_service.Execute();
}
}
=>GetComponent
TryGetComponent
when need to get and use a component:
// 👎 non-compliant
bulletBody = bullet.GetComponent<Rigidbody>();
if(bulletBody is not null)
bulletBody.velocity = transform.forward * speed;
// 👍 preference
if(bullet.TryGetComponent(out Rigidbody bulletBody)
bulletBody.velocity = transform.forward * speed;