Game Dev Cheat Sheet

Compiler errors

error CS1061: 'X' does not contain a definition for 'Y' and no accessible extension method 'Y' accepting a first argument of type 'X' could be found

The exact message

error CS1061: 'X' does not contain a definition for 'Y' and no accessible extension method 'Y' accepting a first argument of type 'X' could be found
Variants of this message
  • does not contain a definition for
  • and no accessible extension method
  • CS1061
  • error CS1061: 'Collision' does not contain a definition for 'GetComponent' and no accessible extension method 'GetComponent' accepting a first argument of type 'Collision' could be found (are you missing a using directive or an assembly reference?)

What it means

You called a method or read a property that does not exist on the type you called it on. The message names both: the first quoted name is the type, the second is the member you asked for. The most useful thing about it is that the type is stated explicitly, which frequently reveals that the variable is not the type you assumed it was.

Causes and fixes

Ranked by how often they actually occur, most common first.

  1. The member name is misspelt or has the wrong casing

    AddListner for AddListener, enable for enabled, GetComponant for GetComponent. C# is case sensitive and Unity's API mixes conventions, with fields such as enabled in lower case and methods in Pascal case, so this is easy to get wrong and quick to rule out.

    The fix: Retype the member and let autocomplete complete it. If autocomplete does not offer what you expect, the problem is the type rather than the spelling, which is the next cause.

    Source: Unity Support: What is CS1061?

  2. The variable is not the type you think it is

    The classic Unity case is OnCollisionEnter, whose parameter is a Collision rather than a Collider or a GameObject. Collision has no GetComponent, so calling it there fails even though the same call works everywhere else. Any API that hands you a wrapper object rather than the object itself produces this, and the message tells you exactly which type you actually have.

    The fix: Read the type in the message and go through the right property. Collision exposes the other object as collision.gameObject and its collider as collision.collider, and both of those do have GetComponent.

    Collision wraps the object; Collider is the object's component.

    using UnityEngine;
    
    public class Projectile : MonoBehaviour
    {
        void OnCollisionEnter(Collision collision)
        {
            // Wrong: Collision has no GetComponent.
            // collision.GetComponent<Health>();
    
            // Right: go through the GameObject or the Collider.
            if (collision.gameObject.TryGetComponent(out Health health))
            {
                health.Apply(-10);
            }
        }
    
        void OnTriggerEnter(Collider other)
        {
            // A trigger hands you the Collider directly, so this one does work.
            other.GetComponent<Health>();
        }
    }
    
    public class Health : MonoBehaviour
    {
        public void Apply(int delta) { }
    }

    Source: Unity Discussions: CS1061 on Collision does not contain a definition for GetComponent, Unity Scripting API: Collision

  3. The member exists but is private

    A member declared without an access modifier is private in C#, so it is invisible outside its own class. The compiler reports it as not existing rather than as inaccessible, which is misleading: you can see it in the file, so the message reads as wrong. Fields you added for the Inspector with [SerializeField] are the usual case, because that attribute does not change accessibility.

    The fix: Make the member public if other classes genuinely need it, or better, expose only what is needed through a public method or a property with a private setter. [SerializeField] on a private field is the right way to show something in the Inspector without exposing it to other code.

    Serialised in the Inspector, readable from outside, writable only from within.

    using UnityEngine;
    
    public class Player : MonoBehaviour
    {
        [SerializeField] private int health = 100;
    
        // Visible to other scripts without letting them assign it directly.
        public int Health => health;
    
        public void Damage(int amount) => health = Mathf.Max(0, health - amount);
    }

    Source: Unity Support: What is CS0122?

  4. The extension method's namespace is not imported

    The second half of the message, about extension methods, is the part people skip, and it is often the answer. LINQ operators such as Any, Where and Select are extension methods that only exist when System.Linq is imported. Without it the compiler reports the member as absent from the type rather than telling you an import is missing.

    The fix: Add the using directive for the namespace that supplies the extension. System.Linq covers the LINQ operators; a package's own extensions are named on its documentation page.

    Without the System.Linq import, every call below reports CS1061.

    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    
    public class Squad : MonoBehaviour
    {
        [SerializeField] private List<Health> members = new();
    
        public bool AnyAlive() => members.Any(m => m != null);
    
        public Health Weakest() => members
            .Where(m => m != null)
            .OrderBy(m => m.Health)
            .FirstOrDefault();
    }

    Source: Unity Support: What is CS1061?

  5. The API was renamed or removed in a newer Unity version

    Code copied from an older tutorial can reference members that no longer exist. Rigidbody.velocity became linearVelocity in Unity 6, and the legacy Input class is absent entirely in projects configured to use only the new Input System. The code was correct when it was written, which makes this hard to spot by reading it.

    The fix: Check the member on the Scripting API page for your Unity version; removed members are usually documented with their replacement. Where the difference is the Input System, Project Settings > Player > Active Input Handling controls which API is available.

    Source: Unity Scripting API: Rigidbody.linearVelocity

How to prevent it

Read the type in the message before looking at your code. CS1061 states the type it was given, and that is frequently the surprise: the variable is a Collision rather than a Collider, or a GameObject rather than the component you meant.

Prefer [SerializeField] on private fields over making fields public. It gets the Inspector behaviour without widening access, which keeps this error pointing at genuine mistakes rather than at deliberate encapsulation.

Check the Unity version a tutorial targets before following it. API renames are the least obvious cause of this error and the most time-consuming to diagnose, because the code looks right.

Let autocomplete type member names for you. It fails fast and visibly when the type is not what you expected, which is quicker feedback than a compile.

Unity version differences

CS1061 is a standard C# compiler error, identical across Unity versions. Which members exist is what varies: Rigidbody.velocity was renamed to linearVelocity in Unity 6, and the legacy Input class is unavailable when Active Input Handling is set to Input System Package only.

Sources

Frequently asked questions

What does the extension method part of the message mean?
The compiler is telling you it checked twice: once for a member declared on the type, and once for an extension method that takes that type as its first argument. Both failed. It matters because it points at a missing using directive, which is the usual cause when the member is a LINQ operator such as Any or Where and System.Linq has not been imported.
Why does GetComponent fail inside OnCollisionEnter but work in OnTriggerEnter?
Because the parameter types differ. OnCollisionEnter receives a Collision, which describes the collision event and is not a component, so it has no GetComponent. OnTriggerEnter receives a Collider, which is a component and does. From a Collision, use collision.gameObject or collision.collider.
What is the difference between CS1061 and CS0246?
CS0246 means the type itself could not be found. CS1061 means the type was found but the member on it was not. So CS0246 points at imports and assembly references, while CS1061 points at the member name, the type of the variable, or accessibility.
The member is right there in my class, so why does the compiler say it does not exist?
Most often because it is private. A field or method with no access modifier is private in C#, so it is invisible from other classes even though you can see it in the file. [SerializeField] does not change this; it only makes the field serialise. Expose it deliberately with a public property or method.
Why did this appear after upgrading Unity?
An API you were using was renamed or removed. Rigidbody.velocity to linearVelocity in Unity 6 is the most common recent one. Check the Scripting API page for the type in your new version; where a member was replaced rather than dropped, the documentation usually names the replacement.

Last updated: