UnrealSharp is a free, open-source plugin for writing Unreal Engine 5 games in C# on top of .NET 10.
- Unreal Engine API in C#: Derive from any UClass. Implement Actors, ActorComponents, and more in C# with access to the Unreal Engine API.
- Generated bindings: The C# API is generated from anything UE exposes to reflection, so new code and types from engine updates or plugins shows up automatically.
- Hot reload: Recompile and reload C# code without restarting the editor.
- Full .NET ecosystem: Pull in any NuGet package you need.
- MIT licensed
| Platform | Status |
|---|---|
| Windows | Supported |
| macOS | Supported |
| Linux | Planned |
| iOS | Planned |
| Android | Planned |
- Unreal Engine 5.5 - 5.7
- .NET 10.0.5 or newer
- A C++ project (strongly recommended, pure Blueprint projects work but are harder to support)
Visit the website's Get Started page!
If you want to contribute with documentation, you can contribute to this repository!
- Sample Defense Game built for Mini Jam 174.
- Slime Guzzler Epic MegaJam 2025 entry.
- UnrealSharp-Cropout Epic's Cropout sample, ported from Blueprints to C#.
A networked, interactable resource pickup written entirely in C#:
using UnrealSharp;
using UnrealSharp.Attributes;
using UnrealSharp.Engine;
using UnrealSharp.Niagara;
namespace ManagedSharpProject;
public delegate void OnIsPickedUp(bool bIsPickedUp);
[UClass]
public partial class AResourceBase : AActor, IInteractable
{
public AResourceBase()
{
Replicates = true;
RespawnTime = 500.0f;
}
[UProperty(DefaultComponent = true, RootComponent = true)]
public partial UStaticMeshComponent Mesh { get; set; }
[UProperty(DefaultComponent = true)]
public partial UHealthComponent HealthComponent { get; set; }
[UProperty(PropertyFlags.EditDefaultsOnly)]
public partial int PickUpAmount { get; set; }
[UProperty(PropertyFlags.EditDefaultsOnly | PropertyFlags.BlueprintReadOnly)]
protected partial float RespawnTime { get; set; }
[UProperty(PropertyFlags.BlueprintReadOnly, ReplicatedUsing = nameof(OnRep_IsPickedUp))]
protected partial bool bIsPickedUp { get; set; }
[UProperty(PropertyFlags.EditDefaultsOnly)]
public partial TSoftObjectPtr<UNiagaraSystem>? PickUpEffect { get; set; }
[UProperty(PropertyFlags.BlueprintAssignable)]
public partial TMulticastDelegate<OnIsPickedUp> OnIsPickedUp { get; set; }
public override void BeginPlay()
{
HealthComponent.OnDeath += OnDeath;
base.BeginPlay();
}
[UFunction]
protected virtual void OnDeath(APlayer player) {}
public void OnInteract(APlayer player)
{
GatherResource(player);
}
[UFunction(FunctionFlags.BlueprintCallable)]
protected void GatherResource(APlayer player)
{
if (bIsPickedUp)
{
return;
}
if (!player.Inventory.AddItem(this, PickUpAmount))
{
return;
}
UExperienceComponent experienceComponent = UExperienceComponent.Get(player.PlayerState);
experienceComponent.AddExperience(PickUpAmount);
SetTimer(OnRespawned, RespawnTime, false);
bIsPickedUp = true;
OnRep_IsPickedUp();
}
[UFunction]
public void OnRespawned()
{
bIsPickedUp = false;
OnRep_IsPickedUp();
}
[UFunction]
public void OnRep_IsPickedUp()
{
if (PickUpEffect is not null)
{
UNiagaraFunctionLibrary.SpawnSystemAtLocation(this, PickUpEffect, GetActorLocation(), GetActorRotation());
}
OnIsPickedUpChanged(bIsPickedUp);
OnIsPickedUp.Invoke(bIsPickedUp);
}
// Overridable from Blueprints
[UFunction(FunctionFlags.BlueprintEvent)]
public partial void OnIsPickedUpChanged(bool bIsPickedUp);
public partial void OnIsPickedUpChanged_Implementation(bool bIsPickedUp)
{
SetActorHiddenInGame(bIsPickedUp);
}
}I accept pull requests and any contributions you make are greatly appreciated.
MIT. See LICENSE for the full text.
Discord: olsson. (yes, with the dot at the end), or just join the Discord server.
I'd like to give a huge shoutout to MonoUE (Sadly abandoned :( ) for the great resource for integrating C# into Unreal Engine. Some of the systems are modified versions of their integration, and it's been a real time saver.