Giter Site home page Giter Site logo

unrealenginepython's Introduction

UnrealEnginePython

Embed Python in Unreal Engine 4

Teaser (by Kite & Lightning): https://twitter.com/KNLstudio/status/932657812466843648

Fixing Mixamo RootMotion tuturial: https://github.com/20tab/UnrealEnginePython/blob/master/tutorials/FixingMixamoRootMotionWithPython.md

Funny snippets for working with StaticMesh and SkeletalMesh assets: https://github.com/20tab/UnrealEnginePython/blob/master/tutorials/SnippetsForStaticAndSkeletalMeshes.md

More tutorials: https://github.com/20tab/UnrealEnginePython/tree/master/tutorials

Project Status (IMPORTANT)

Currently (as april 2020) the project is on hold: between 2016 and 2018 20tab invested lot of resources in it but unfortunately epic (during 2018) decided to suddenly release its own implementation and the request made for a megagrant in 2019 by the original plugin author was rejected too.

As this plugin (still) has way more features than the Epic one and many contributors, we are currently looking for new maintainers helping us to keep it alive, checking PR and issues. If you are interested in working on it a few hours a week, drop us a line at [email protected] to discuss about it.

If you are interested in game logic scripting/modding in Unreal Engine 4 consider giving a look at the LuaMachine project (https://github.com/rdeioris/LuaMachine/).

The plugin should work up to unreal engine version 4.23 and there are forks/pull requests for 4.24. Since 4.25 Epic refactored the UProperty subsystem, so if you want to port the plugin to a version >= 4.25 you should make a lot of search & replace (basically renaming UProperty to FProperty and Cast to CastField should be enough)

How and Why ?

This is a plugin embedding a whole Python VM (versions 3.x [the default and suggested one] and 2.7) In Unreal Engine 4 (both the editor and runtime).

The Python VM tries to give easy access to all of the UE4 internal api + its reflection system. This means you can use the plugin to write other plugins, to automate tasks, to write unit tests and to implement gameplay elements.

It is not meant as a way to avoid blueprints or c++ but as a good companion to them (albeit reducing the amount of c++ required for coding a game could be an interesting thing ;). If your development pipeline is already python-based (Maya, Blender, ...), this plugin could easily help you in integrating unreal into it.

If you want to have an idea of what the plugin can do, jump here: https://github.com/20tab/UnrealEnginePython/blob/master/tutorials/YourFirstAutomatedPipeline.md

In addition to this, the plugin automatically adds an actor class (PyActor), a pawn class (PyPawn), a character class (PyCharacter) and a component class (PythonComponent) for "gentle" integration of python in your games.

In the spirit of automating tasks, even wrappers for third party libraries used by UE4 are exposed in a 'pythonic' way. As an example the FbxSdk is exposed to allow low-level interaction with Fbx files. This is an example extracting animation curves: https://github.com/20tab/UnrealEnginePython/blob/master/examples/fbx_curves_extractor.py

Another funny feature (well, a side effect ;) is that you can change your python code even after the project has been packaged. You can potentially build a completely new game from an already packaged one.

Once the plugin is installed and enabled, you get access to the 'PythonConsole' item in the 'Development Menu', you can use it to trigger python commands directly from the editor. There is even an experimental Editor/IDE included, you can run it from the Window/Layout/Python Editor menu item.

All of the exposed engine features are under the 'unreal_engine' virtual module (it is completely coded in c into the plugin, so do not expect to run 'import unreal_engine' from a standard python shell)

The minimal supported Unreal Engine version is 4.12, while the latest is 4.23

We support official python.org releases as well as IntelPython and Anaconda distributions.

Note: this plugin has nothing to do with the experimental 'PythonScriptPlugin' included in Unreal Engine >= 4.19. We aim at full integration with engine and editor (included the Slate api, check here: https://github.com/20tab/UnrealEnginePython/blob/master/docs/Slate_API.md), as well as support for the vast majority of python features like asyncio, coroutines, generators, threads and third party modules.

Binary installation on Windows (64 bit)

Check in the releases page (https://github.com/20tab/UnrealEnginePython/releases) if there is a binary version that matches your configuration (otherwise open an issue asking us for it [please specify the python version too]) and download it.

Binary releases are in two forms: standard and embedded. Standard uses the python installation of your system, so ensure the python installation directory is in your system PATH environment variable (otherwise you will get an error while loading your project). Embedded releases include an embedded python installation so you do not need to have python in your system.

Create (if it does not already exist) a Plugins directory in your project root directory (at the same level of Content/ and the .uproject file) and unzip the plugin into it. If your project is named FooBar you will end with FooBar/Plugins/UnrealEnginePython.

Open your project and go to the Edit/Plugins menu. Go to the bottom and under "Project/Scripting Languages" enable UnrealEnginePython.

Restart your project and you should see the PythonConsole under the "Window/Developer Tools" menu

Binary releases are mainly useful for editor scripting, if you want to package your project for distribution and you need the python runtime, you need a source release (see below).

If instead, you want to package your project without python, just remember to change the UnrealEnginePython.uplugin to have this line: https://github.com/20tab/UnrealEnginePython/blob/master/UnrealEnginePython.uplugin#L20 set as "Editor" instead of "Runtime"

Installation from sources on Windows (64 bit)

Currently python3.6, python3.5 and python2.7 are supported. It is highly suggested to have a python system wide installation (by default the official python distributions are installed in user's home directory) with the PATH environment variable including it (if you change the PATH variable remember to reboot the system before running the build procedure, this is not strictly required but will ensure the PATH is updated). If the PATH variable does not contain the path of your python installation you will see a warning in the build log/output.

Download a source official release or simply clone the repository for latest updates:

git clone https://github.com/20tab/UnrealEnginePython

By default the build procedure will try to discover your python installation looking at hardcoded known paths. If you want to specify a custom python installation (or the autodetection simply fails) you can change it in the Source/UnrealEnginePython/UnrealEnginePython.Build.cs file at this line: https://github.com/20tab/UnrealEnginePython/blob/master/Source/UnrealEnginePython/UnrealEnginePython.Build.cs#L10

Note: ensure you have a 64bit python installation

choose a project you want to install the plugin into, open the file explorer (you can do it from the epic launcher too) and:

  • create a Plugins/ directory (if it does not exist) in your project and copy the directory UnrealEnginePython into it
  • from the file explorer right click on the project main file and choose 'generate visual studio project files'
  • open visual studio, you should now see Plugins/UnrealEnginePython in your solution explorer
  • run the compilation from visual studio
  • once the compilation ends, double check the python libraries can be found by the plugin (they must be in the system PATH like previously described, or brutally copy them in the Binaries/Win64 directory of the just built plugin)
  • now you can re-run the unreal engine editor

If all goes well, you will see 'Python Console' in the "Window/Developer Tools" menu

If you want to package your project (it is required only if you need to have a python VM at runtime, read: your game logic is programmed in python) ensure the Content/Scripts/ue_site.py file is in your project (it can be empty). At the end of the build procedure ensure to copy all of your required python scripts in the final directory. Remember that unless you add an embedded python in your final build, the final users of your project will require python installed in his/her system.

If you want to package without python, just remember to change the UnrealEnginePython.uplugin to have this line: https://github.com/20tab/UnrealEnginePython/blob/master/UnrealEnginePython.uplugin#L20 set as "Editor" instead of "Runtime"

Binaries installation on MaxOSX

Check in the releases page (https://github.com/20tab/UnrealEnginePython/releases) if there is a binary version that matches your configuration (otherwise open an issue asking us for it [please specify the python version too]) and download it.

Binary releases for MacOSX expects an official python installation (the packages you get from python.org).

Create (if it does not already exist) a Plugins directory in your project root directory (at the same level of Content/ and the .uproject file) and unzip the plugin into it. If your project is named FooBar you will end with FooBar/Plugins/UnrealEnginePython.

Open your project and go to the Edit/Plugins menu. Go to the bottom and under "Project/Scripting Languages" enable UnrealEnginePython.

Restart your project and you should see the PythonConsole under the "Window/Developer Tools" menu

Binary releases are mainly useful for editor scripting, if you want to package your project for distribution and you need the python runtime, you need a source release (see below).

If instead, you want to package your project without python, just remember to change the UnrealEnginePython.uplugin to have this line: https://github.com/20tab/UnrealEnginePython/blob/master/UnrealEnginePython.uplugin#L20 set as "Editor" instead of "Runtime"

Installation from sources on MacOSX

  • install the latest official python distribution from python.org (the installation will end in the "/Library/Frameworks/Python.framework/Versions/X.Y" directory).
  • create a new unreal engine blank c++ project (NOT a blueprint one, otherwise XCode will not be initialized)
  • create a Plugins directory in the project directory
  • move to the Plugins directory and clone the plugin repository
git clone https://github.com/20tab/UnrealEnginePython
  • restart the editor and a popup should appear asking your for confirmation of the build of the plugin.
  • Once the plugin is built, go to the output log console and filter for 'Python'. You should see the Python VM banner.

The build procedure will try to automatically discover python installations. If you need custom paths, just edit here:

https://github.com/20tab/UnrealEnginePython/blob/master/Source/UnrealEnginePython/UnrealEnginePython.Build.cs#L10

Upgrading on MacOSX

To upgrade to the latest development version of UnrealEnginePython:

  • move to the Plugins directory in the project directory and use git pull
git pull
  • move to UnrealEnginePython/Binaries/Mac from the Plugin directory
  • remove the plugin libraries to warn UnrealEngine to recompile the plugin
rm *.dylib
  • restart the editor and a popup should appear asking your for confirmation of the build of the plugin.
  • Once the plugin is built, go to the output log console and filter for 'Python'. You should see the Python VM banner.

Installation from sources On Linux (64 bit)

Currently the suggested distribution is Ubuntu Xenial (LTS 16.04) 64bit. Obviously you need to already have an Unreal Engine build (note that on ubuntu xenial you need to install the clang-3.5 package to build the editor). Both python2.7 and python3.5 are supported and the default configuration assumes python3 (so ensure to install the python3-dev package).

  • Create a new C++ project and close the editor once the project is fully started
  • go to the just created project directory and create the Plugins folder
  • move to the Plugins folder and clone the plugin repository:
git clone https://github.com/20tab/UnrealEnginePython
  • re-open your project, this time you will get a popup asking you for re-building the python plugin. Choose yes and wait.

NOTE: always run your project from a terminal so you can see startup logs (they are really useful when building the plugin the first time, if you cannot build the plugin, open an issue on github pasting the related log lines).

If you want to use python2 (or another specific version) just edit the Source/UnrealEnginePython/UnrealEnginePython.Build.cs file and change the pythonHome string accordingly (ensure to have the python2.7-dev package installed).

Upgrade the plugin on Linux

Just remove the .so files in Plugins/UnrealEnginePython/Binaries/Linux and pull the latest code.

At the next run the build procedure wil be started again.

Android Deployment

Check https://github.com/20tab/UnrealEnginePython/blob/master/docs/Android.md

Installation on other platforms

Currently only Windows, MacOSX, Linux and Android are supported.

Using Python with Unreal Engine (finally)

If your objective is to script the editor, you can directly jump to

https://github.com/20tab/UnrealEnginePython/tree/master/docs

and

https://github.com/20tab/UnrealEnginePython/tree/master/examples

The first directory contains the official documentation for specific areas, while the second one is a collection of python scripts doing any sort of 'magic' with your project ;)

Creating a new blueprint class managed by python

We are going to create a new Actor based on python (instead of C++ or blueprints)

This is the "gentle" approach, using a 'proxy' python class to speak with the UE4 api. Once you get familiar with the system, you can go further and start working withe native subclassing api (https://github.com/20tab/UnrealEnginePython/blob/master/docs/Subclassing_API.md)

In the content browser click on 'add new' and choose 'blueprint class'

In the classes menu choose 'PyActor':

Alt text

You now have a new asset, give it a meaningful name, and double click on it to start configuring it in the blueprint editor

Alt text

On the right (in the 'Details' tab) you will find the Python section.

For now only 'Python Module' and 'Python Class' are meaningful.

Go to the Content directory of your project and create a directory named 'Scripts'. This is where all of your python modules will reside. With your favourite text editor create a new python module (like funnygameclasses.py), and define a new class into it:

import unreal_engine as ue

ue.log('Hello i am a Python module')

class Hero:

    # this is called on game start
    def begin_play(self):
        ue.log('Begin Play on Hero class')
        
    # this is called at every 'tick'    
    def tick(self, delta_time):
        # get current location
        location = self.uobject.get_actor_location()
        # increase Z honouring delta_time
        location.z += 100 * delta_time
        # set new location
        self.uobject.set_actor_location(location)

Now, go back to the blueprint editor and set 'funnygameclasses' in the 'Python Module' field, and 'Hero' in 'Python Class'

As you can see the actor will simply move over the z axis, but we need to give it some kind of visual representation to have a feedback in the scene. In the blueprint editor click on 'add component' and add some shape (a sphere, or a cube, or whatever you want). Save and Compile your blueprint.

Now you can drag the bluprint from the content browser to the scene and just click 'Play'.

You should see your actor moving along the 'z' axis at a speed of 1 meter per second

By default a 'begin_play' and a 'tick' method are expected (they will be automatically taken into account if found). In addition to them an 'automagic' system for defining event is available:

def on_actor_begin_overlap(self, me, other_actor):
    pass

def on_actor_end_overlap(self, me, other_actor):
    pass
    
def on_actor_hit(self, me, other_actor, normal_impulse, hit_result):
    pass

...

Basically for each method startwing with 'on_' the related delegate/event is automatically configured (if available).

If you instead prefer to manually setup events, the following functions are exposed:

class Ball:

    def begin_play(self):
        self.uobject.bind_event('OnActorBeginOverlap', self.manage_overlap)
        self.uobject.bind_action('Jump', ue.IE_PRESSED, self.uobject.jump)
        self.uobject.bind_key('K', ue.IE_PRESSED, self.you_pressed_K)
        self.uobject.bind_axis('MoveForward', self.move_forward)
        
    def manage_overlap(self, me, other):
        ue.print_string('overlapping ' + other.get_name())
        
    def you_pressed_K(self):
        ue.log_warning('you pressed K')
        
     def move_forward(self, amount):
        ue.print_string('axis value: ' + str(amount))
        

What is 'self.uobject' ?

To allow seamless Python integration, each UObject of the engine is automatically mapped to a special Python Object (ue_PyUObject).

Whenever you want to access a UObject from python, you effectively get a reference to a ue_PyUObject exposing (via its methods) the features of the UObject (properties, functions, ....)

This special python object is cached into a c++ map in memory. (The key is the UObject pointer, the value is the ue_PyUObject pointer)

To be more clear, a call to:

text_render_component = unreal_engine.find_class('TextRenderComponent')

will internally search for the 'TextRenderComponent' class (via unreal c++ reflection) and when found will check if it is available in the cache, otherwise it will create a new ue_PyUObject object that will be placed in the cache.

From the previous example the 'text_render_component' maintains a mapping to the UObject (well a UClass in this example).

Pay attention: the python class you map to the PyActor (or PyPawn, PyCharacter or PyComponent), is not a ue_PyUObject. It is a classic python class that holds a reference (via the 'uobject' field) to the related ue_PyUObject mapped object. The best technical term to describe those classes is 'proxy'.

Note about 'uobject' from now on

In the following lines, whenever you find a reference to 'uobject' it is meant as a ue_PyUObject object.

Adding a python component to an Actor

This works in the same way as the PyActor class, but it is, well, a component. You can attach it (search for the 'Python' component) to any actor.

Remember that for components, the self.uobject field point to the component itself, not the actor.

To access the actor you can use:

actor = self.uobject.get_owner()

The following example implements the third person official blueprint as a python component:

class Player:
    
    def begin_play(self):
        # get a reference to the owing pawn (a character)
        self.pawn = self.uobject.get_owner()

        # the following two values were originally implemented as blueprint variable
        self.base_turn_rate = 45.0
        self.base_look_up_rate = 45.0

        # bind axis events
        self.pawn.bind_axis('TurnRate', self.turn)
        self.pawn.bind_axis('LookUpRate', self.look_up)
        self.pawn.bind_axis('Turn', self.pawn.add_controller_yaw_input)
        self.pawn.bind_axis('LookUp', self.pawn.add_controller_pitch_input)

        self.pawn.bind_axis('MoveForward', self.move_forward)
        self.pawn.bind_axis('MoveRight', self.move_right)

        # bind actions
        self.pawn.bind_action('Jump', ue.IE_PRESSED, self.pawn.jump)
        self.pawn.bind_action('Jump', ue.IE_RELEASED, self.pawn.stop_jumping)

    def turn(self, axis_value):
        turn_rate = axis_value * self.base_turn_rate * self.uobject.get_world_delta_seconds()
        self.pawn.add_controller_yaw_input(turn_rate)

    def look_up(self, axis_value):
        look_up_rate = axis_value * self.base_look_up_rate * self.uobject.get_world_delta_seconds()
        self.pawn.add_controller_pitch_input(look_up_rate)

    def move_forward(self, axis_value):
        rot = self.pawn.get_control_rotation()
        fwd = ue.get_forward_vector(0, 0, rot[2])
        self.pawn.add_movement_input(fwd, axis_value)

    def move_right(self, axis_value):
        rot = self.pawn.get_control_rotation()
        right = ue.get_right_vector(0, 0, rot[2])
        self.pawn.add_movement_input(right, axis_value)

Native methods VS reflection

By default the UObject class defines getattr and setattr as wrappers for unreal properties and functions.

This means that calling:

self.uobject.bCanBeDamaged = True

it is the same as

self.uobject.set_property('bCanBeDamaged', True)

As well as function calls:

vec = self.uobject.GetActorRightForward()

means

vec = self.uobject.call_function('GetActorRightForward')

And more important (and handy) K2_ functions are automagically exposed too:

vec = self.uobject.GetActorLocation()

is equal to:

vec = self.uobject.call_function('K2_GetActorLocation')

Obviously you can combine methods/properties:

self.uobject.CharacterMovement.MaxWalkSpeed = 600.0

Albeit the system allows for full unreal api usage, reflection is slower than native methods.

Try to use native methods whenever possible, and open pull request whenever you think a function should be exposed as native methods.

So

vec = self.uobject.get_actor_location()

is way faster than

vec = self.uobject.GetActorLocation()

Reflection based functions are those in camelcase (or with the first capital letter). Native functions instead follow the python style, with lower case, underscore-as-separator function names.

Note that, in editor builds, when you change the property of an archetype (included ClassDefaultObject) via setattr all of the archtype instances will be updated too.

To be more clear:

your_blueprint.GeneratedClass.get_cdo().CharacterMovement.MaxWalkSpeed = 600.0

is a super shortcut for:

your_blueprint.GeneratedClass.get_cdo().CharacterMovement.pre_edit_change('MaxWalkSpeed')
your_blueprint.GeneratedClass.get_cdo().CharacterMovement.set_property('MaxWalkSpeed', 600.0)
your_blueprint.GeneratedClass.get_cdo().CharacterMovement.post_edit_change_property('MaxWalkSpeed')
for instance in your_blueprint.GeneratedClass.get_cdo().CharacterMovement.get_archetype_instances():
    instance.pre_edit_change('MaxWalkSpeed')
    instance.set_property('MaxWalkSpeed', 600.0)
    instance.post_edit_change_property('MaxWalkSpeed')

The automagic UClass, UStruct and UEnums mappers

Instead of doing a gazilion of unreal_engine.find_class(name) calls, the plugin adds three 'magic' modules called unreal_engine.classes, unreal_engine.structs and unreal_engine.enums. They allows to import unreal classes/structs/enums like python classes:

from unreal_engine.classes import ActorComponent, ForceFeedbackEffect, KismetSystemLibrary

...
components = self.uobject.get_owner().GetComponentsByClass(ActorComponent)

...
self.force_feedback = ue.load_object(ForceFeedbackEffect, '/Game/vibrate')
self.uobject.get_player_controller().ClientPlayForceFeedback(self.force_feedback)

...
name = KismetSystemLibrary.GetObjectName(self.actor)

the last example, shows another magic feature: static classes function calls. Obviously in this specific case using self.actor.get_name() would have been the best approach, but this feature allows you to access your blueprint function libraries too.

Another example for adding a widget:

from unreal_engine.classes import WidgetBlueprintLibrary

class PythonFunnyActor:
    def begin_play(self):
        WidgetBlueprintLibrary.Create(self.uobject, ue.find_class('velocity_C'))

And another complex example using enums, keyword arguments and output values (output values are appended after the return value):

import unreal_engine as ue
from unreal_engine import FVector, FRotator, FTransform, FHitResult
from unreal_engine.classes import ActorComponent, ForceFeedbackEffect, KismetSystemLibrary, WidgetBlueprintLibrary
from unreal_engine.enums import EInputEvent, ETraceTypeQuery, EDrawDebugTrace

...

is_hitting_something, hit_result = KismetSystemLibrary.LineTraceSingle_NEW(self.actor, self.actor.get_actor_location(), FVector(300, 300, 300), ETraceTypeQuery.TraceTypeQuery1, DrawDebugType=EDrawDebugTrace.ForOneFrame)
if is_hitting_something:
    ue.log(hit_result)

To create a new struct instance you can do:

from unreal_engine.structs import TerrificStruct

ts = TerrificStruct()

or (to initialize some of its fields)

from unreal_engine.structs import TerrificStruct

ts = TerrificStruct(Foo='Bar', Test=17.22)

To access the fields of a struct just call the fields() method.

A good example of struct usage is available here: https://github.com/20tab/UnrealEnginePython/blob/master/docs/Settings.md

More details here: https://github.com/20tab/UnrealEnginePython/blob/master/docs/MemoryManagement.md

The ue_site.py file

On Editor/Engine start, the ue_site module is tried for import. You should place initialization code there. If the module cannot be imported, you will get a (harmful) message in the logs.

PyPawn

This works like PyActor, but this time you generate a new Pawn class (that you can posses with a controller)

The 'World' concept

Every actor is mapped to a world (UWorld in c++). Generally when you play on a Level your objects all live in the same world, but at the same time there could be multiple worlds (for example while testing in the editor there is a world for the editor and one for the simulation)

While it is pretty rare to reference other worlds, you may need to compare the world of two uobject's (for example you may have a reference in your python module to a uobject of a hidden world and you want to check if you need to use it).

The uobject.get_world() function returns a uobject representing the world (the C++ UWorld class)

The uobject api

Each uobject represent a UObject class of the Engine. This C++ class is basically the root of all the other classes (Actors, Pawns, components, properties ...). Thanks to Unreal Engine reflection system we do not need to implement a python class for each unreal engine class, but for performance reason we expose the most common methods. The uobject system checks for the type of the mapped C++ UObject and will call the method only if it is safe to call it.

Sometime methods are implemented for automatically getting the right object. As an example get_actor_location() when called over a component will automatically retrieve the related actor and will call C++ AActor::GetActorLocation() method over it.

When this automagic approach is too risky, the method will check for the uobject type and will raise an exception in the case of inconsistencies.

Remember, there is no need to implement every single engine class method, the reflection system is powerful enough to be governed only via properties and function calls (check the uobject call() method)

Most-used methods are implemented directly as uobject methods for performance reasons.

You can get the the list of uobject api methods here: https://github.com/20tab/UnrealEnginePython/blob/master/docs/uobject_API.md

Automatic module reloading (Editor only)

When in the editor, you can change the code of your modules mapped to proxies without restarting the project. The editor will reload the module every time a PyActor, PyPawn or PythonComponent is instantiated. This is obviously not the best approach. In the future we would like to implement timestamp monitoring on the file to reload only when needed.

Primitives and Math functions

The plugin exposes FVector, FRotator, FQuat, FColor, FHitResult and a bunch of the internal handles.

Where meaningful, math operations are exposed:

import unreal_engine

class ActorGoingUp:
    def begin_play(self):
        # 1 meter by second
        self.speed = 100
    
    def tick(self, delta_time):
        # get the up vector
        up = self.uobject.get_up_vector()
        # get current position
        position = self.uobject.get_actor_location()
        # build a direction vector based on speed
        up_amount = up * self.speed * delta_time)
        # sum the direction to the position
        position += up_amount
        # set the new position
        self.uobject.set_actor_location(new_position)

Referencing objects

You can use find_class(), find_struct() and find_object() functions to reference already loaded classes/objects.

If you need to reference assets (still) not loaded in the engine you can use load_struct(), load_class() or load_object():

a_struct_data = ue.load_struct('/Game/Data')
ue.log(a_struct_data.as_dict())

or to find a specific asset:

texture_class = ue.find_class('Texture2D')
a_specific_texture = ue.load_object(texture_class, '/Game/Textures/logo2')

More infos about dealing with assets are available here: https://github.com/20tab/UnrealEnginePython/blob/master/docs/ManagingAssets.md

The as_dict() method

This special method can be called on any uobject: it will attempt to serialize it to a python dictionary

Blueprints integration

You can call blueprints functions (or custom events) via the .call() and .call_function() methods:

your_funny_blueprint_object.call('AFunctionOrACustomEvent with_a_arg')

Whenever you need to reference external object, avoid using find_object() and similar. Instead add a public variable in your blueprint pointing to the specific object. You can then reference this object easily getting the property value:

the_other_object = self.uobject.get_property('target')
the_other_object.set_actor_location(0, 0, 0)

.call_function() is more advanced, as it allows for return values and python args:

# an example of moving an object z with curves:
class Curver:
    def begin_play(self):
        self.curve = self.uobject.get_owner().get_property('curve')
        self.accumulator = 0.0
    def tick(self, delta_time):
        location = self.uobject.get_actor_location()
        z = self.curve.call_function('GetFloatValue', self.accumulator) * 100
        self.uobject.set_actor_location(location.x, location.y, z)
        self.accumulator += delta_time

Events

You can easily bind events (as seen before) with the bind_event function

self.uobject.bind_event('OnActorBeginOverlap', a_funny_callback)

You can obviously bind to Event Dispatchers too.

Triggering events is basically like calling functions, self.uobject.call('OnActorBeginOverlap') will be more than enough.

If you want to map events from a blueprint to a python function, the best thing to do is using the 'python call' blueprint functions exposed by the various plugin classes:

Alt text

Plugin Configuration

You can tune your python environment adding a [Python] stanza to the Config/DefaultEngine.ini file.

The following parameters are supported:

  • Home: set the path of the python installation, useful for forcing the python vm to search modules in a specific directory (like old-style virtualenvs)
  • RelativeHome: like Home but relative to the /Content directory
  • ProgramName: set the python program name path
  • RelativeProgramName: like ProgramName, but the path is relative to the /Content directory
  • ScriptsPath: change the default path on where Unreal Engine searches for python scripts
  • RelativeScriptsPath: like ScriptsPath, but relative to the /Content directory
  • AdditionalModulesPath: add the specified directory to sys.path
  • RelativeAdditionalModulesPath: like AdditionalModulesPath, but the path is relative to the /Content directory
  • ZipPath: allow to specify a .zip file that is added to sys.path
  • RelativeZipPath: like ZipPath, but the path is relative to the /Content directory
  • `ImportModules: comma/space/semicolon separated list of modules to import on startup (after ue_site)

Example:

[Python]
Home = C:/FooBar/Python36

Packaging

When you package your projects, remember to include the libpython (dll or dylib or .so based on your operating system) in the binaries folder and the Scripts directory (if you do not want to force the user to have python installed in its system). For Windows system you can use the embedded distributions available in the official python.org site. Just uncompress the zip in the plugin binary folder (at the same level of UnrealEnginePython.dll)

If you do not want to distribute python sources, you can include only the __pycache__ directory with the bytecode.

Do not forget to include python third party modules (if you use any of them in your project)

Quick Examples

This is a PyActor destroying itself whenever another actor overlap it. Remember to add a mesh component to it (like a sphere) and set its collision behaviour as 'OverlapAll'. This could be tested with the third person official template.

class Ball:
    def begin_play(self):
        ue.print_string('Hello')

    def on_actor_begin_overlap(self, other_actor):
        ue.print_string('Collided with ' + other_actor.get_name())
        self.uobject.actor_destroy()

Now we create (at runtime !!!) a whole new PyActor:

class SuperHero:
    def begin_play(self):
        # spawn a new PyActor
        new_actor = self.uobject.actor_spawn(ue.find_class('PyActor'), Fvector(0, 0, 0),FRotator(0, 0, 90))
        # add a sphere component as the root one
        static_mesh = new_actor.add_actor_root_component(ue.find_class('StaticMeshComponent'), 'SphereMesh')
        # set the mesh as the Sphere asset
        static_mesh.call('SetStaticMesh /Engine/EngineMeshes/Sphere.Sphere')
        # set the python module
        new_actor.set_property('PythonModule', 'gameclasses')
        # set the python class
        new_actor.set_property('PythonClass', 'Vertical')

For more examples: https://github.com/20tab/UnrealEnginePython/tree/master/examples

Spawning Notes

Remember that only Actors can be spawned in a world, and that even the editor is a valid world:

import unreal_engine as ue
from unreal_engine.classes import Actor, Character
from unreal_engine import FVector, FRotator

world = ue.get_editor_world()
actor000 = world.actor_spawn(Actor, FVector(0, 0, 0), FRotator(0, 0, 0))
character000 = world.actor_spawn(Character, FVector(100, 100, 100), FRotator(0, 0, 0))

Remember that the Blueprint asset is not a valid actor by itself, you need to get the class generated by the blueprint:

import unreal_engine as ue
from unreal_engine.classes import Blueprint
from unreal_engine import FVector, FRotator

world = ue.get_editor_world()

blueprint = ue.load_object(Blueprint, '/Game/TestBall.TestBall')
actor000 = world.actor_spawn(blueprint.GeneratedClass, FVector(0, 0, 0), FRotator(0, 0, 0))

otherwise you can directly reference the BlueprintGeneratedClass

import unreal_engine as ue
from unreal_engine.classes import BlueprintGeneratedClass
from unreal_engine import FVector, FRotator

world = ue.get_editor_world()

blueprint_actor = ue.load_object(BlueprintGeneratedClass, '/Game/TestBall.TestBall_C')
actor000 = world.actor_spawn(blueprint_actor, FVector(0, 0, 0), FRotator(0, 0, 0))

The Python Editor

Starting from version 20170301 a handy editor has been added to the plugin:

Alt text

It allows you to run, create, modify and delete scripts directly from the UE editor

The first pull request for the editor has been issued by https://github.com/sun5471 so many thanks to him ;)

Integration with Qt4/Qt5/PySide2

Thanks to solid GIL management, you can integrate Qt python apps in Unreal Engine 4.

Pay attention to not call app.exec_() as it will result in Qt taking control of the UE loop. Instead use a ticker to integrate the Qt loop in the editor loop:

# save it as ueqt.py
import sys
import unreal_engine as ue
import PySide2
from PySide2 import QtWidgets

app = QtWidgets.QApplication(sys.argv)

def ticker_loop(delta_time):
    app.processEvents()
    return True

ticker = ue.add_ticker(ticker_loop)

now you can start writing your gui (this is a simple example loading asset thumbnail):

import ueqt
from PySide2 import QtCore, QtWidgets, QtGui
import unreal_engine as ue

from unreal_engine import FARFilter

_filter = FARFilter()
_filter.class_names = ['SkeletalMesh', 'Material']

class MyWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.vertical = QtWidgets.QVBoxLayout()
        self.scroll = QtWidgets.QScrollArea()
        self.content = QtWidgets.QWidget()
        self.scroll.setWidget(self.content)
        self.scroll.setWidgetResizable(True)
        self.layout = QtWidgets.QVBoxLayout()
	
        for asset_data in ue.get_assets_by_filter(_filter, True):
            try:
                thumbnail = asset_data.get_thumbnail()
            except:
                continue

            label = QtWidgets.QLabel()
            data = thumbnail.get_uncompressed_image_data()
            image = QtGui.QImage(data, 256, 256, QtGui.QImage.Format_RGB32)
            label.setPixmap(QtGui.QPixmap.fromImage(image).scaled(256, 256))
            self.layout.addWidget(label)

        self.content.setLayout(self.layout)
        self.vertical.addWidget(self.scroll)
        self.setLayout(self.vertical)



widget = MyWidget()
widget.resize(800, 600)
widget.show()

root_window = ue.get_editor_window()
root_window.set_as_owner(widget.winId())

(no need to allocate a new Qt app, or start it, as the UE4 Editor, thanks to to ueqt module is now the Qt app itself)

Note the 2 final lines: they 'attach' the Qt window as a 'child' of the editor root window. Note that on windows platform this is not simple parenting but 'ownership'.

Memory management

Dealing with 2 different GC's is really challenging.

Starting from release 20180226 a new memory management system has been added (FUnrealEnginePythonHouseKeeper, available here https://github.com/20tab/UnrealEnginePython/blob/master/Source/UnrealEnginePython/Public/PythonHouseKeeper.h). This new system is completely integrated with the Unreal Engine reflection-based GC and will hold track of each ue_PyUObject abd the related UObject to understand when a python object can be safely destroyed.

The same system works for delegates, as well as Slate.

More details here: https://github.com/20tab/UnrealEnginePython/blob/master/docs/MemoryManagement.md

Unit Testing

The repository includes the tests/ directory from which unit tests will be run.

To run the unit tests (ensure to run them on an empty/useless project to avoid messing with assets) run the following commands from the ue4 python console:

import unreal_engine as ue
ue.py_exec(ue.find_plugin('UnrealEnginePython').get_base_dir() + '/run_tests.py')

if you plan to add new features to the plugin, including a test suite in your pull request will be really appreciated ;)

Threading

Since release 20180624 threading is fully supported.

As with native threads, do not modify (included deletion) UObjects from non-main threads.

Accessing Python Proxy From UObject

Sometimes you may have a UObject and know that it is backed by a python object. To get the python object from the UObject, use the get_py_proxy method. For example, imagine you have the following situation:

  1. There is a PyActor sub-class called PyExplosiveActor which has Explosive as its python class.
  2. The Explosive has a go_boom python method.
  3. There is a PyActor sub-class called PyBadGuyActor which has a Blueprint property called MyBomb and a python class called BadGuy.
  4. The BadGuy instance in python knows that its UObject has its MyBomb as an instance of PyExplosiveActor and wants to call the go_boom python method.

This would be resolved as shown below:

import unreal_engine as ue

class Explosive:
    'Python representation for PyExplosiveActor in UE4'

    def go_boom(self):
        # do python stuff to explode
        ...
        self.uobject.destory()

class BadGuy:
    'Python reprsentation for PyBadGuyActor in UE4'
   
    def ignite_bomb(self, delay):
        bomb = self.uobject.MyBomb
        py_bomb = bomb.get_py_proxy()
        py_bomb.go_boom()
	

What is going on here in BadGuy is that self.uobject is a reference to the PyActor UObject and self.uobject.MyBomb is a reference to the PyExplosive uobject. But instead you want to access its proxy class (Explosive). The get_py_proxy() method returns the python custom class, Explosive that the PyExplosiveActor object is mapped to.

Status and Known issues

Exposing the full ue4 api is a huge amount of work, feel free to make pull requests for your specific needs.

We still do not have a plugin icon ;)

We try to do our best to "protect" the user, but you can effectively crash UE from python as you are effectively calling the C/C++ api

Contacts and Commercial Support

If you need commercial support for UnrealEnginePython just drop a mail to info at 20tab.com

Follow @unbit on twitter for news about the project

Special Thanks

Such a big project requires constant sponsorship, special thanks go to:

unrealenginepython's People

Contributors

dfb avatar edowson avatar efeng-weta avatar heylenz avatar hippid avatar hueypark avatar hughmacdonald avatar jay2645 avatar jiloc avatar kuafu avatar mmmaat avatar naveent1010 avatar oliverzx avatar osstony avatar pepin- avatar pio-neil avatar prokopst avatar rdeioris avatar rdsgautier avatar sabhiram avatar samhocevar avatar schizo avatar sinokgr avatar slartibaartfast avatar speedpacer avatar stevenshan avatar sun5471 avatar taotang1984 avatar unbit avatar yakhira 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  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

unrealenginepython's Issues

Take my money, please?

You guys are completely awesome. My dream since ue4 was released was to have Python in the mix. Python is like, the perfect match for ue4 and the blueprint system. SO many possibilities here. I tried, tried to drop in cpython, SWIG, and failed badly. Crashes and errors galore.

My plan was to use Kivy ports to get things to work on mobile as well.

How can I help? What kind of hacking needed? Oh, feel free to close this issue once you guys all admit you're the coolest thing that's happened to ue4. This is testament to the best part of open source.

Deadlock with SetPythonAttr from C++ Callback

Hi,
I am experiencing a deadlock when I call SetPythonAttrObject from within a C++ function invoked from Python. Is this something that should work currently? I have threading enabled, but everything UE-related is on the main thread. Other thread is running an async event loop that wouldn't be blocking.

Compile error; should I clone specific stable tag?

First of all, thanks for this awesome project. I'm very excited to play with it. I am getting a compile error when trying to build (relevant Visual Studio error shown below).

I notice that this is very actively developed. Is there a particular stable version I should be using?

I tried commit 3646583 and got the error below.

Thanks again,
-Emin

C:\Users\Emin\Documents\Unreal Projects\GPMProto\Plugins\UnrealEnginePython\Source\UnrealEnginePython\Public\PyCommandlet.cpp(31): error C2440: 'initializing': cannot convert from 'initializer list' to 'TArray<FString,FDefaultAllocator>'
2> C:\Users\Emin\Documents\Unreal Projects\GPMProto\Plugins\UnrealEnginePython\Source\UnrealEnginePython\Public\PyCommandlet.cpp(31): note: No constructor could take the source type, or constructor overload resolution was ambiguous
2>ERROR : UBT error : Failed to produce item: C:\Users\Emin\Documents\Unreal Projects\GPMProto\Plugins\UnrealEnginePython\Binaries\Win64\UE4Editor-UnrealEnginePython.dll
2> Total build time: 42.19 seconds
2>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.MakeFile.Targets(37,5): error MSB3075: The command ""C:\Program Files\Epic Games\4.12\Engine\Build\BatchFiles\Build.bat" GPMProtoEditor Win64 Development "C:\Users\Emin\Documents\Unreal Projects\GPMProto\GPMProto.uproject" -waitmutex" exited with code 5. Please verify that you have sufficient rights to run this command.
========== Build: 1 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Introduce native support for FVector and FRotator

Now that we have a solid base to work on, we can stop using single tuple for native types and introducing
wrapper for FVector and FRotator. This will remove the need for math features in the unreal_engine api

Python classes extending from Engine classes

One of the major features of Unreal.js that is handy is the ability to create subclasses of Engine classes in js (they are converted to JavascriptDelegateClass and treated similar to Blueprints). The same functionality would be nice in UE4.py as well.

Assumptions for below example:

  • unreal_engine.classes reference to internal C++ classes available to Blueprint
  • MyBasePlayer inherit all the "functionality" of the Character with only additions/overrides as specified
  • BaseGameMode blueprint having Python component with module = my_base_gamemode, class = MyBaseGameMode

See code example.

Content/Scripts/my_base_player.py

from unreal_engine.classes import Character

class MyBasePlayer(Character):
    def __init__(self):
        super().__init__()
        self.CharacterMovement.MaxWalkSpeed = 1200

    def is_grounded(self):
        return self.CharacterMovement.IsMovingOnGround()

Content/Scripts/my_base_gamemode.py

import unreal_engine as ue
from my_base_player import MyBasePlayer

class MyBaseGameMode:
    def __init__(self):
        if self.uobject.get_world().IsServer():
            owner = self.uobject.get_owner()
            owner.DefaultPawnClass = MyBasePlayer()

Here is a link to the Unreal.js method of subclassing. Theirs even works with Blueprints, which would be a nice addition at some point as well.

UEPY_THREADING Change causing Unreal 4.1.2 to close before the editor launches.

The experimental UEPY_THREADING changes are causing Unreal 4.1.2 to not fully launch for me. Backing out of this commit resolves the problem. I'm not sure if this is also an issue with 4.1.3.

On the topic of threading, is it possible to run the "import_asset" and "asset_reimport" commands from a separate python thread? My guess would be it's not thread safe, but maybe there is way to have it execute on the main engine thread? Forgive my lack of knowledge on this, could see it being a complicated matter.

Asking because I'm currently launching an rpc-server on a separate python thread in the hopes of sending commands to the Editor from an outside python console. The server has a while loop to catch incoming connections and commands, which means I have to run it on a background thread in order to not pause the editor.

List / Delete / Move / Rename assets in Content Browser

Hey guys,

how could I delete, move or rename an exisiting asset in the content browser?
Also, is there a way to check the existence of a folder (apart from checking on file system) and then list all assets within that folder?

I tried to figure this out by digging around in the existing funcionality but had no luck.

Set Unreal as QtWidget.Parent()

Hi guys,

Can you please expose UnrealEditors's Window handle so we can set it as parent to the QtWidgets?
Similar to 3dsMax's MaxPlus.GetQMaxWindow().

Thanks,
Nick

Add UAssetImportData Support

Currently we are able to get this UObject via reflection but are unable to access any of it's methods.

Should a new class be created that inherits from UObject and adds the missing functions for this class? Is there a mechanism for looking up and returning python wrappers for these classes when reflection is invoked?

Python 3.5 32/64 bit

Hi,
i am getting a build error concerning the python version.
Is it supposed to be 32 or 64 bit?

Regards,
Lars

Missing consts for Mac build

Don't seem worth a pull request:

../../Source/UnrealEnginePython/Private/UEPyFColor.cpp

-static void fcolor_add_color(char *color_name, FColor fcolor) {
+static void fcolor_add_color(const char *color_name, FColor fcolor) {

../../Source/UnrealEnginePython/Private/UEPyFLinearColor.cpp

-static void flinearcolor_add_color(char *color_name, FLinearColor lcolor) {
+static void flinearcolor_add_color(const char *color_name, FLinearColor lcolor)

PyQt5 no events delivered on Mac OS?

Example from readme is OK on Windows, but on Mac spinning wheel and no mouse over events.

How are events getting delivered in the Windows release and how does Mac differ?

Easy for me to work around by moving to Windows for now. Thank you.

Saving an asset

Hi,
I changed the material on a StaticMesh using "my_asset.Materials = [...]". I discovered that the material changes are lost on restart of the editor if I don't open the static mesh and save it manually.

How can I save it by script? I looked into "save_package". but didn't really get ho to work it in order to save in place:
https://docs.unrealengine.com/latest/INT/API/Runtime/CoreUObject/UObject/UPackage/SavePackage/index.html

I "simply" want to trigger the same behaviour as if I was pressing the save button in the editor.

Access Functions

While I'm trying to get familiar with developing in Python for Unreal, I realised that I didn't know how to access funtions. Currently we have access to properties (.get_property, .set_property, .properties) and they work fine but how about functions? I saw that in the UEPyModule.cpp there are a few related functions (.find_function and .call_function") but I can't make them work. I assume that I'm doint something wrong.

That's a simple example of how I was trying access Actor's GetLevel() function:
image

Scripts\test.py

def fun():
    selected_actors = ue.editor_get_selected_actors()
    for actor in selected_actors:
        fn = actor.find_function("GetLevel")
        ue.log(str(fn))

This prints "None". What am I doing wrong?

Best way to call python methods on a PyComponent from a C++ Actor

Hi,

I hope this is a good place to ask questions.

I am experimenting with your project (which is great btw) and I am trying a basic interaction between a C++ Actor and a PyComponent contained in the actor.

What I need is basically call a python function from C++ actor passing parameters from C++ and receving a result from python (all synchronous).

So, i have tried to create the PyComponent object in the C++ Actor and add it to the RootComponent but I am running in a number of issues with includes. The code looks like:

#include "UnrealEnginePython.h"
#include "PythonComponent.h"

[....]

myPyComponent = CreateDefaultSubobject<UPythonComponent>(TEXT("MyPyComponent"));

Now, when I include the "PythonComponent.h" file, I get errors, probably related to include of Python headers:

error C2143: syntax error: missing ';' before '*'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2238: unexpected token(s) preceding ';'

on this line in PyComponent.h:
PyObject *py_component_instance;

Am i missing something? Am I not supposed to include "PythonComponent.h" in my game? Maybe I am just going down a rabbit hole and there is just a different way to do what I need?

Thanks a lot!
Mike

Mobile Devices

We intend to use the plugin within a project, where we need to deliver the application for several plattforms - including Desktop, VR and Mobile (iOS and Android).

How would the plugin work on a mobile device? I am not familiar with running python on mobile devices, which might already answer the question.

Accessing Static Mesh BuildSettings causes crash

Hi,

I tried this and it caused unreal to crash when I attempt to open the Static Mesh asset from the Content Browser
(It acutally already crashes when I open the Folder "ImportTest" in the Content Browser):

import unreal_engine as ue
from unreal_engine.classes import StaticMesh
sm = ue.load_object(StaticMesh, "/Game/ImportTest/my_static_mesh")
source_model = sm.SourceModels[0]
source_model.BuildSettings.bUseFullPrecisionUVs = True

I am aware that when you do this within the UI you need to press the "ApplyChanges" button.
Any way to get this working?

Failing to Instance Factory

Following the "Asset Importing" example in the Python Console and encountering an error.

import unreal_engine as ue

factory = ue.find_class('TextureFactory')

factory_obj = ue.new_object(factory)

If run from an external script I get the following error:
"argument is not a UObject"
Running directly in the console results in a crash.

Thanks again for adding the import function! Just wanted to report the bug.

All unit tests fail on macOS

On Sierra, recent changes have gotten the plugin to successfully compile (using Python 3.5.2, UE 4.13, threading support disabled).

But running the unit tests cause the editor to crash:

If I comment out
self.uobject.quit_game()
from tests.py

Then I get the following output:

PlayLevel: No blueprints needed recompiling
New page: SIE session: MainLevel (Oct 23, 2016, 11:05:51 PM)
Creating play world package: /Game/UEDPIE_0_MainLevel
PIE: StaticDuplicateObject took: (0.002017s)
Creating AISystem for world MainLevel
Got a bulk data texture, with 1 mips
PIE: World Init took: (0.000700s)
Got a bulk data texture, with 1 mips
PIE: Created PIE world by copying editor world from /Game/MainLevel.MainLevel to /Game/UEDPIE_0_MainLevel.MainLevel (0.003290s)
Got a bulk data texture, with 1 mips
FAudioDevice initialized.
Game class is 'GameMode'
Bringing World /Game/UEDPIE_0_MainLevel.MainLevel up for play (max tick rate 0) at 2016.10.24-03.05.51
Bringing up level for play took: 0.001412
Native class hierarchy updated for 'MovieSceneCapture' in 0.0018 seconds. Added 11 classes and 0 folders.
Match State Changed from EnteringMap to WaitingToStart
F
F
.
F
======================================================================
FAIL: test_create_player (tests.TestPlayer)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "../../../../../../Pepin/Dropbox/ETC/Fall 2016/Cozplay/Final Unity Setup/Unreal mk2/Test2/Content/Scripts/tests.py", line 45, in test_create_player
    self.assertEqual(self.actor.get_num_players(), 1)
AssertionError: 0 != 1
======================================================================
FAIL: test_location (tests.TestTransform)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "../../../../../../Pepin/Dropbox/ETC/Fall 2016/Cozplay/Final Unity Setup/Unreal mk2/Test2/Content/Scripts/tests.py", line 26, in test_location
    self.assertEqual(location, (1, 1, 1))
AssertionError: <unreal_engine.FVector object at 0x179c65790> != (1, 1, 1)
======================================================================
FAIL: test_scale (tests.TestTransform)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "../../../../../../Pepin/Dropbox/ETC/Fall 2016/Cozplay/Final Unity Setup/Unreal mk2/Test2/Content/Scripts/tests.py", line 38, in test_scale
    self.assertEqual(scale, (3, 5, 7))
AssertionError: <unreal_engine.FVector object at 0x179c65790> != (3, 5, 7)
----------------------------------------------------------------------
Ran 4 tests in 0.001s
FAILED
 (failures=3)
Match State Changed from EnteringMap to WaitingToStart
Info Play in editor start time for /Game/UEDPIE_0_MainLevel 0.499

Any ideas what could be going on?

Import Meta Data

Hi guys,

I'm trying to export/import some data from 3dsMax file. I decided to save a .meta file for every FBX file we save (one FBX per geometry in our case).

I got it working for the selected Actors using the ue.editor_get_selected_actors() but I can't find a way to get all the level Actors (e.g. something like ue.editor_get_all_actors()).
To be honest, I'm struggling to find a connection between the Assets and the Actors. I used for example the ue.get_assets_by_class('StaticMesh') to collect all the static meshes, I filtered the ones I wanted but then I couldn't find the Actors in the level.

Also, is there anyway to expose the "content" path? I want to scan the dir for my meta files (I assume what I'm looking for is the FPaths::GameContentDir()).

Last thing, is there any way to create callbacks? I might want to set a post_import callback to automatically load the meta files.

Thanks,
Nick

Automatically Override Events in subclassing mode

When subclassing, every python callable is mapped to a UE4 function (eventually overridden if it matches a base function). The system should take in account multicast delegates so we can fastly do:

class Hero(Character):

    def OnActorBeginOverlap(self, .....):
        ...

without registering the event in the init

Spawning actors out of begin_play

Hi,

I'm having an issue when spawning new actors. The code works fine when inside the function begin_play, but when called from an other function it just crashes UE without explanation.

I'm new to UE so maybe I haven't completely understood how it should work...

Here is the code I use :

new_actor = self.ue_object.actor_spawn(ue.find_class('PyActor'), FVector(0, 0, 0), FRotator(0, 0, 90))

Thank you

Add asset to blueprint actor

Hi,

I manually created a blueprint actor called "MyActor".
How do I add an imported asset as component to that actor?

I think I might be on the totally wrong track here:

>>> from unreal_engine.classes import StaticMeshComponent
>>> my_asset = ue.find_oject("/Game/Imports/my_asset")
>>> my_blueprint = ue.find_object("Game/BP/MyActor")
>>> my_blueprint.add_actor_component(StaticMeshComponent, my_asset.get_full_name())
uobject is not an AActor
Traceback (most recent call last):
  File "<string>", line 1, in <module>
Exception: uobject is not an AActor

How much of the editor interface could be exposed

I'm interested in building up levels using Python scripts, not so much using Python in run mode.

Have tried reading the UE source base to find the editor classes. How much could be exposed to Python? Import to Content Browser with options set, import to World Outliner, again with options, etc.?

API docs and auto complete

I love the have auto completion working in Visual Studio Code with UnrealEnginePython.
Is there anyway to do that?

If not, is there a way to have some APIs doc to reference to?

Where is PyComponent in Blueprints?

Hi! Is it possible to create a PythonComponent using blueprints? I only see pyActor pyPawn and pyCharacter in the list of available blueprints.

Option to add Editor Buttons/Menus

Hi again,

I know that this is already in the list, I just wanted to create this "issue" in order to track the process.
The idea is that I would love if I could have the ability to create menus/buttons in the editor instead of having to execute python commands to start a tool.

Thanks,
Nick

Get Python instance from PyActor

Can I get Python instance from PyActor?

like this:

class MyPyActor:
    def on_actor_begin_overlap(self, me, other_actor):
        python_instance = other_actor.get_py_instance()
        # do something with python_instance

Ticker Functions Only Fired Once

Currently the way add_ticker is implemented causes all ticker events to be treated as one shots and not execute repeatedly. The function added to the delegate is expected to return either true or false. If false then the function will not be called again. Is it possible to address this issue with the way add_ticker is currently implemented?

Adding Python Packages in Linux

I was able to get this up and running thanks to your latest commit and with the "funnygameclasses.py" used in the readme. The example of moving the sphere at every tick worked fine. However, I'm wondering what the process is for adding other python packages such as numpy in Linux. Here's the error I'm getting from the log:

[2016.10.03-01.13.50:776][717]LogPython:Error: /home/daeil/.local/lib/python2.7/site-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct
[2016.10.03-01.13.50:777][717]LogPython:Error: Traceback (most recent call last):

[2016.10.03-01.13.50:777][717]LogPython:Error: File "../../../../../Projects/Unreal/DeepCars/Content/Scripts/funnygameclasses.py", line 3, in
import numpy as np

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/init.py", line 180, in
from . import add_newdocs

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/add_newdocs.py", line 13, in
from numpy.lib import add_newdoc

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/lib/init.py", line 8, in
from .type_check import *

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/lib/type_check.py", line 11, in
import numpy.core.numeric as _nx

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/core/init.py", line 14, in
from . import multiarray

[2016.10.03-01.13.50:777][717]LogPython:Error: ImportError: /home/daeil/.local/lib/python2.7/site-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct

[2016.10.03-01.13.50:812][717]LogPython:Error: /home/daeil/.local/lib/python2.7/site-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct
[2016.10.03-01.13.50:812][717]LogPython:Error: Traceback (most recent call last):

[2016.10.03-01.13.50:812][717]LogPython:Error: File "../../../../../Projects/Unreal/DeepCars/Content/Scripts/funnygameclasses.py", line 3, in
import numpy as np

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/init.py", line 180, in
from . import add_newdocs

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/add_newdocs.py", line 13, in
from numpy.lib import add_newdoc

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/lib/init.py", line 8, in
from .type_check import *

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/lib/type_check.py", line 11, in
import numpy.core.numeric as _nx

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/core/init.py", line 14, in
from . import multiarray

[2016.10.03-01.13.50:812][717]LogPython:Error: ImportError: /home/daeil/.local/lib/python2.7/site-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct

Use for 4.13

Hi guys,

any issues to be expected building the plugin with 4.13?

Is this limited to scripting game logic at the moment?

Excited by the prospect of using Python to automate actions in the editor like moving files around, assigning materials, importing meshes, querying asset data, and communicating with external python tools. I'm wondering if any of this is possible with the current state of this plug-in. Using python in conjunction with blueprints sounds like a great augmentation, but the most potential I see here is making up for Unreal4's lack of a more general scripting interface.

Really awesome work btw! I'll be watching this.

Compiler error with Python 2.7

Python 2.7 has non-const char * parameters for method and format. This can be worked around with a const_cast:

diff --git a/Source/UnrealEnginePython/Private/UEPyModule.cpp b/Source/UnrealEnginePython/Private/UEPyModule.cpp
index 1ddde64..73e35d6 100644
--- a/Source/UnrealEnginePython/Private/UEPyModule.cpp
+++ b/Source/UnrealEnginePython/Private/UEPyModule.cpp
@@ -1589,7 +1589,7 @@ UFunction *unreal_engine_add_function(UClass *u_class, char *name, PyObject *py_
        if (!inspect) {
                return NULL;
        }
-       PyObject *signature = PyObject_CallMethod(inspect, "signature", "O", py_callable);
+       PyObject *signature = PyObject_CallMethod(inspect, const_cast<char*>("signature"), const_cast<char*>("O"), py_callable);
        if (!signature) {
                return NULL;
        }

using python packages such as numpy in linux

I was able to get this up and running thanks to your latest commit and with the "funnygameclasses.py" used in the readme. The example of moving the sphere at every tick worked fine. However, I'm wondering what the process is for adding other python packages such as numpy in Linux. Here's the error I'm getting from the log:

[2016.10.03-01.13.50:776][717]LogPython:Error: /home/daeil/.local/lib/python2.7/site-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct
[2016.10.03-01.13.50:777][717]LogPython:Error: Traceback (most recent call last):

[2016.10.03-01.13.50:777][717]LogPython:Error: File "../../../../../Projects/Unreal/DeepCars/Content/Scripts/funnygameclasses.py", line 3, in
import numpy as np

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/init.py", line 180, in
from . import add_newdocs

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/add_newdocs.py", line 13, in
from numpy.lib import add_newdoc

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/lib/init.py", line 8, in
from .type_check import *

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/lib/type_check.py", line 11, in
import numpy.core.numeric as _nx

[2016.10.03-01.13.50:777][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/core/init.py", line 14, in
from . import multiarray

[2016.10.03-01.13.50:777][717]LogPython:Error: ImportError: /home/daeil/.local/lib/python2.7/site-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct

[2016.10.03-01.13.50:812][717]LogPython:Error: /home/daeil/.local/lib/python2.7/site-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct
[2016.10.03-01.13.50:812][717]LogPython:Error: Traceback (most recent call last):

[2016.10.03-01.13.50:812][717]LogPython:Error: File "../../../../../Projects/Unreal/DeepCars/Content/Scripts/funnygameclasses.py", line 3, in
import numpy as np

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/init.py", line 180, in
from . import add_newdocs

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/add_newdocs.py", line 13, in
from numpy.lib import add_newdoc

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/lib/init.py", line 8, in
from .type_check import *

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/lib/type_check.py", line 11, in
import numpy.core.numeric as _nx

[2016.10.03-01.13.50:812][717]LogPython:Error: File "/home/daeil/.local/lib/python2.7/site-packages/numpy/core/init.py", line 14, in
from . import multiarray

[2016.10.03-01.13.50:812][717]LogPython:Error: ImportError: /home/daeil/.local/lib/python2.7/site-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct

Cant' set list property - Materials

Hi,

I am tryint to change the materials on an imported asset in the content browser, which is a Static Mesh by the uniqe name "test":

I get a reference to the static mesh and also the material, that I want to assign.
Both "find_object" operations work fine and I am able to retrieve the current materials by calling
get_property("Materials"). But setting the property with a new list won't work - example code:

import unreal_engine as ue
my_asset = ue.find_object("test")
new_material = ue.find_object("test_material")
my_asset.set_property("Materials", [new_material])

Exception: unable to set property Materials

Is there any special kind of List/Array-instance I need to create and pass?

PySideQt Test Widget

Hi Guys,
After a little help from 20tab, I successfully compiled the plugin and ran the first example with the Py Anchor and everything worked great. The next step for me, is to have a PySide QtWidget running in Unreal. I uncommented this line, re-build and tried to run the following small script.

import sys
from PySide import QtGui, QtCore


class ModalWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ModalWidget, self).__init__()
        self.resize(200, 200)
        self.setWindowModality(QtCore.Qt.ApplicationModal)
        # Label Widget
        self.test_lbl = QtGui.QLineEdit(self)
        self.show()


class MainWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(MainWidget, self).__init__()
        self.resize(400, 200)
        self.window = None
        # Button Widget
        self.my_btn = QtGui.QPushButton(self)
        self.my_btn.clicked.connect(self.open_second_window)
        self.my_btn.setText("Open Modal Window")
        self.show()

    # Def to open the Modal window
    def open_second_window(self):
        self.window = ModalWidget()

When I import PySideTestWidget, it loads the module fine. When I try to execute PySideTestWidget.MainWidget() Unreal instantly freezes. Any idea why and how to fix?

Thanks,
Nick

***Note I'm relatively new to Python and completely new to Unreal.

Override material instance parameters

Is there anyway to do with the current python binding?

I would like to do something like this:

myMaterialInstance.OverrideScalarParameterDefault("UseThisColor", 1.0, True)

Cheers,
Eric

Sequencer API

Extend the editor api to allow scripting of the sequencer

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.