Unity Performance by cryptorabea/claude_unity_dev_plugin
npx skills add https://github.com/cryptorabea/claude_unity_dev_plugin --skill 'Unity Performance'适用于 Unity 游戏的关键性能优化技术,涵盖内存管理、CPU 优化、渲染和性能分析策略。
性能对于所有平台上的 Unity 游戏都至关重要。性能不佳表现为帧率低、卡顿、加载时间长和崩溃。本技能涵盖适用于所有 Unity 项目的成熟优化技术。
核心优化领域:
最常见的 Unity 性能错误是重复进行昂贵的查找操作。缓存所有引用以避免冗余操作。
切勿重复调用 GetComponent - 在 Awake 中缓存结果:
// ❌ 错误 - 每帧都调用 GetComponent
private void Update()
{
GetComponent<Rigidbody>().velocity = Vector3.forward; // 慢!
}
// ✅ 正确 - 缓存一次
private Rigidbody rb;
private void Awake()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
rb.velocity = Vector3.forward; // 快
}
性能影响:GetComponent 比缓存的引用慢 10-100 倍。
缓存 transform 访问,特别是对于频繁访问的 GameObject:
// ❌ 错误 - 属性访问开销
private void Update()
{
transform.position += Vector3.forward * Time.deltaTime;
transform.rotation = Quaternion.identity;
}
// ✅ 正确 - 缓存 transform 引用
private Transform myTransform;
private void Awake()
{
myTransform = transform;
}
private void Update()
{
myTransform.position += Vector3.forward * Time.deltaTime;
myTransform.rotation = Quaternion.identity;
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
原因:transform 属性有开销。缓存的引用消除了重复查找。
切勿在 Update 中使用 Find 方法 - 缓存结果:
// ❌ 错误 - 每帧都查找(极其缓慢)
private void Update()
{
GameObject player = GameObject.Find("Player");
Transform target = GameObject.FindWithTag("Enemy").transform;
}
// ✅ 正确 - 在 Start 中缓存
private GameObject player;
private Transform target;
private void Start()
{
player = GameObject.Find("Player");
target = GameObject.FindWithTag("Enemy")?.transform;
}
private void Update()
{
// 使用缓存的引用
}
性能影响:Find 方法扫描整个场景层次结构。比缓存的引用慢 100-1000 倍。
访问 renderer.material 会创建新的 Material 实例 - 缓存以避免内存泄漏:
// ❌ 错误 - 每帧创建新的 Material(内存泄漏)
private void Update()
{
GetComponent<Renderer>().material.color = Color.red; // 创建新的 Material!
}
// ✅ 正确 - 缓存 material 引用
private Material material;
private void Awake()
{
material = GetComponent<Renderer>().material;
}
private void Update()
{
material.color = Color.red; // 修改缓存的 Material
}
private void OnDestroy()
{
// 清理实例化的 material
if (material != null)
Destroy(material);
}
关键点:访问 .material 会创建新实例。对于只读访问,使用 .sharedMaterial 以避免实例化。
Instantiate 和 Destroy 是昂贵的操作。应复用对象,而不是重复创建/销毁。
public class ObjectPool : MonoBehaviour
{
[SerializeField] private GameObject prefab;
[SerializeField] private int initialSize = 10;
private Queue<GameObject> pool = new Queue<GameObject>();
private void Awake()
{
// 预实例化对象
for (int i = 0; i < initialSize; i++)
{
GameObject obj = Instantiate(prefab);
obj.SetActive(false);
pool.Enqueue(obj);
}
}
public GameObject Get()
{
if (pool.Count > 0)
{
GameObject obj = pool.Dequeue();
obj.SetActive(true);
return obj;
}
// 池耗尽 - 创建新的
return Instantiate(prefab);
}
public void Return(GameObject obj)
{
obj.SetActive(false);
pool.Enqueue(obj);
}
}
适用于:
性能提升:比 Instantiate/Destroy 快 10-50 倍,消除 GC 峰值。
public class BulletSpawner : MonoBehaviour
{
[SerializeField] private ObjectPool bulletPool;
[SerializeField] private Transform firePoint;
private void Fire()
{
// 从池中获取
GameObject bullet = bulletPool.Get();
bullet.transform.position = firePoint.position;
bullet.transform.rotation = firePoint.rotation;
// 3 秒后归还
StartCoroutine(ReturnToPoolAfterDelay(bullet, 3f));
}
private IEnumerator ReturnToPoolAfterDelay(GameObject obj, float delay)
{
yield return new WaitForSeconds(delay);
bulletPool.Return(obj);
}
}
Update、FixedUpdate 和 LateUpdate 被频繁调用 - 尽量减少在这些方法中完成的工作。
// ❌ 错误 - 空方法仍有开销
private void Update() { }
private void FixedUpdate() { }
// ✅ 正确 - 移除未使用的方法
// (如果不需要,就不要有 Update/FixedUpdate)
性能:Unity 会调用所有 Update 方法,即使它们是空的。移除以减少开销。
并非所有逻辑都需要每帧运行:
// ❌ 错误 - 每帧都进行昂贵的检查
private void Update()
{
CheckForNearbyEnemies(); // 昂贵的射线检测/距离检查
}
// ✅ 正确 - 每 N 帧检查一次
private int frameCounter = 0;
private const int checkInterval = 10;
private void Update()
{
frameCounter++;
if (frameCounter >= checkInterval)
{
frameCounter = 0;
CheckForNearbyEnemies();
}
}
// ✅ 更好 - 使用 InvokeRepeating 或协程
private void Start()
{
InvokeRepeating(nameof(CheckForNearbyEnemies), 0f, 0.2f); // 每 0.2 秒
}
替代方案:协程
private void Start()
{
StartCoroutine(CheckEnemiesRoutine());
}
private IEnumerator CheckEnemiesRoutine()
{
while (true)
{
CheckForNearbyEnemies();
yield return new WaitForSeconds(0.2f);
}
}
用事件替代轮询:
// ❌ 错误 - 每帧轮询状态变化
private bool wasGrounded;
private void Update()
{
bool grounded = IsGrounded();
if (grounded != wasGrounded)
{
OnGroundedChanged(grounded);
}
wasGrounded = grounded;
}
// ✅ 正确 - 事件驱动
public event Action<bool> OnGroundedChanged;
private bool isGrounded;
private void SetGrounded(bool grounded)
{
if (isGrounded != grounded)
{
isGrounded = grounded;
OnGroundedChanged?.Invoke(grounded);
}
}
避免在频繁调用的方法中进行分配,以防止 GC 峰值。
// ❌ 错误 - 每帧分配字符串
private void Update()
{
string message = "Health: " + health; // 字符串分配
scoreText.text = "Score: " + score; // 字符串分配
}
// ✅ 正确 - 使用 StringBuilder 或字符串插值
private StringBuilder sb = new StringBuilder();
private void UpdateUI()
{
sb.Clear();
sb.Append("Health: ").Append(health);
healthText.text = sb.ToString();
}
// ✅ 替代方案 - 缓存格式化字符串
private void UpdateHealth(int newHealth)
{
health = newHealth;
healthText.text = health.ToString(); // 比拼接分配更少
}
// ❌ 错误 - 每帧分配新列表
private void Update()
{
List<Enemy> nearbyEnemies = new List<Enemy>(); // GC 分配!
FindNearbyEnemies(nearbyEnemies);
}
// ✅ 正确 - 复用列表
private List<Enemy> nearbyEnemies = new List<Enemy>();
private void Update()
{
nearbyEnemies.Clear(); // 复用现有列表
FindNearbyEnemies(nearbyEnemies);
}
// ❌ 错误 - ToArray 会分配
private void Update()
{
GameObject[] enemies = enemyList.ToArray(); // GC 分配!
}
// ✅ 正确 - 直接遍历列表
private void Update()
{
for (int i = 0; i < enemyList.Count; i++)
{
Enemy enemy = enemyList[i];
// 处理敌人
}
}
// ✅ 正确 - 使用 foreach(对 List 无分配)
private void Update()
{
foreach (var enemy in enemyList)
{
// 处理敌人
}
}
// ❌ 错误 - 每次调用都分配 WaitForSeconds
private IEnumerator DelayedAction()
{
yield return new WaitForSeconds(1f); // 每次都新分配
}
// ✅ 正确 - 缓存 WaitForSeconds
private WaitForSeconds oneSecondWait = new WaitForSeconds(1f);
private IEnumerator DelayedAction()
{
yield return oneSecondWait; // 复用缓存的等待
}
// ❌ 错误 - 多次 GetComponent 调用
private void OnTriggerEnter(Collider other)
{
if (other.GetComponent<Enemy>() != null)
{
other.GetComponent<Enemy>().TakeDamage(10); // 调用了两次!
}
}
// ✅ 正确 - 单次 GetComponent 配合模式匹配
private void OnTriggerEnter(Collider other)
{
if (other.TryGetComponent<Enemy>(out var enemy))
{
enemy.TakeDamage(10); // 调用一次
}
}
// ❌ 错误 - 每次碰撞都 GetComponent
private void OnTriggerEnter(Collider other)
{
var damageable = other.GetComponent<IDamageable>();
if (damageable != null)
damageable.TakeDamage(10);
}
// ✅ 正确 - 在触发器进入时缓存组件
private Dictionary<Collider, IDamageable> damageableCache = new Dictionary<Collider, IDamageable>();
private void OnTriggerEnter(Collider other)
{
if (!damageableCache.TryGetValue(other, out var damageable))
{
damageable = other.GetComponent<IDamageable>();
damageableCache[other] = damageable; // 为未来碰撞缓存
}
damageable?.TakeDamage(10);
}
private void OnTriggerExit(Collider other)
{
damageableCache.Remove(other); // 清理缓存
}
配置物理图层碰撞矩阵以防止不必要的碰撞检查:
编辑 > 项目设置 > 物理 > 图层碰撞矩阵
// 设置图层
Layer 8: Player
Layer 9: Enemies
Layer 10: Projectiles
Layer 11: Environment
// 禁用不必要的碰撞:
- Player vs Player (disabled)
- Enemies vs Enemies (disabled)
- Projectiles vs Projectiles (disabled)
性能提升:物理开销减少 30-50%。
// ❌ 错误 - 射线检测检查所有物体
bool hit = Physics.Raycast(origin, direction, out RaycastHit hitInfo);
// ✅ 正确 - 图层遮罩限制检查范围
int layerMask = 1 << LayerMask.NameToLayer("Enemy");
bool hit = Physics.Raycast(origin, direction, out RaycastHit hitInfo, maxDistance, layerMask);
// ✅ 更好 - 缓存图层遮罩
private int enemyLayerMask;
private void Awake()
{
enemyLayerMask = 1 << LayerMask.NameToLayer("Enemy");
}
private void Fire()
{
bool hit = Physics.Raycast(origin, direction, out RaycastHit hitInfo, maxDistance, enemyLayerMask);
}
当不移动时让 Rigidbody 休眠:
// 当速度 < 阈值时,Rigidbody 会自动休眠
// 在 编辑 > 项目设置 > 物理 中配置
// 需要时手动唤醒
private void ApplyForce()
{
if (rb.IsSleeping())
rb.WakeUp();
rb.AddForce(force);
}
优化前先测量。使用 Unity Profiler 识别实际瓶颈。
打开 Profiler:窗口 > 分析 > Profiler
CPU 使用情况:
内存:
启用 深度分析 以获取详细的调用堆栈(会影响性能):
警告:深度分析会显著降低游戏速度。用于小场景或针对性分析。
测量特定代码段:
using Unity.Profiling;
public class AIController : MonoBehaviour
{
private static readonly ProfilerMarker s_PathfindingMarker = new ProfilerMarker("AI.Pathfinding");
private static readonly ProfilerMarker s_DecisionMarker = new ProfilerMarker("AI.DecisionMaking");
private void Update()
{
s_PathfindingMarker.Begin();
CalculatePath();
s_PathfindingMarker.End();
s_DecisionMarker.Begin();
MakeDecision();
s_DecisionMarker.End();
}
private void CalculatePath() { }
private void MakeDecision() { }
}
在 Profiler 中显示自定义标记以进行精确测量。
为每个系统设定性能目标:
目标:60 FPS(每帧 16.67ms)
使用 Profiler 监控并优化超出预算的系统。
关键关注点:
移动端特定优化:
有更多余量但仍需优化:
有关详细的性能技术,请查阅:
references/memory-optimization.md - 高级 GC 减少、分配模式references/rendering-optimization.md - 绘制调用批处理、GPU 优化、着色器references/physics-optimization.md - 碰撞优化、Rigidbody 最佳实践references/profiling-guide.md - 完整的性能分析工作流、工具、分析缓存优先级:
在 Update 中避免:
优化前始终进行性能分析:
持续应用这些性能实践,以在所有平台上获得流畅、响应迅速的 Unity 游戏。
每周安装
0
仓库
GitHub 星标
3
首次出现
1970年1月1日
安全审计
Essential performance optimization techniques for Unity games, covering memory management, CPU optimization, rendering, and profiling strategies.
Performance is critical for Unity games across all platforms. Poor performance manifests as low framerates, stuttering, long load times, and crashes. This skill covers proven optimization techniques that apply to all Unity projects.
Core optimization areas:
The most common Unity performance mistake is repeated expensive lookups. Cache all references to avoid redundant operations.
Never call GetComponent repeatedly - cache results in Awake:
// ❌ BAD - GetComponent every frame
private void Update()
{
GetComponent<Rigidbody>().velocity = Vector3.forward; // SLOW!
}
// ✅ GOOD - Cache once
private Rigidbody rb;
private void Awake()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
rb.velocity = Vector3.forward; // FAST
}
Performance impact : GetComponent is 10-100x slower than cached reference.
Cache transform access, especially for frequently accessed GameObjects:
// ❌ BAD - Property access overhead
private void Update()
{
transform.position += Vector3.forward * Time.deltaTime;
transform.rotation = Quaternion.identity;
}
// ✅ GOOD - Cache transform reference
private Transform myTransform;
private void Awake()
{
myTransform = transform;
}
private void Update()
{
myTransform.position += Vector3.forward * Time.deltaTime;
myTransform.rotation = Quaternion.identity;
}
Why : transform property has overhead. Cached reference eliminates repeated lookups.
Never use Find methods in Update - cache results:
// ❌ BAD - Find every frame (EXTREMELY SLOW)
private void Update()
{
GameObject player = GameObject.Find("Player");
Transform target = GameObject.FindWithTag("Enemy").transform;
}
// ✅ GOOD - Cache in Start
private GameObject player;
private Transform target;
private void Start()
{
player = GameObject.Find("Player");
target = GameObject.FindWithTag("Enemy")?.transform;
}
private void Update()
{
// Use cached references
}
Performance impact : Find methods scan entire scene hierarchy. 100-1000x slower than cached references.
Access renderer.material creates new Material instance - cache to avoid leaks:
// ❌ BAD - Creates new Material every frame (MEMORY LEAK)
private void Update()
{
GetComponent<Renderer>().material.color = Color.red; // Creates new Material!
}
// ✅ GOOD - Cache material reference
private Material material;
private void Awake()
{
material = GetComponent<Renderer>().material;
}
private void Update()
{
material.color = Color.red; // Modifies cached Material
}
private void OnDestroy()
{
// Clean up instantiated material
if (material != null)
Destroy(material);
}
Critical : Accessing .material creates new instance. Use .sharedMaterial for read-only access to avoid instantiation.
Instantiate and Destroy are expensive. Reuse objects instead of creating/destroying repeatedly.
public class ObjectPool : MonoBehaviour
{
[SerializeField] private GameObject prefab;
[SerializeField] private int initialSize = 10;
private Queue<GameObject> pool = new Queue<GameObject>();
private void Awake()
{
// Pre-instantiate objects
for (int i = 0; i < initialSize; i++)
{
GameObject obj = Instantiate(prefab);
obj.SetActive(false);
pool.Enqueue(obj);
}
}
public GameObject Get()
{
if (pool.Count > 0)
{
GameObject obj = pool.Dequeue();
obj.SetActive(true);
return obj;
}
// Pool exhausted - create new
return Instantiate(prefab);
}
public void Return(GameObject obj)
{
obj.SetActive(false);
pool.Enqueue(obj);
}
}
Use for:
Performance gain : 10-50x faster than Instantiate/Destroy, eliminates GC spikes.
public class BulletSpawner : MonoBehaviour
{
[SerializeField] private ObjectPool bulletPool;
[SerializeField] private Transform firePoint;
private void Fire()
{
// Get from pool
GameObject bullet = bulletPool.Get();
bullet.transform.position = firePoint.position;
bullet.transform.rotation = firePoint.rotation;
// Return after 3 seconds
StartCoroutine(ReturnToPoolAfterDelay(bullet, 3f));
}
private IEnumerator ReturnToPoolAfterDelay(GameObject obj, float delay)
{
yield return new WaitForSeconds(delay);
bulletPool.Return(obj);
}
}
Update, FixedUpdate, and LateUpdate are called frequently - minimize work done in these methods.
// ❌ BAD - Empty methods still have overhead
private void Update() { }
private void FixedUpdate() { }
// ✅ GOOD - Remove unused methods
// (No Update/FixedUpdate if not needed)
Performance : Unity calls all Update methods even if empty. Remove to reduce overhead.
Not all logic needs to run every frame:
// ❌ BAD - Expensive check every frame
private void Update()
{
CheckForNearbyEnemies(); // Expensive raycast/distance checks
}
// ✅ GOOD - Check every N frames
private int frameCounter = 0;
private const int checkInterval = 10;
private void Update()
{
frameCounter++;
if (frameCounter >= checkInterval)
{
frameCounter = 0;
CheckForNearbyEnemies();
}
}
// ✅ BETTER - Use InvokeRepeating or Coroutine
private void Start()
{
InvokeRepeating(nameof(CheckForNearbyEnemies), 0f, 0.2f); // Every 0.2 seconds
}
Alternative: Coroutines
private void Start()
{
StartCoroutine(CheckEnemiesRoutine());
}
private IEnumerator CheckEnemiesRoutine()
{
while (true)
{
CheckForNearbyEnemies();
yield return new WaitForSeconds(0.2f);
}
}
Replace polling with events:
// ❌ BAD - Poll for state change every frame
private bool wasGrounded;
private void Update()
{
bool grounded = IsGrounded();
if (grounded != wasGrounded)
{
OnGroundedChanged(grounded);
}
wasGrounded = grounded;
}
// ✅ GOOD - Event-driven
public event Action<bool> OnGroundedChanged;
private bool isGrounded;
private void SetGrounded(bool grounded)
{
if (isGrounded != grounded)
{
isGrounded = grounded;
OnGroundedChanged?.Invoke(grounded);
}
}
Avoid allocations in frequently-called methods to prevent GC spikes.
// ❌ BAD - Allocates strings every frame
private void Update()
{
string message = "Health: " + health; // String allocation
scoreText.text = "Score: " + score; // String allocation
}
// ✅ GOOD - Use StringBuilder or string interpolation
private StringBuilder sb = new StringBuilder();
private void UpdateUI()
{
sb.Clear();
sb.Append("Health: ").Append(health);
healthText.text = sb.ToString();
}
// ✅ ALTERNATIVE - Cache formatted strings
private void UpdateHealth(int newHealth)
{
health = newHealth;
healthText.text = health.ToString(); // Less allocation than concatenation
}
// ❌ BAD - Allocates new list every frame
private void Update()
{
List<Enemy> nearbyEnemies = new List<Enemy>(); // GC allocation!
FindNearbyEnemies(nearbyEnemies);
}
// ✅ GOOD - Reuse list
private List<Enemy> nearbyEnemies = new List<Enemy>();
private void Update()
{
nearbyEnemies.Clear(); // Reuse existing list
FindNearbyEnemies(nearbyEnemies);
}
// ❌ BAD - ToArray allocates
private void Update()
{
GameObject[] enemies = enemyList.ToArray(); // GC allocation!
}
// ✅ GOOD - Iterate list directly
private void Update()
{
for (int i = 0; i < enemyList.Count; i++)
{
Enemy enemy = enemyList[i];
// Process enemy
}
}
// ✅ GOOD - Use foreach (no allocation for List)
private void Update()
{
foreach (var enemy in enemyList)
{
// Process enemy
}
}
// ❌ BAD - Allocates WaitForSeconds every call
private IEnumerator DelayedAction()
{
yield return new WaitForSeconds(1f); // New allocation each time
}
// ✅ GOOD - Cache WaitForSeconds
private WaitForSeconds oneSecondWait = new WaitForSeconds(1f);
private IEnumerator DelayedAction()
{
yield return oneSecondWait; // Reuse cached wait
}
// ❌ BAD - Multiple GetComponent calls
private void OnTriggerEnter(Collider other)
{
if (other.GetComponent<Enemy>() != null)
{
other.GetComponent<Enemy>().TakeDamage(10); // Called twice!
}
}
// ✅ GOOD - Single GetComponent with pattern matching
private void OnTriggerEnter(Collider other)
{
if (other.TryGetComponent<Enemy>(out var enemy))
{
enemy.TakeDamage(10); // Called once
}
}
// ❌ BAD - GetComponent on every collision
private void OnTriggerEnter(Collider other)
{
var damageable = other.GetComponent<IDamageable>();
if (damageable != null)
damageable.TakeDamage(10);
}
// ✅ GOOD - Cache component on trigger enter
private Dictionary<Collider, IDamageable> damageableCache = new Dictionary<Collider, IDamageable>();
private void OnTriggerEnter(Collider other)
{
if (!damageableCache.TryGetValue(other, out var damageable))
{
damageable = other.GetComponent<IDamageable>();
damageableCache[other] = damageable; // Cache for future collisions
}
damageable?.TakeDamage(10);
}
private void OnTriggerExit(Collider other)
{
damageableCache.Remove(other); // Clean up cache
}
Configure Physics Layer Collision Matrix to prevent unnecessary collision checks:
Edit > Project Settings > Physics > Layer Collision Matrix
// Setup layers
Layer 8: Player
Layer 9: Enemies
Layer 10: Projectiles
Layer 11: Environment
// Disable unnecessary collisions:
- Player vs Player (disabled)
- Enemies vs Enemies (disabled)
- Projectiles vs Projectiles (disabled)
Performance gain : 30-50% reduction in physics overhead.
// ❌ BAD - Raycast checks everything
bool hit = Physics.Raycast(origin, direction, out RaycastHit hitInfo);
// ✅ GOOD - Layer mask limits checks
int layerMask = 1 << LayerMask.NameToLayer("Enemy");
bool hit = Physics.Raycast(origin, direction, out RaycastHit hitInfo, maxDistance, layerMask);
// ✅ BETTER - Cache layer mask
private int enemyLayerMask;
private void Awake()
{
enemyLayerMask = 1 << LayerMask.NameToLayer("Enemy");
}
private void Fire()
{
bool hit = Physics.Raycast(origin, direction, out RaycastHit hitInfo, maxDistance, enemyLayerMask);
}
Let Rigidbody sleep when not moving:
// Rigidbody automatically sleeps when velocity < threshold
// Configure in Edit > Project Settings > Physics
// Wake up manually when needed
private void ApplyForce()
{
if (rb.IsSleeping())
rb.WakeUp();
rb.AddForce(force);
}
Measure before optimizing. Use Unity Profiler to identify actual bottlenecks.
Open Profiler: Window > Analysis > Profiler
CPU Usage:
Memory:
Enable Deep Profile for detailed call stack (impacts performance):
Warning : Deep Profile slows game significantly. Use for small scenes or targeted profiling.
Measure specific code sections:
using Unity.Profiling;
public class AIController : MonoBehaviour
{
private static readonly ProfilerMarker s_PathfindingMarker = new ProfilerMarker("AI.Pathfinding");
private static readonly ProfilerMarker s_DecisionMarker = new ProfilerMarker("AI.DecisionMaking");
private void Update()
{
s_PathfindingMarker.Begin();
CalculatePath();
s_PathfindingMarker.End();
s_DecisionMarker.Begin();
MakeDecision();
s_DecisionMarker.End();
}
private void CalculatePath() { }
private void MakeDecision() { }
}
Shows custom markers in Profiler for precise measurement.
Set performance targets for each system:
Target: 60 FPS (16.67ms per frame)
Monitor with Profiler and optimize systems exceeding budget.
Key concerns:
Mobile-specific optimizations:
More headroom but still optimize:
For detailed performance techniques, consult:
references/memory-optimization.md - Advanced GC reduction, allocation patternsreferences/rendering-optimization.md - Draw call batching, GPU optimization, shadersreferences/physics-optimization.md - Collision optimization, Rigidbody best practicesreferences/profiling-guide.md - Complete profiling workflows, tools, analysisCaching priorities:
Avoid in Update:
Always profile before optimizing:
Apply these performance practices consistently for smooth, responsive Unity games across all platforms.
Weekly Installs
0
Repository
GitHub Stars
3
First Seen
Jan 1, 1970
Security Audits
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
103,800 周安装
OpenAPI 转 TypeScript 工具 - 自动生成 API 接口与类型守卫
563 周安装
数据库模式设计器 - 内置最佳实践,自动生成生产级SQL/NoSQL数据库架构
564 周安装
Rust Unsafe代码检查器 - 安全使用Unsafe Rust的完整指南与最佳实践
564 周安装
.NET并发编程模式指南:async/await、Channels、Akka.NET选择决策树
565 周安装
韩语语法检查器 - 基于国立国语院标准的拼写、空格、语法、标点错误检测与纠正
565 周安装
技能安全扫描器 - 检测Claude技能安全漏洞,防范提示注入与恶意代码
565 周安装