UnrealSharp is a plugin for Unreal Engine 5 that allows game developers to use C# in their projects with the power of .NET 9. This plugin bridges the gap between C# and UE5, providing a seamless and efficient workflow for those who prefer C# over C++/Blueprints.
- C# Integration: Write your game logic in C#.
- Seamless Unreal Engine 5 Compatibility: Fully integrated with the latest UE5 features and API.
- Hot reload: Compile and reload code on the fly without having to restart the engine for changes.
- Automatic Bindings: Automatically generates C# API based on what is exposed to reflection.
- .NET Ecosystem: Use any NuGet package to extend functionality.
Check out UnrealSharp-Cropout, an ongoing effort to convert Cropout, originally created in Blueprints, into C# using UnrealSharp.
- Unreal Engine 5.3+ (Will support earlier versions in the future)
- .NET 9.0+
Visit the website's Get Started page!
If you want to contribute with documentation, you can contribute to this repository!
using UnrealSharp;
using UnrealSharp.Attributes;
using UnrealSharp.Engine;
using UnrealSharp.Niagara;
namespace ManagedSharpProject;
public delegate void OnIsPickedUp(bool bIsPickedUp);
[UClass]
// Partial classes are only a requirement if you want UnrealSharp to generate helper methods.
// Such as: MyCustomComponent foundComponent = MyCustomComponent.Get(actorReference);
public partial class AResourceBase : AActor, IInteractable
{
public AResourceBase()
{
SetReplicates(true);
RespawnTime = 500.0f;
}
// The mesh of the resource
[UProperty(DefaultComponent = true, RootComponent = true)]
public UStaticMeshComponent Mesh { get; set; }
// The health component of the resource, if it has one
[UProperty(DefaultComponent = true)]
public UHealthComponent HealthComponent { get; set; }
[UProperty(PropertyFlags.EditDefaultsOnly)]
public int PickUpAmount { get; set; }
// The time it takes for the resource to respawn
[UProperty(PropertyFlags.EditDefaultsOnly | PropertyFlags.BlueprintReadOnly)]
protected float RespawnTime { get; set; }
// Whether the resource has been picked up, is replicated to clients.
[UProperty(PropertyFlags.BlueprintReadOnly, ReplicatedUsing = nameof(OnRep_IsPickedUp))]
protected bool bIsPickedUp { get; set; }
// The effect to play when the resource is picked up
[UProperty(PropertyFlags.EditDefaultsOnly)]
public TSoftObjectPtr<UNiagaraSystem>? PickUpEffect { get; set; }
// The delegate to call when the resource is picked up, broadcasts on clients too.
[UProperty(PropertyFlags.BlueprintAssignable)]
public TMulticastDelegate<OnIsPickedUp> OnIsPickedUp { get; set; }
protected override void BeginPlay()
{
HealthComponent.OnDeath += OnDeath;
base.BeginPlay();
}
[UFunction]
protected virtual void OnDeath(APlayer player) {}
// Interface method implementation
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;
}
// Get the ExperienceComponent from the PlayerState using the generated helper methods.
UExperienceComponent experienceComponent = UExperienceComponent.Get(player.PlayerState);
experienceComponent.AddExperience(PickUpAmount);
// Respawn the resource after a certain amount of time
SetTimer(OnRespawned, RespawnTime, false);
bIsPickedUp = true;
OnRep_IsPickedUp();
}
[UFunction]
public void OnRespawned()
{
bIsPickedUp = false;
OnRep_IsPickedUp();
}
// This is called when the bIsPickedUp property is replicated
[UFunction]
public void OnRep_IsPickedUp()
{
if (PickUpEffect is not null)
{
UNiagaraFunctionLibrary.SpawnSystemAtLocation(this, PickUpEffect, GetActorLocation(), GetActorRotation());
}
OnIsPickedUpChanged(bIsPickedUp);
OnIsPickedUp.Invoke(bIsPickedUp);
}
// This can be overridden in blueprints
[UFunction(FunctionFlags.BlueprintEvent)]
public void OnIsPickedUpChanged(bool bIsPickedUp)
{
SetActorHiddenInGame(bIsPickedUp);
}
}
Take a look at the roadmap for planned and developed features!
Join the discord community to stay up to date with the recent updates and plugin support!
I accept pull requests and any contributions you make are greatly appreciated.
Distributed under the MIT License. See LICENSE
for more information.
Discord: olsson. (Yes, with a dot at the end.)
Or join the Discord community.
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.
Thank you to the MonoUE team!