unity-csharp-fundamentals
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUnity C# Fundamentals - Essential Coding Patterns
Unity C# 基础核心 - 必备编码模式
Overview
概述
Core Unity C# patterns for safe, maintainable code. Not optimizations but fundamental practices.
Foundation Required: C# basics, Unity MonoBehaviour lifecycle
Core Topics: TryGetComponent, SerializeField, RequireComponent, Null-safe patterns, Lifecycle management
核心Unity C#模式,用于编写安全、可维护的代码。这些不是优化技巧,而是基础实践。
前置要求:C#基础知识、Unity MonoBehaviour生命周期
核心主题:TryGetComponent、SerializeField、RequireComponent、空安全模式、生命周期管理
Essential Patterns
必备模式
TryGetComponent (Required)
TryGetComponent(必用)
Always use instead of :
TryGetComponentGetComponentcsharp
// ❌ WRONG
Rigidbody rb = GetComponent<Rigidbody>();
rb.velocity = Vector3.zero; // NullReferenceException!
// ✅ CORRECT
Rigidbody rb;
if (TryGetComponent(out rb))
{
rb.velocity = Vector3.zero;
}
// ✅ Cache in Awake with validation
private Rigidbody mRb;
void Awake()
{
if (!TryGetComponent(out mRb))
{
Debug.LogError($"Missing Rigidbody on {gameObject.name}", this);
}
}始终使用而非:
TryGetComponentGetComponentcsharp
// ❌ WRONG
Rigidbody rb = GetComponent<Rigidbody>();
rb.velocity = Vector3.zero; // NullReferenceException!
// ✅ CORRECT
Rigidbody rb;
if (TryGetComponent(out rb))
{
rb.velocity = Vector3.zero;
}
// ✅ Cache in Awake with validation
private Rigidbody mRb;
void Awake()
{
if (!TryGetComponent(out mRb))
{
Debug.LogError($"Missing Rigidbody on {gameObject.name}", this);
}
}Global Object Search (Unity 2023.1+)
全局对象搜索(Unity 2023.1+)
csharp
// ❌ OBSOLETE - DON'T USE
GameManager manager = FindObjectOfType<GameManager>();
// ✅ CORRECT - Fastest (unordered)
GameManager manager = FindAnyObjectByType<GameManager>();
// ✅ CORRECT - Ordered
GameManager manager = FindFirstObjectByType<GameManager>();
// ✅ Multiple objects
Enemy[] enemies = FindObjectsByType<Enemy>(FindObjectsSortMode.None);csharp
// ❌ OBSOLETE - DON'T USE
GameManager manager = FindObjectOfType<GameManager>();
// ✅ CORRECT - Fastest (unordered)
GameManager manager = FindAnyObjectByType<GameManager>();
// ✅ CORRECT - Ordered
GameManager manager = FindFirstObjectByType<GameManager>();
// ✅ Multiple objects
Enemy[] enemies = FindObjectsByType<Enemy>(FindObjectsSortMode.None);SerializeField Pattern
SerializeField 模式
csharp
// ❌ WRONG: Public field
public float speed;
// ✅ CORRECT: SerializeField + private
[SerializeField] private float mSpeed = 5f;
// ✅ With Inspector helpers
[SerializeField, Tooltip("Units/second"), Range(0f, 100f)]
private float mMoveSpeed = 5f;
public float Speed => mSpeed; // Read-only accesscsharp
// ❌ WRONG: Public field
public float speed;
// ✅ CORRECT: SerializeField + private
[SerializeField] private float mSpeed = 5f;
// ✅ With Inspector helpers
[SerializeField, Tooltip("Units/second"), Range(0f, 100f)]
private float mMoveSpeed = 5f;
public float Speed => mSpeed; // Read-only accessRequireComponent
RequireComponent
csharp
[RequireComponent(typeof(Rigidbody))]
[DisallowMultipleComponent]
public class PhysicsObject : MonoBehaviour
{
private Rigidbody mRb;
void Awake()
{
TryGetComponent(out mRb); // Guaranteed to exist
}
}csharp
[RequireComponent(typeof(Rigidbody))]
[DisallowMultipleComponent]
public class PhysicsObject : MonoBehaviour
{
private Rigidbody mRb;
void Awake()
{
TryGetComponent(out mRb); // Guaranteed to exist
}
}Unity Null Safety
Unity 空安全
csharp
// ❌ WRONG: C# null operators don't work with Unity Objects
Transform target = mCached ?? FindTarget(); // Broken!
mEnemy?.TakeDamage(10); // May fail after Destroy
// ✅ CORRECT: Explicit null check
Transform target = mCached != null ? mCached : FindTarget();
if (mEnemy != null)
{
mEnemy.TakeDamage(10);
}csharp
// ❌ WRONG: C# null operators don't work with Unity Objects
Transform target = mCached ?? FindTarget(); // Broken!
mEnemy?.TakeDamage(10); // May fail after Destroy
// ✅ CORRECT: Explicit null check
Transform target = mCached != null ? mCached : FindTarget();
if (mEnemy != null)
{
mEnemy.TakeDamage(10);
}Lifecycle Order
生命周期顺序
csharp
void Awake() { /* 1. Self-init, cache components */ }
void OnEnable() { /* 2. Subscribe events */ }
void Start() { /* 3. Cross-object init */ }
void OnDisable() { /* 4. Unsubscribe events */ }
void OnDestroy() { /* 5. Final cleanup */ }csharp
void Awake() { /* 1. Self-init, cache components */ }
void OnEnable() { /* 2. Subscribe events */ }
void Start() { /* 3. Cross-object init */ }
void OnDisable() { /* 4. Unsubscribe events */ }
void OnDestroy() { /* 5. Final cleanup */ }Unity C# 9.0 Limitations
Unity C# 9.0 限制
Important: Unity's Mono/IL2CPP runtime lacks.IsExternalInitaccessor causes compile error CS0518.init
csharp
// ❌ COMPILE ERROR in Unity
public string Name { get; private init; }
// ✅ Use private set
public string Name { get; private set; }
// ✅ Or readonly field + property
private readonly string mName;
public string Name => mName;Available: Pattern matching, switch expressions, covariant returns
NOT Available: , (C# 11)
initrequired重要提示:Unity的Mono/IL2CPP运行时不支持。使用IsExternalInit访问器会导致编译错误CS0518。init
csharp
// ❌ COMPILE ERROR in Unity
public string Name { get; private init; }
// ✅ Use private set
public string Name { get; private set; }
// ✅ Or readonly field + property
private readonly string mName;
public string Name => mName;可用特性:模式匹配、switch表达式、协变返回
不可用特性:、(C# 11)
initrequiredQuick Reference
快速参考
| Pattern | Rule |
|---|---|
| Component access | Always |
| Serialization | |
| Dependencies | Use |
| Null checks | Explicit |
| Caching | Get in |
| Events | Subscribe in |
| Global search | |
| 模式 | 规则 |
|---|---|
| 组件访问 | 始终使用 |
| 序列化 | 使用 |
| 依赖管理 | 使用 |
| 空值检查 | 显式使用 |
| 缓存策略 | 在 |
| 事件处理 | 在 |
| 全局搜索 | 使用 |
Reference Documentation
参考文档
Component Access Patterns
组件访问模式
- TryGetComponent variations and interface-based access
- GetComponentInChildren/Parent patterns
- Allocation-free multiple component access
- Caching strategies and performance comparisons
- TryGetComponent的变体及基于接口的访问方式
- GetComponentInChildren/Parent的使用模式
- 无分配的多组件访问
- 缓存策略与性能对比
Attributes and Patterns
特性与模式
- Complete serialization attribute reference
- Inspector customization (Header, Tooltip, Range)
- Execution order control
- Conditional compilation
- 完整的序列化特性参考
- 检视面板自定义(Header、Tooltip、Range)
- 执行顺序控制
- 条件编译
Language Limitations
语言限制
- accessor alternatives with code examples
init - Records in Unity (limitations and workarounds)
- modifier alternatives
required - Available C# 9.0 features in Unity
- 访问器的替代方案及代码示例
init - Unity中的Records(限制与变通方案)
- 修饰符的替代方案
required - Unity中可用的C# 9.0特性