Hi. I know that Blueprints main purpose are to allow designers to iterate quickly. And that more complicated systems probably should be designed in c++.
But is there a specific reason why you don’t allow programmers to rapidly prototype with their full potential in blueprints as well before we move over to c++?
There are some essential features that I’m really missing!
Being able to freely choose wheater something is private/protected/public.
Some things, like variables can ONLY be public or private. I might want to be able to access it within child classes, but NOT from other blueprints.
Being able to freely choose accessability for Custom Events.
Custom Events is required in order to use latent functions like the Delay node, which is saving SOOO much time.
But it’s rarely I want these events to be something other blueprints should fiddle with.
You have a tickbox to enable abstract classes. Which is great. Where are the abstract methods that FORCE you to override them?
I saw that with c++ you can add in PropertyAttributes that allow you to make a exposed variable hidden based on another variable state.
Is this something you could introduce for Blueprints as well?
I really wish BlueprintInterfaces could support EventDispatchers.
This happens 8/10 times I wish to use interfaces, I find that I can’t really, because I need the generic callback events.
Some variable types like UWorld especially, should be exposed to blueprints.
Using strings to load in levels is not really a solid method, as they are prone to spelling errors and they dont update if you change the names.
How ever, nothing stops you from creating a Load Level Instance (by Object Reference) node and converting its UWorld Soft Object to a variable.
This is super useful and most likely not supposed to be intended. But I think it should be!
You can do the same (as mentioned in point 6) with Event nodes. Create a Bind to Event node and drag the Event pin to a function input, and voila.
Generic callback method. Works amazingly for certain tasks. Like for example, a custom method I made called MakeConfimationWidget(AcceptCallback, DeclineCallback).
Please look into exposing these in an elegant way also.
If you have some comments on any of these I would love to hear your thought on the subjects.
Use Timers instead of relying on Delay nodes. Delay nodes are a quick hack, so it’s no regret with using Timers instead of them
Then you can set the access level to functions, it works since 4.25.
Actually, it’s a matter of adding a simple method like “Load Stream Level (by Object Reference)”. Load Level Instance also has 2 versions, accepting string and accepting TSoftObjectPtr<UWorld>.
Using Soft Object Ptr is all good and definitely intended, but IIRC it was added thanks to a pull request.
It would be a trivial work to add proper StreamLevel methods, I could look into it. Now, can’t promise if they would pull that in
I think you can do all the prototyping you want without having the specific restrictions of “checked access control” or whatever.
Make everything public. Only hide it if it gets in the way in some property panel. if it’s a bad idea to access something in another class, even though it’s public, simply don’t access it.
If you really, truly, need all the power of the C++ type system to express your design, then you should take that as an indication that you really do need C++
Thing is, some of the blueprints we will use for the final production as well. And I personally know well what I can and cannot tamper with.
But lets say a college taps into my public variable (assuming it cant be private due to child class access) and sets it manually and the entire blueprint goes into a broken state because of it.
Its not really great.
Also, we have just recently started learning the engine. And we all have a fair understanding of c++.
It just is much quicker to check if the data flow etc works in blueprints.
And sometimes the budget just tells us that we simply cannot take the time to make it into c++ after all.
Think there might have been misunderstanding. I know how to do it.
Its just that you cannot select the UWorld object from the dropdown of variable types where you select Int, Bool, etc.
This is one of many useful types that are not exposed as a blueprint type.
The only way to get a variable of these types is to convert a pin that happens to be of that type into a variable.
@Ledii
Submitted a change with these 2 new methods (by Object Reference). Let’s hope it will get accepted
If not, it’s trivial to put this method into your own project’s code or plugin… but this should definitely become part of the engine.
That sounds to me like a people problem, not a technology problem.
First, someone trying a variable without checking what it does.
Second, after trying it, not testing that it actually still works.
If you want to save someone the 20 seconds of finding the variable inside the blueprint before using it, then you can name such variables with some prefix, like “privMyVariable.”
Crude, and very effective. Assuming you don’t have problem people on the team. If you DO have problem people on the team, I’m afraid no technical solution is going to fix that for you.
Well yes, that is exactly why private and protected modifiers exist in the first place right?
Fixing people’s habits of coding is not easy. Preventing them from using the wrong stuff is. (or should be in this case)
Am I wrong?
I see. You must have done some simular workaround as I have been doing then?
The variable type that allows for a dropdown of levels is called World (UWorld) as far as I know, that is the only one that allows that.
I would really love for this variable type to be available here on this list. That is my wish / request.
Now, anyways… When you have a reference to it following the method I described earlier, you can then do this to grab the actual asset name out of it.
And if you can use the methods that take the Soft Object as a input pin, that is ofc preffered.
But this is still a neat know how to convert a asset dropdown to asset name string. =)
For #7
Let’s say you want to have a more generic player request for “asking for confirmation”.
This is a common feature that may occur many places in your games depending on what you are trying to make.
And making bindings to several callbacks is a little tedious if you want to do it without long spaghetti.
This is what my Widget looks like:
This is a function library to hook up the tedious pieces of nodes:
For #5
In our team at work, we dont really have the luxary of spending any budget on testing as of right now.
So the only reason we would want to use interfaces would be in the case that we would want to experiment with different implementations of a mechanic.
Let’s say we want to make some sort of a save system. Maybe we want this cloud based so that the user can share their saves accross devices.
In which case I would like to work with an internal SaveGame object first. Because that is the most simple case to handle.
So I would love to make UnrealSaveGame and CloudServiceSaveGame objects. Which both implement a shared interface.
I know that most common loading & saving APIs will supply you with getters & setters for common types like boolean, integers, floats and strings.
So I want to plan ahead for that in my system. So I create a interface with those getters & setters, right?
Well, I also need to be able to keep streaming levels persistent after the get unloaded and reloaded again.
To handle the states I decided to look into a state system to bind saved variables to conditions.
(There is lots of blueprints to this, but I will summarize the core of it here!)
Step 1, we make a state machine, and say what we want each state to initialize in the blueprint.
We also make a key string that will be used for the conditions later.
Step 3, we create conditions that is required to evaluate the particular state true.
(In the picture we want the condition to be “The boolean value stored in the Key of the SaveGameObject” should be “True”.
When you make a condition, it will also want to bind to an event dispatcher that will fire whenever the Key is set. (This is the part where I discover i can’t do it with interfaces, without event dispatchers)
The condition will then make a internal evaluation on weather it changed the result or not (to prevent firing again if its the same result).
If it happens to be a change, it will send a event dispatcher back to the StateMachine to run a full check.
Technology solutions to people problems seldom work. At best, they can help reinforce an actual people-solution.
(Yes, I claim that private/protected in the C++/Java style is a design mistake in software development, as is implementation inheritance. We have to live with these mistakes, but when we can avoid using them, we’re better off!)
If you really want private in blueprints, today, with no additional effort needed, use a naming convention!
If you have a team who can’t read and follow a naming convention, and keeps writing obviously broken code without testing it, fix your team!
My point was that fixing technology is still much easier for the most part than fixing people.
But I agree that fixing people would be the more “proper” solution if its a possibility.
When it comes to inheritance, it’s absolutly not a mistake!
Inheritance is one of the most powerful programming techinques out there.
If you think that is a mistake, I would argue you should look into learning what good you can use it for.
And private/protected is a also very essential part of that.
Without it, you would start crying when you were trying to access the one method you want to use, and find 1000 of simularly named methods available on the dropdown list.
It’s meant to be a clean-up feature. And working in a dirty environment is not good.