20tab / UnrealEnginePython

Embed Python in Unreal Engine 4
MIT License
2.75k stars 746 forks source link

Blueprint call() and call_function() have no effect #774

Open jasper-law opened 5 years ago

jasper-law commented 5 years ago

Hi all, I'm trying to call a function that is part of my blueprint class.

I've tried both call() and call_function() on my UObject, but neither have any effect. Passing either method an incorrect function name returns an error, whereas the correct name gives no output at all.

I have also tried adding a print node to the function definition (nothing printed in any case), and I have tried both call() and call_function() at run time and in the editor.

Thanks in advance, Jasper

dfb commented 5 years ago

Can you share some code and screenshots? There's just not enough info here to be able to help you currently.

djsquber commented 5 years ago

Hi!

I'm running into a similar issue. I've found that self.some_actor.call_function(...) has no effect (i.e. the corresponding UObject function isn't called) when the supplied function name is correct and that it raises an exception when no function corresponds to the supplied function name. Please refer to PyActorImpl.py.

Thanks in advance, David


MyActorClass__snippet.cc ```cpp void AMyActorClass::RunDiagnostics(int a, int b) { UE_LOG(MyActorClassLog, Error, TEXT("this: %p"), this); UE_LOG(MyActorClassLog, Error, TEXT("GWorld: %p"), GWorld); UE_LOG(MyActorClassLog, Error, TEXT("GetWorld(): %p"), GetWorld()); UE_LOG(MyActorClassLog, Error, TEXT("a: %d"), a); UE_LOG(MyActorClassLog, Error, TEXT("b: %d"), b); TestSet_.Add(4); // Rename(TEXT("TestName")); // throw 1; } ```
MyActorClass__snippet.h ```cpp UCLASS(Transient, Blueprintable, UserHideCategories = (Rendering, Input, Actor, Collision)) class AMyActorClass : public AActor { GENERATED_BODY() ​ // ... ​ UFUNCTION() void RunDiagnostics(int a, int b); ​ // ... } ```
PyActorImpl.py ```python import unreal_engine as ue _BLUEPRINT_PATH = '/Game/Blueprints/Actors/' class PyActor: def __init__(self): world = ue.get_editor_world() blueprint = ue.load_object(Blueprint, _BLUEPRINT_PATH) self.some_actor_class = blueprint.GeneratedClass self.some_actor = world.actor_spawn(self.blueprinted_class) def CallRunDiagnostics(self): print 'ue.get_editor_world(): {}'.format(ue.get_editor_world()) uobject = self.uobject world = uobject.get_world() print 'PyActor self: {}'.format(self) print 'PyActor uobject: {}'.format(uobject) print 'PyActor world: {}'.format(world) print 'PyActor actor class: {}'.format(self.some_actor_class) print 'PyActor actor instance: {}'.format(self.some_actor) if self.some_actor: print "Alpha" # Good: Finds RunDiagnostics print self.some_actor.find_function('RunDiagnostics') # Bad: Finds RunDiagnostics but does not run RunDiagnostics self.some_actor.call_function('RunDiagnostics', 1, 2, 3) # Bad: Finds RunDiagnostics but does not run RunDiagnostics self.some_actor.RunDiagnostics(1, 2, 3) print "Bravo" # Good: Cannot find RunDiagnostics print self.some_actor_class.find_function('RunDiagnostics') # Good Error: Cannot find RunDiagnostics; throws exception self.some_actor_class.call_function('RunDiagnostics', 4, 5, 6, this=self.some_actor) # Very Bad: Finds RunDiagnostics and runs RunDiagnostics # When RunDiagnostics is called, `this` refers to the Class generated from the blueprint # Using member variables corrupts memory self.some_actor_class.RunDiagnostics(4, 5, 6, this=self.some_actor) print "Charlie" ```
dfb commented 5 years ago

Have you tried making the UFUNCTION BlueprintCallable?

djsquber commented 5 years ago

Thanks for the prompt reply.

BlueprintCallable didn't make a difference unfortunately.