Giter Club home page Giter Club logo

unreal-rust's Introduction

๐Ÿฆ€ unreal-rust

Opinionated Rust integration for Unreal Engine

Build Status LICENSE LICENSE Discord

โ˜ฃ๏ธ Warning

unreal-rust is not ready to be used in a real project. unreal-rust is in a very early state and nothing more than a proof of concept right now. The API will change quite frequently. Things might crash, or not work as intended. The user experience will not be great.

I am releasing unreal-rust on github to develop it in the open.

๐ŸŽฏ Features

  • Simple opinionated bindings: Easy access to core APIs like playing sounds, spawning actors, pathfinding, physics etc.
  • Developer friendly: Fast iteration times with hot reloading in the editor and during live play. Panics are caught and do not crash the editor
  • Editor integration: Add Rust components to actors in the editor, or access Rust components from Blueprint to drive animations.
  • Entity Component System: unreal-rust is built on top of an ECS.
  • Built on top of AActor: Most gameplay features like GameMode, Characters, GameState, GAS are not directly accessible in unreal-rust. Instead unreal-rust will provide optional alternatives. But you can still interact with most parts of the engine as Rust components can be accessed in Blueprint.
  • No engine modifications: unreal-rust is only a Plugin, just drop it in your project. See Supported versions for more information.
  • Samples: The development of unreal-rust is heavily driven by samples.
  • Free: Dual licensed under MIT/APACHE

๐Ÿ–ฅ๏ธ Supported Platforms

  • ๐Ÿง Linux
  • ๐ŸชŸ Windows

Potential future platforms: iOS, macOS, Android, html5/browser(possibly)

Consoles are unsupported. I simply can not offer console support as it is a closed off ecosystem. Nor do I have access to any developer kits myself.

๐Ÿ’Œ Blog posts / media

๐Ÿšฉ Known problems

  • This is just a hobby project of mine that I work on outside of my normal work hours. I might be slow to respond to issues, questions, feature requests, or PR reviews.

๐Ÿฆฎ Getting started

Running the example

I am aware that these are a lot of steps. I am sorry, I will try to simplify this in the future

  • Prerequisites:
    • Get git lfs, and run git lfs install
    • ue4cli, You can get it with pip3 install ue4cli. This step is optional but I will use ue4cli in this guide.

We start by cloning this repository

git clone https://github.com/MaikKlein/unreal-rust

Next we clone the submodule. This will download the actual example with all the assets.

cd unreal-rust
git submodule update --init

Next we need to setup the example

    • Linux sh setup.sh
    • Windows setup.bat

This will symlink the RustPlugin into the unreal example/RustExample/Plugin folder.

Now we need to build the actual Rust code:

Simply run

cargo build --release

This will build the whole project. This also produces our dll that we are going to load into Unreal.

Copy the dll/so file into the project

  • Linux: cp target/release/libunreal_rust_example.so example/RustExample/Binaries/rustplugin.so
  • Windows: copy .\target\release\unreal_rust_example.dll .\example\RustExample\Binaries\rustplugin.dll

Now we need to build the unreal example

cd example/RustExample
ue4 build Development Editor

Now you can run the example with ue4 run

๐Ÿš€ Supported versions

  • 5.0

This project will always try to support the latest version.

  • Latest version of Unreal
  • Latest version of Rust
  • Latest version of all dependencies

๐Ÿค Alternatives

๐Ÿฅฐ Thank you

unreal-rust's People

Contributors

maikklein avatar tusharxoxoxo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

unreal-rust's Issues

Usage with rust-bindgen

Was thinking it might be possible to use the rust-bindgen package to generate ffi instead of writing it manually... Thoughts?

Support for Mac

Hi,

I'm very excited about this project. I'm on a Mac OS, learning Rust and wanting to start working with Unreal.
I'd obviously be very interested to see support for Mac OS as well. How can I help make this happen?

Cheers

Nats integration

I am working on e posing this bad boy over nats.

there is a good rust Nats driver

this then allows the library to be able to be controlled from any language that nats supports which is about 20 I think.

Let me know if your I terraced in this.

I donโ€™t know yet if I should use protobuf buffers as the types and if the rust api is generic enough to even expose the types over NATS.

Nats will mean that thousands of real time actors ( client or servers ) can control unreal

Low level physics integration

Right now unreal-rust uses a high level physics api based on AActor and UPrimitiveComponent. It might be worth going more low level to FPysicsInterface / FBodyInstance.

Reasons

  • More direct access to physics
  • Potentially thread safe apis

Hot Reload

How do you achieve hot reloading in UE5? Are you just using cargo-watch or hot-lib-reloader to do this in you demo videos or should this just work out of the box?

Mouse input jitters sometimes

Occasionally when starting a new play session, the camera input will be very jittery for the whole session. This usually goes away by starting a new session.

Support for linux

  • Support finding .so files
  • More?

The editor startup times are extremely slow for UE5 on linux. On my machine roughly 3 min. This makes it impossible to develop unreal-rust on linux as I crash the editor through ffi fairly often.

ffi

Hi MaikKlein.
I've tried to use cxx to build FFI wrappers, but I found this way is almost on the opposite way to bind ue apis to rust.
Then I tried another way, using clang ast-dump tool to find "all" the "Runtime/" headers, then export all(maybe) these safe apis and generate FFI bind wrappers from cpp and rust. But it's still very experimental.
I'm unreal newer, but do not like to build or develop a game using c++.Hope this will give you some help.
Blow are the examples:
rust side:

use std::{ffi::c_void, os::raw::c_char};
use ffis::*;
pub type UObjectOpaque = c_void;//cpp type UObject
pub struct UObject{
    inner: *mut UObjectOpaque
}
impl UObject{
    #[inline]
    pub fn AbortInsideMemberFunction(&self){
        unsafe{ UObject_AbortInsideMemberFunctionInvokerHandler.as_ref().unwrap()(self.inner) }
    }
    #[inline]
    pub fn AreNativePropertiesIdenticalTo(&self, Other: *mut UObjectOpaque) -> bool{
        unsafe{ UObject_AreNativePropertiesIdenticalToInvokerHandler.as_ref().unwrap()(self.inner, Other) }
    }
}
mod ffis{
    use super::*;
    type UObject_AbortInsideMemberFunctionInvoker = unsafe extern "C" fn(*mut c_void);
    pub(super) static mut UObject_AbortInsideMemberFunctionInvokerHandler: Option<UObject_AbortInsideMemberFunctionInvoker> = None;
    #[no_mangle]
    extern "C" fn set_UObject_AbortInsideMemberFunction_handler(handler: UObject_AbortInsideMemberFunctionInvoker){
        unsafe{ UObject_AbortInsideMemberFunctionInvokerHandler = Some(handler) };
    }

    type UObject_AreNativePropertiesIdenticalToInvoker = unsafe extern "C" fn(*mut c_void, *mut UObjectOpaque) -> bool;
    pub(super) static mut UObject_AreNativePropertiesIdenticalToInvokerHandler: Option<UObject_AreNativePropertiesIdenticalToInvoker> = None;
    #[no_mangle]
    extern "C" fn set_UObject_AreNativePropertiesIdenticalTo_handler(handler: UObject_AreNativePropertiesIdenticalToInvoker){
        unsafe{ UObject_AreNativePropertiesIdenticalToInvokerHandler = Some(handler) };
    }
}

cpp side Rigister:

//#include "CoreMinimal.h"
//#include "Binder.h"
using uapi_UObject_AbortInsideMemberFunctionFn = void(*)(void* target);
using uapi_UObject_AreNativePropertiesIdenticalToFn = bool(*)(void* target,UObject* Other);
class Plugin{
    public:
    void* GetDllExport(FString apiName);
}
//auto generated register entry
void register_all(Plugin* plugin){    
    auto const apiuapi_UObject_AbortInsideMemberFunction = (uapi_UObject_AbortInsideMemberFunctionFn)plugin->GetDllExport(TEXT("set_UObject_AbortInsideMemberFunction_handler\0"));
    if(apiuapi_UObject_AbortInsideMemberFunction){
        apiuapi_UObject_AbortInsideMemberFunction(&uapi_UObject_AbortInsideMemberFunction);
    }

    auto const apiuapi_UObject_AreNativePropertiesIdenticalTo = (uapi_UObject_AreNativePropertiesIdenticalToFn)plugin->GetDllExport(TEXT("set_UObject_AreNativePropertiesIdenticalTo_handler\0"));
    if(apiuapi_UObject_AreNativePropertiesIdenticalTo){
        apiuapi_UObject_AreNativePropertiesIdenticalTo(&uapi_UObject_AreNativePropertiesIdenticalTo);
    }
}

cpp side Binder:

//#include "CoreUObject/Public/UObject/Object.h"
extern "C"{
void uapi_UObject_AbortInsideMemberFunction(void* target){
        ((UObject*)target)->AbortInsideMemberFunction();
    }
bool uapi_UObject_AreNativePropertiesIdenticalTo(void* target, UObject* Other){
        return  ((UObject*)target)->AreNativePropertiesIdenticalTo(Other);
    }
}

The project url is https://github.com/DrYaling/UnrealObject2RustBuilder.git

Load Errors & Malformed Tags

Sorry if this is trivial, first time using UE ever.

Version: UE 5.0.3
No issues with :
~/unreal-rust/example/RustExample$ ue4 build Development Editor
Occurs after:
~/unreal-rust/example/RustExample$ ue4 run

Issue:
Bunch of load errors and malformed tags issues:
(Basically a bunch of these errors, I have omitted most of these, since they're all the same just for different assets.)

[2022.09.22-07.35.09:402][  0]LoadErrors: Error: The summary for the package '/Game/Assets/Kits/NatureKit/flower_redA_flower_redA' is invalid. Check that the file is of the expected type and not corrupted.
[2022.09.22-07.35.09:402][  0]LoadErrors: Error: The summary for the package '/Game/Assets/Kits/NatureKit/flower_redA_flower_redA' is invalid. Check that the file is of the expected type and not corrupted.
[2022.09.22-07.35.09:402][  0]LoadErrors: Error: The summary for the package '/Game/Assets/Kits/NatureKit/flower_redA_flower_redA' is invalid. Check that the file is of the expected type and not corrupted.
[2022.09.22-07.35.09:402][  0]LoadErrors: Error: The summary for the package '/Game/Assets/Kits/NatureKit/flower_redA_flower_redA' 
[2022.09.22-07.33.24:806][  0]LogAssetRegistry: Error: Package /home/us/unreal-rust/example/RustExample/Content/Assets/Kits/NatureKit/tree_pineSmallA_tree_pineSmallA.uasset has malformed tag
[2022.09.22-07.33.24:806][  0]LogAssetRegistry: Error: Package /home/us/unreal-rust/example/RustExample/Content/Assets/Kits/NatureKit/tree_palm_tree_palm.uasset has malformed tag
[2022.09.22-07.33.24:806][  0]LogAssetRegistry: Error: Package /home/us/unreal-rust/example/RustExample/Content/Assets/Kits/NatureKit/tree_palm_tree_palm.uasset has malformed tag
[2022.09.22-07.33.24:806][  0]LogAssetRegistry: Error: Package /home/us/unreal-rust/example/RustExample/Content/Assets/Kits/NatureKit/tree_pineDefaultB_tree_pineDefaultB_FoliageType.uasset has malformed tag
[2022.09.22-07.33.24:806][  0]LogAssetRegistry: Error: Package /home/us/unreal-rust/example/RustExample/Content/Assets/Kits/NatureKit/tree_pineDefaultB_tree_pineDefaultB_FoliageType.uasset has malformed tag

First prototype

  • Create simple rust c dll with common entry points
  • Load rust dll in unreal
  • hot reload dll
  • Add Bevy-ecs
  • Register RustActors on startup
  • Create C ffi ActorComponent
  • Basic ffi actor functions like set_position
  • Hook up input
  • Expose some physics ffi functions
  • Implement simple movement system
  • Expose some rust ecs stuff to blueprint
  • Drive an animation blueprint with rust
  • Try to use bevy meta
    • Expose a c ffi reflection api
  • Register reflection information in unreal
  • Create a simple details panel for rust components
  • logging with tracing adapter
  • profiler scopes with marco/proc-macro

Contribution guidelines

First of thank you ๐Ÿ™. The project right now mostly lives inside my head. In the next few weeks I'll create more issues detailing the work that needs to be done. I will also keep this issues updated.

You can start by reading following https://github.com/MaikKlein/unreal-rust#-getting-started and try to run the example. I think the best place right now would be to build your own game/sample.
Try to understand how things work and feel free to play around with it. If you want to do some gameplay, you will most likely run into a lot of limitations and that is okay.

If something is not working or missing, please create an issue for it. If you feel adventures you can start by creating new bindings for the things you need. I wrote down how the FFI works here.

If you have some CI/backend experience I would love to setup a CI for unreal. #8 It would be nice to make sure PRs actually compile ๐Ÿ˜… .

Look for issues with "question" if you have unreal experience. Any help is very much appreciated ๐Ÿ’˜.

If you are not interested in gameplay, there are lots of core things that can be improved. For example the FFI layers required code duplication for function pointers and function definitions. Can we get rid of that? Maybe we can get some better ffi interop by using https://cxx.rs/?
Or maybe we can actually generate most of the ffi bindings automatically with UHT (Unreal header tool)?

Want to chat? Feel free to join our Discord https://discord.gg/jyM6fBBdt6

Log safty

void Log(const char* s, int32 len)
{
    // TODO: Can we get rid of that allocation?
    FString LogString = FString(len, UTF8_TO_TCHAR(s));
    UE_LOG(LogTemp, Warning, TEXT("%s"), *LogString);
}

I'm not sure whether UTF8_TO_TCHAR(s) will lead to undefined behavior. This MACRO will call utf8 conversion of option ENullTerminatedString::Yes, but rust native string end with no \0
Maybe use

 (TCHAR*)FUTF8ToTCHAR((const ANSICHAR*)str, (int32)len).Get()

should be safer?

Add docs on how to integrate with new & existing UE project

It would be nice to have some documentation on how to use this with an existing UE project, or even a brand new project.

So far, for adding to an existing project, I've copied over the RustPlugin to my Plugins directory, and the .dll into Binaries, but I'm not sure where to write my Rust code, and place my Cargo.toml... and how to link that project with my game.

Get rid of URustGameModeBase

Right now unreal-rust uses URustGameModeBase to hook up into the engine. GameModes in unreal are quite opinionated, maybe we can hook into the engine at an earlier time?

Create our own UWorld/GameInstance?

Setup a CI

We need a ci that builds and tests

  • All of the rust crates in this repo

We need an CI for unreal.

  • Cross compile on Windows and Linux
  • Lints: clang-tidy, clang format, and more
  • Package examples for Windows and Linux

Github actions: Actions doesn't seem to be capable of running the docker images for unreal. Neither the standard nor the slim image seem to work and both run out of diskspace.

Maybe we can set up our own server for this? I'd be happy for some advice here.

Q: Could you use Bevy ECS?

Is the ECS managed from the C++ side of the plugin or could bevy's ECS be integrated instead from rust side? The ergonomics of their ECS would be awesome in UE

Licensing questions

https://www.unrealengine.com/en-US/eula/creators

a. Non-Engine Products - You may Distribute Non-Engine Products to any third party. โ€œNon-Engine Productโ€ means a Product made using the Licensed Technology that does not include any Engine Code or any Paid Content Distributed in uncooked source format (in each case, including as modified by you under the License) and does not require any Engine Code (including as modified by you under the License) to run. For example, and subject to the foregoing, you may freely Distribute non-interactive linear media products (e.g., broadcast or streamed video files, cartoons, movies, or images) rendered using the Engine Code, and asset files (other than UE-Only Content) developed or used with the Engine Code, including in products that use or rely on other video game engines. For clarity, this section does not constitute a license under any patents, copyrights, trademarks, trade secrets or other intellectual property rights, whether by implication, estoppel or otherwise.

This plugin does not contain any engine code, nor paid content

g. Distribution of Paid Plug-ins - You may Distribute Paid Plug-ins to each of your Paid Plug-in Users so that they may use those Paid Plug-ins on your behalf under the Engine License.

Not sure if this is relevant as this plugin is free.

h. Distribution and sublicensing of Examples - You may Distribute or sublicense Examples (including as modified by you under the License) in Source Code or object code format to any third party. However, the rights in this Section 1(A)(h) do not expand or modify your limited Distribution and sublicensing rights for Engine Code and Content (including as modified by you under the Engine License) that are not Examples.

This seems like I am allowed to use example content in this project. I'd use this content to write Rust specific examples.

i. Distribution of Non-C++ Programming Language Integration - You may Distribute an integration of a programming language other than C++ for the Licensed Technology, but if you do, the integration must be Distributed free of charge to all Engine Licensees, must be available in Source Code form (including, but not limited to, any compiler, linker, toolchain, and runtime), and must permit Distribution free of charge, on all platforms, in any Product.

Weirdly specific. I am not sure how a language integration is different from a plugin. In any case this plugin will be free to use and does not violate this clause.

You may not sublicense the Licensed Technology in Source Code format. You may not sublicense the Licensed Technology in object code format, or any Content, except to grant Related Parties, Clients, or end users the ability to use a Product as permitted in Section 1(A), or to permit your publishers and distributors to market and Distribute an Exempt Product as permitted in Section 1(A)(c) above. This paragraph does not limit your rights to Distribute and sublicense Examples. Any other Distribution or sublicensing of Licensed Technology is permitted only if and to the extent authorized under an Unrealยฎ Engine End User License Agreement and/or a Custom License you may have with Epic.

This plugin will be license under MIT and APACHE

Other open source projects:

Open Questions:

  • Non of the example content has a license included but are explicitly licensed under the engine license. Do I need to include the engine license in this repo?

Top down action sample

The next sample will be a top down action game sample. It should be fairly simple, and inspired by some V rising gameplay. This forces me to fix/implement a bunch of things.
This will also serve as a benchmark as we can simply spawn more units and see where the bottlenecks are.

  • Camera: Top down, can rotate and move with the player
  • Expose unreal parenting/attachments to Rust
  • Add Camera shakes
  • Find Attack animations
  • Add animation notifies to Rust. With this we can do gameplay things during an animation like axe throwing.
  • Access to skeletal mesh sockets, so we know where our hands/weapon is during an animation.
  • Change spawning actor to accept a custom UClass*, so we can spawn enemies which are defined in the editor
  • Expose some navigation api to Rust. Most of the api seems to use shared ptr and we need to find a way to have those in ffi.
  • Enemies should be turned into ragdolls on death.
  • Add spells/abilities.
  • Bigger levels with streaming?
  • ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.