unity — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited unity (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
spikes and frame rate drops.
Instantiate or Destroy during active gameplay loops.Pre-warm pools during scene load.
GarbageCollector.GCMode.Manual (or GarbageCollector.Mode.Disabled) only for critical, predictable gameplaysegments with strictly bounded allocation budgets (e.g., a racing lap). Always re-enable incremental GC afterward to prevent OS-level memory pressure shutdowns.
StringBuilder in any loop that constructs strings. Never use + string concatenation inside Update or tightloops; each concatenation allocates a new managed string object.
Example pool pattern:
// Pre-warm
for (int i = 0; i < poolSize; i++)
_pool.Enqueue(Instantiate(prefab));
// Acquire
var obj = _pool.Count > 0 ? _pool.Dequeue() : Instantiate(prefab);
obj.SetActive(true);
// Release
obj.SetActive(false);
_pool.Enqueue(obj);Resources.Load. Use the Addressables system (com.unity.addressables) for all dynamic asset loading tooptimise memory footprint and reduce bundle sizes.
Addressables.LoadAssetAsync<T>() call must have a correspondingAddressables.Release() call when the asset is no longer needed.
AsyncOperationHandle structs is properly freed.
UI, Level_01, Shared_Audio) to minimise bundle download sizeand enable incremental content updates.
// Load
var handle = Addressables.LoadAssetAsync<Sprite>("ui/icons/health");
await handle.Task;
_healthIcon.sprite = handle.Result;
// Release when done
Addressables.Release(handle);instead of relying on arbitrary Unity load orders.
[DefaultExecutionOrder(N)] attribute on MonoBehaviours where the execution order matters: [DefaultExecutionOrder(-100)]
public class InputManager : MonoBehaviour { ... }UI).
GetComponent<T>() and FindObjectOfType<T>() calls in Awake() or Start(). Never call them insideUpdate() loops: they are expensive searches.
Awake() only when it is synchronous and fast. Defer non-critical setup toStart() or use async/UniTask to prevent blocking the main thread during scene loads.
OnEnable if the component may be destroyed and re-enabled; do not assume the cachedreference remains valid across scene reloads.
private Rigidbody _rb;
private Animator _animator;
private void Awake()
{
_rb = GetComponent<Rigidbody>();
_animator = GetComponent<Animator>();
}Physics.RaycastNonAlloc instead of Physics.RaycastAll to eliminate GC allocation during collision checks.Pre-allocate a results buffer at field level.
Transform.SetPositionAndRotation() rather thansetting position and rotation separately to avoid redundant internal transform updates.
ref or in keywords to preventunnecessary stack copying.
private readonly RaycastHit[] _hits = new RaycastHit[10];
private void Update()
{
int count = Physics.RaycastNonAlloc(transform.position, transform.forward, _hits, 10f);
for (int i = 0; i < count; i++) { /* process _hits[i] */ }
}MonoBehaviour class names must match their filename exactly.[SerializeField] private for Inspector-exposed fields. Never use public fields solely for Inspectorvisibility.
MyGame.Core, MyGame.UI). Do not place scripts in theglobal namespace.
_camelCasePascalCasePascalCase (C# convention, not UPPER_SNAKE_CASE)I: IInteractable, IDamageableBase: BaseDamageable, BaseWeaponsettings) instead of hardcoding values in MonoBehaviours.
GameEvent / GameEventListener pattern) for decoupled communicationbetween systems, replacing direct MonoBehaviour references and static events.
them only for immutable configuration data or event definitions.
// Data container
[CreateAssetMenu(menuName = "Game/WeaponData")]
public class WeaponData : ScriptableObject
{
public float damage;
public float fireRate;
public AudioClip shootSound;
}
// Event channel
[CreateAssetMenu(menuName = "Events/GameEvent")]
public class GameEvent : ScriptableObject
{
private readonly List<GameEventListener> _listeners = new();
public void Raise() => _listeners.ForEach(l => l.OnEventRaised());
public void Register(GameEventListener l) => _listeners.Add(l);
public void Unregister(GameEventListener l) => _listeners.Remove(l);
}com.unity.test-framework) for all automated tests. Organise tests in a dedicatedTests/ assembly definition (.asmdef).
required, fastest execution).
integration tests requiring a running scene.
create minimal test scenes.
// Edit Mode test
[Test]
public void WeaponData_DamageIsPositive()
{
var data = ScriptableObject.CreateInstance<WeaponData>();
data.damage = 25f;
Assert.Greater(data.damage, 0f);
}.gitignore excluding: Library/, Temp/, Logs/, Builds/, UserSettings/, *.csproj, *.sln (unlessneeded by CI).
diffs for scene and prefab files, enabling meaningful Git diffs and conflict resolution.
*.png *.jpg *.psd *.tga # Textures
*.wav *.mp3 *.ogg # Audio
*.fbx *.obj *.blend # 3D models
*.anim *.controller # Animation assets
*.unity *.prefab # Scenes & prefabs (optional, helps with large files)provides better runtime performance and enables code stripping via Managed Stripping Level settings.
every merge to the main branch.
modules installed.
Strip Engine Code: true, Managed Stripping Level: High) for release builds.Maintain a link.xml to preserve types used via reflection.
com.unity.inputsystem) for all new projects. Do not use the legacy Input class(Input.GetKey, Input.GetAxis, etc.).
.inputactions). Never hardcode key bindings in MonoBehaviours.for type-safe, IntelliSense-supported access.
private PlayerInputActions _inputActions;
private void Awake()
{
_inputActions = new PlayerInputActions();
_inputActions.Player.Jump.performed += OnJump;
}
private void OnEnable() => _inputActions.Enable();
private void OnDisable() => _inputActions.Disable();UIElements) for:Canvas-based) only for:~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.