You paste in some modern C# from a tutorial or an AI assistant and Unity refuses it with something like “Feature ‘file-scoped namespace’ is not available in C# 9.0. Please use language version 10.0 or greater.” The code is valid C#, just newer than Unity supports. This guide explains which C# version Unity 6 uses, which popular features are missing or partly supported, and the rewrites and workarounds that get your code compiling.
Which C# Version Unity Uses
Unity compiles your scripts with its own bundled Roslyn compiler, set to C# 9.0. That has been true since Unity 2021.2 and is still the case in Unity 6. Your installed .NET SDK and your IDE don’t change it. Visual Studio or Rider may happily accept C# 12 syntax in the editor, but Unity’s compiler decides, and it says no.
Unity is moving to the modern .NET runtime (CoreCLR) in a future version, which is expected to bring newer C# versions. Until your Unity version officially supports it, write C# 9.
What the Errors Look Like
The message names the feature, the version you have and the version you need:
error CS8773: Feature 'file-scoped namespace' is not available in C# 9.0.
Please use language version 10.0 or greater.
The error code differs by feature and version, but the wording “is not available in C# 9.0” is the giveaway. A few features fail with other errors instead, which are harder to recognise:
- CS0518 “Predefined type ‘System.Runtime.CompilerServices.IsExternalInit’ is not defined or imported” when using
initor records. - CS0656 “Missing compiler required member” for some newer attribute-based features.
- Syntax errors (like
CS1003orCS1525) for brand-new syntax such as collection expressions, because the parser doesn’t recognise it at all.
Common Features You Can’t Use (and the Fix)
These come up most, especially in code from recent tutorials and AI tools:
File-scoped namespaces (C# 10)
// Not allowed:
namespace Game.Combat;
// Use:
namespace Game.Combat
{
public class Weapon { }
}
Global usings (C# 10): global using UnityEngine; isn’t allowed. Add usings to each file.
Record structs and with on structs (C# 10): use a normal struct with a copy method.
Constant interpolated strings and extended property patterns (C# 10): { Owner.Health: < 10 } must become { Owner: { Health: < 10 } }.
Raw string literals (C# 11): """...""" isn’t allowed. Use verbatim strings @"..." with doubled quotes.
Required members (C# 11): required isn’t available. Use constructor parameters or validate in Awake/OnValidate.
Generic math and static abstract interface members (C# 11): not available. Use separate overloads or Unity.Mathematics.
Collection expressions (C# 12)
// Not allowed:
int[] values = [1, 2, 3];
List<string> names = [];
// Use:
int[] values = { 1, 2, 3 };
var names = new List<string>();
Primary constructors on classes (C# 12)
// Not allowed:
public class DamageCalc(int baseDamage) { public int Get() => baseDamage * 2; }
// Use:
public class DamageCalc
{
readonly int baseDamage;
public DamageCalc(int baseDamage) => this.baseDamage = baseDamage;
public int Get() => baseDamage * 2;
}
MonoBehaviours can’t use constructors for setup anyway; Unity creates them. Use Awake or an Init method. The Awake vs Start guide explains why.
C# 9 Features With Catches
Some C# 9 features work only partly in Unity:
- init-only setters and records need a type the Unity runtime doesn’t provide. Add this file once to your project and they compile:
namespace System.Runtime.CompilerServices
{
internal static class IsExternalInit { }
}
- Records are not serialized by Unity. Unity’s serializer (Inspector, prefabs,
JsonUtility) works with fields, so records with only init properties won’t show in the Inspector or save with JsonUtility. Use records for plain data passed around in code, and normal[Serializable]classes for anything Unity saves. - Not supported at all in Unity: covariant return types, module initializers, and a few low-level features like function pointers with unmanaged calling conventions on some platforms. You rarely need them in game code.
Pattern matching improvements (is not null, relational and logical patterns), target-typed new(), and static lambdas all work. Be careful with is null / is not null on Unity objects though: they bypass Unity’s overloaded ==, so a destroyed object is “not null”. Use == null or the implicit bool check for UnityEngine.Object types. The NullReferenceException guide explains this trap.
.NET API Level vs C# Version
There are two separate settings:
- C# language version (syntax): fixed at 9.0 by Unity.
- API Compatibility Level (which .NET library classes exist): set in Project Settings > Player > Other Settings. Options are .NET Standard 2.1 (default) and .NET Framework.
A method missing from the base library, like some newer string or LINQ methods, causes a CS0117 or CS1061 “does not contain a definition” error instead of a language version error. Switching to .NET Framework exposes more APIs, but newer .NET APIs (from .NET 5 and later) aren’t available either way. The compiler errors guide covers those errors.
What About Changing langversion?
You may find advice to add a csc.rsp file to Assets with -langversion:10 or -langversion:preview. Unity’s bundled compiler can parse some newer syntax, so a few features may compile. It’s not officially supported:
- Features that need runtime support can compile but fail in builds or on IL2CPP.
- Unity can change the compiler at any update and break your project.
- Teammates and CI need the same hack.
For a hobby project you might accept the risk. For anything you plan to ship, stick to C# 9.
Telling AI Tools Your C# Version
AI assistants are trained on lots of modern .NET code and often produce C# 10 to 12 syntax. Save yourself the rewrites by saying it upfront: “Unity 6, C# 9 only: no file-scoped namespaces, no collection expressions, no primary constructors, no records for serialized data.” If you keep a project instructions file for your AI tool, put that line in it. The AI hallucinated API guide covers more of these mismatches.
📚 Level up your C#
Knowing which features belong to which C# version makes these errors trivial. Our list of programming books for game developers includes solid C# references.
Troubleshooting
“Feature ‘file-scoped namespace’ is not available in C# 9.0”
Wrap the file’s contents in a block namespace with braces.
“Predefined type ‘System.Runtime.CompilerServices.IsExternalInit’ is not defined or imported”
Add the IsExternalInit class shown above, or replace init with set or a constructor.
Collection expression gives a syntax error
Use an array initializer or new List<T>() instead of square brackets.
My IDE shows no error but Unity does
The IDE is using a newer language version. Regenerate project files from External Tools so the IDE picks up Unity’s settings, and trust the Unity Console.
Record fields don’t show in the Inspector
Unity doesn’t serialize record properties. Use a normal serializable class with fields.
FAQ
What C# version does Unity 6 support?
C# 9.0, with a few C# 9 features unsupported or needing workarounds.
Will installing a newer .NET SDK help?
No. Unity uses its own compiler. The SDK only affects your IDE.
Can I use async/await?
Yes. async/await has been supported for years, and Unity 6 adds the Awaitable type for game code.
Can I use switch expressions?
Yes. Switch expressions are C# 8 and work fine.
When will Unity support newer C#?
Unity has said newer C# arrives with its move to modern .NET. Check your Unity version’s release notes.
Reader questions
Asked by readers of this article and answered by AI. Behavior can differ between Unity versions, so test in yours.




Leave a Reply