-
Notifications
You must be signed in to change notification settings - Fork 240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Creation of properties from managed code #61
Comments
The property Properties can't be created from managed code at the moment. |
Thank you! I just figured that out on my own. :-) Is this the recommended way to maintain state on a subclassed Actor? I'd rather not make Blueprint classes that are just property bags, if you will. It doesn't feel like the native C# way of doing things. For example, I handle |
If you don't need to pass it back and forth to the engine (and later in future for network synchronization with a few other things), then you can just declare managed variables/properties as you normally do.
But in this case, yes, it becomes a problem since object references come from the engine, so data should be stored there as well. Yes, the only option is to use workarounds with object IDs, at the moment, since properties is the only intermediate type-safe data storage. I wish we have aspect-oriented interceptors for properties as a language feature like how it's done in PostSharp, so I could transparently hook and redirect managed properties to Unreal ones. |
That's a good point about network sync. I'll give it a think and maybe come up with some abstraction so I can deal more with POCOs than with all this glue. Is it possible to create Blueprints programmatically/at runtime? I can't imagine a way to make Source Generators work.. because it'd more so be trying to generate stuff the engine can consume instead of managed code consuming.. or possibly generating both -- think I noticed you flagged this as an enhancement, did you want me to keep this issue open? |
Yes, it's possible, and I'm working on it, but it's a very tricky thing.
Yes, please, keep it open. This is one of the high-priority tasks in my list for a few months already. |
You might wanna check https://github.com/pamidur/aspect-injector - Apache-licensed compile-time AOP framework. |
@Dreamescaper Interesting, thanks for the link. |
For anyone that wants a short term solution that will allow them to use properties to feed stuff in and out of their blueprints (without a lot of boilerplate code) you can use these bits of code (You still need to create the properties in the blueprint, but now you can use them in a more natural to c# way): Create a file called ActorExtensions.cs and put this class in it:
Then when you define a property simply do:
|
I'm planning to do something similar with aspects injection, but automatically. |
Just a quick question: Has there been any progress on this ? I guess there are two parts,
|
Yes, the second part is tricky. The way how engine work with properties that created at runtime is hard to wrap around in a flexible way. |
Have you considered generating C++ code based on defined C#? I mean, for property/components definition. I'm not that knowlegeable in UE as in .NET development, but I've used Roslyn for build-time C# code generation with great success and don't see why it wouldn't work for generating C++ bindings for that particular purpose. It will allow typesafe and fast interop as well, instead of relying on strings. |
Yes, and I even implemented this for testing purposes. This approach has several caveats on the engine side. For example, as soon as you make more advanced C++ code touching blueprints it becomes impossible to dynamically reload the plugin with generated code, the entire editor has to be restarted to reflect changes.
The current implementation for accessing properties is type-safe and relatively fast. The primary goal with the generation of properties with aspect injection is to improve usability and workflow. |
@OlsonDev How do you make use of object IDs? I mean, which UnrealCLR functions work with Object IDs?
@OlsonDev If I understand it correctly, were you suggesting that @nxrighthere Why wouldn't |
As long as it's not null it will always return a reference to the actual actor. This function converts a blittable pointer to a managed reference, this intermediate conversion is required due to interop limitations of .NET, see dotnet/runtime#40484 (comment). |
I mean, I don't know much about UE, but wouldn't the generated code be part of the would-be game logic cpp project? And if so, how would it result in engine restart requirement? |
The game code is a module essentially, similarly to plugins it's being reloaded after you make changes to C++. Once you add generated code as a blueprint function library the same limitations apply to it. |
Uhm, I don't follow. What's the difference between adding .cpp file by yourself and via File.WriteAllText() or something? Manually added classes certainly don't require engine restarts. do they? |
It's not about how do you add code, it's about how the engine's runtime work with modules. Generation and compilation is not an issue, the issue is reflecting the changes in the editor dynamically. |
I don't want to annoy you by continuing to ask the same question, but it's still very confusing. What I mean is that, if, say, I want to write a .cs file with a class with several intended-to-be UPROPERTY's, that would look like Then .cpp project gets rebuilt as per new changes, .net embedding host is restarted and everything's good, aint't? |
Yes.
Yes it does, but hot-reload has limitations, for example, you can't reload a module with a blueprint function library.
You have to understand how inconsistent and limited hot-reload in Unreal, which makes code generation useless. |
Right. Yeah, that clears it up. Thanks for explaining. Never thought that to be an issue. |
It seems that now we have Data Registries which can be used as an intermediate type-safe data storage. It's introduced in Unreal Engine 5 and 4.27.0, so I'm going to investigate it. |
Any progress on this front? |
You can find some info here. |
I have a class deriving from
Actor
, with a constructor that looks like:When I play in the editor, it outputs
False; 9001
when I'd expectTrue; 42
.I've played around and moved the
GetInt
andSetInt
calls all over, thinking perhaps it was an object lifetime issue, but I can't seem to get this to ever print out my expectations. Currently I'm instantiating aCard
inOnWorldPostBegin()
. I've also triedGetBool
andSetBool
and those didn't work either -- I'm guessing this is broken for all of the method pairs.The
AddTag()
call seems to work -- I can see it when I inspect the Details pane with the Card actor selected.Is this a bug or am I doing something wrong?
The text was updated successfully, but these errors were encountered: