179 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			179 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|  | # UnrealSharp
 | ||
|  | 
 | ||
|  | ## Introduction
 | ||
|  | 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. | ||
|  | 
 | ||
|  | [Workflow Showcase](https://www.youtube.com/watch?v=NdbiysPTztA) | ||
|  | 
 | ||
|  | ## Features
 | ||
|  | - **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. | ||
|  | 
 | ||
|  | ## Sample Projects
 | ||
|  | 
 | ||
|  | [UnrealSharp-Cropout](https://github.com/UnrealSharp/UnrealSharp-Cropout/tree/main), originally created in Blueprints by Epic Games, now converted into C#. | ||
|  | 
 | ||
|  | [Sample Defense Game](https://github.com/UnrealSharp/UnrealSharp-SampleDefenseGame), project made for Mini Jam 174. | ||
|  | 
 | ||
|  | ## Prerequisites
 | ||
|  | - Unreal Engine 5.3 - 5.6 | ||
|  | - .NET 9.0+ | ||
|  | 
 | ||
|  | ## Frequently Asked Questions
 | ||
|  | 
 | ||
|  | [FAQ](https://www.unrealsharp.com/faq) | ||
|  | 
 | ||
|  | ## Get Started
 | ||
|  | 
 | ||
|  | Visit the website's [Get Started](https://www.unrealsharp.com/getting-started/quickstart) page! | ||
|  | 
 | ||
|  | If you want to contribute with documentation, you can contribute to this [repository](https://github.com/UnrealSharp/unrealsharp.github.io)! | ||
|  | 
 | ||
|  | ## Code Example
 | ||
|  | 
 | ||
|  | ```c# | ||
|  | 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); | ||
|  |     } | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | ## Roadmap
 | ||
|  | Take a look at the roadmap for planned and developed features! | ||
|  | 
 | ||
|  | [Roadmap](https://github.com/orgs/UnrealSharp/projects/3) | ||
|  | 
 | ||
|  | ## Discord Community 
 | ||
|  | Join the discord community to stay up to date with the recent updates and plugin support! | ||
|  | 
 | ||
|  | [Discord community](https://discord.gg/HQuJUYFxeV) | ||
|  | 
 | ||
|  | ## Contributing
 | ||
|  | I accept pull requests and any contributions you make are **greatly appreciated**. | ||
|  | 
 | ||
|  | ## License
 | ||
|  | Distributed under the MIT License. See `LICENSE` for more information. | ||
|  | 
 | ||
|  | ## Contact
 | ||
|  | Discord: **olsson.** (Yes, with a dot at the end.) | ||
|  | 
 | ||
|  | Or join the [Discord community](https://discord.gg/HQuJUYFxeV). | ||
|  | 
 | ||
|  | ## Special Thanks
 | ||
|  | I'd like to give a huge shoutout to [MonoUE](https://mono-ue.github.io/) (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!** | ||
|  | 
 |