Values of Expose on Spawn variables of Component are not set when doing BeginPlay

When my actor component (say OOOComponent) is doing BeginPlay, Expose on Spawn variables are still in default value.

variables can only have correct value when AddOOOComponent node is finished, or when component enters first Tick.

Is this a bug? Anything I can do to fix it, or get a work-around? Thanks.

Hello,

Looking at screenshot you’ve provided, I’m having trouble following where you are setting Is Major. If you’ve said that when you Print IsMajor, value is correct, where exactly is issue occurring? Is there somewhere else that you are setting value of Is Major?

Hi: occurring issue is in Add Parent Component node. I set value of Is Major by exposing this variable, so you can see a pin on this node. This node would trigger Parent Component’s Begin Play event, and at that time, Is Major is not value I set. But after this node is done, I printed value of Is Major, and it’s value I set.

Could you provide a screenshot of your variable details panel where you are exposing variable and setting its default value?

Hi Sean: I get you a test project, please download it and check printed strings. Also please check comments I wrote on nodes. Thanks.link text

To be clear, you were looking for Level variable to print out “1” correct? I got this to work by adding Staff blueprint as a component of Actor blueprint. Then, I removed Tick event and Do Once node and replaced those with Event Begin Play. After doing this, I got a reference to Staff component and got Level variable from that. Finally, I plugged this in to Level pin on Add Staff node, and this got it to print 1 each time.

Here is a screenshot of how I altered setup:

No, I want it to print out 999, as you can see value in Add Staff node is 999. And, my intend is not adding Staff Component in Actor BP, I would like component to be added in run-time. component doesn’t exist in Actor BP at beginning. Tick event and DoOnce is to simulate a run-time adding, so please don’t remove it.

69157-should_print_999.png

Actor BP should be like image below, and always be; since Staff Component is only added in run-time, conditionally. And it should be added other than Actor’s BeginPlay, since if you do that, component’s BeginPlay won’t execute.

69158-clean_actor.png

reason that your value is not 999 when you print it out of Actor Component blueprint is because when you set that Level variable inside of Actor BP, it is only for that particular instance of Staff that you are spawning, not blueprint itself. Think of blueprint as a template, and each time you add an instance of staff to your Actor BP, it grabs that template and uses it to create a new Staff component. However, any changes made to new components will not apply to original template, it is just their for a basic framework, so to speak.

What you can do if you’d like value to print out in your actor component is set up a custom event that will use a variable based on return value of Add Staff node to grab that particular instance’s Level variable and print it out. This is only way to get behavior that you’re looking for.

Also, with Tick setup that you currently have, you’d be unable to use Tick for anything else, so it’s not recommend that you set it up this way. best way to do so would be to use a custom event instead.

Feel free to let me know if there are any questions.

I think I can get point of that Component Template design, but there’s another point: I can have correct value 999 printed out exactly after Add Staff node, despite of any complex setup; which means, value is correctly set, but just in a wrong (or not-desirable) timing. So, basically I’m questioning timing of setting 999 onto Component. In my imagination, execution order should be like: 1) Do Add Staff, give 999; 2) Use Template of Staff, spawn it, also set Level to 999; 3) Do Staff.BeginPlay(); 4) Finish Add Staff; 5) Maybe another print of Level, and it’s surely 999. But in real life, it’s like 1) is fine, but 2) is not good, it only does spawning (using Template), but not giving my value of 999. And weirdly, it gives value of 999 after step 4), which means I cannot use it during most important step 3). 999 is like initial value (not default value) of Staff, so it should be already set when doing BeginPlay(), otherwise, I don’t need to expose it on spawn. Finally for Tick setup, it’s only purpose is to simulate a runtime adding of Staff, I won’t do it in real game design, so it’s ok to forget it. Thanks.

When you’re spawning instance of Add Staff and setting values, you are only setting values for that instance. Staff blueprint is like default of that class, which means that when you change a value on an instance, this change will not apply to original default values. In order to get value of Level variable on a particular spawned instance of Staff class, you would need to get a reference to that instance and then grab that instance’s variable. Also, in case of my example, reason I have timer set to a 5 second delay is because running component’s begin play creates an order of operations issue. value of level will only be set a few seconds after begin play starts, just based on how Actor Blueprint is set up.

Hi, I have to apology for late reply. I’d like to explain again and try to make it clearer. (1) spawned Staff Component instance, lets say S, will be added into (or onto) owner Actor; So, in a later time, I can access it by Get Components by Class, which returns an array, and first element is S (since I only added one Staff Component); also, return value of Add Staff node is exactly S; So, which means, I don’t have to make an additional reference to store (remember) it. (2) Now talk about exposed variable, Level, of Staff Component; if I set it by Add Staff node (as I did in my example project), it is successfully stored in S (NOT stored in any temporary object), that’s why I printed it after Add Staff node, Level shows 999 instead of its default value; if I get Staff Component by Get Component by Class node now, it’s also S, so Level is of course 999; which means, there is no such thing like “only setting values for that instance”; Conclusion: Add Staff Component node is fine, I can successfully create a Staff Component, set exposed variable with my provided value 999, I can access added Staff Component perfectly any time. only problem is 999 is not usable in Staff Component’s BeginPlay(), which is DURING (or, part of) Add Staff Component node procedure. Such behavior is very undesirable, since 999 should be accessible in BeginPlay(), not after it.

In order to get functionality that you want, you cannot use components in way that you are wanting to use them. Instead of using a component blueprint, create another actor, spawn that actor, and then attach it to your original blueprint. Doing this allows you to get functionality that you are looking for without having to use setup that I provided above.

Here is what your actor would look like:

I’m not sure about attaching actor approach, I think it’s getting a little far away. My problem is fairy simple: I added a Staff Component, with exposed variable named Level, and I set it to 999. During necessary steps of adding it, however, I can’t use it! So, question is, is this by design? If so, why, since this design is annoying. If not, then will it be redesigned in future release? Thanks.

I’ll try to make it a real world example, so maybe it could be clearer. Sean is an ordinary people, one day he becomes staff of Epic, so Epic added a Staff Component onto Sean, also assign his level to 999, and Epic tells Sean “Welcome, now please report to HR department so that they can run some necessary procedures for you”. So, Sean write his level down on a little card, and prepare to show it to Epic Human Resource department, telling them his level is 999. One of procedures, for example, could be making a staff badge for Sean, which shows his name and Level on it. But, in HR department, Sean can’t use it’s little card, HR department just reject it, and says, “Sorry, all Staff can only run these procedures with our default template, so your level is 1 now”. So, Level shown on badge is default value, 1, despite that Sean is actually Level 999! So, assignment of 999 is useless! Since it’s invisible when running necessary procedures! However, after Sean left HR department, suddenly everyone recognizes little card, and Sean finally got his correct level as 999, and he has to manually overwrite his staff badge, make it 999 instead of 1. In such case, question is, why does Epic assign Sean’s Level to 999, before he can uses it?

Hi marsonmao,

We understand what you’re saying. Unfortunately, this is an order-of-operations problem, and that’s not going to change. Sean has offered some alternative approaches, and there are certainly other options, but at end of day method you have proposed is not going to work in this engine without altering source code.

, just wanted to point out I’m have a very similar issue on this post. I originally thought variables exposed to spawn acted like how a class constructor would initialize default values.

Hi marsonmao,
We understand what you’re saying. Unfortunately, this is an order-of-operations problem, and that’s not going to change. Sean has offered some alternative approaches, and there are certainly other options, but at end of day method you have proposed is not going to work in this engine without altering source code.

From what I read in your statement, , it seems that is case. Whatever this order of operation is, I have definitely noticed that values exposed on spawn are not set as soon as Begin Play is called. I have done some tinkering and discovered if a Delay node is somewhere between entry node and your main sequence, your spawn values will be set by time they are accessed. Delay node doesn’t even have to be set to anything other than 0. You can set it as 0 delay and your spawn values will still be set by time Begin Play accesses them.

I have no clue what is happening at engine level, but this is weird and counter-intuitive to those who’ve programmed in OOP before.

In C++ since Delay nodes don’t exist (which is my current problem in my post at time of writing this), my solution there is to either start a timer handler in Begin Play that calls an initializer method, or to invoke initializer method manually after spawning.

So now I ask Devs, if invoking an initializer method after spawn to set our instance’s spawn defaults then proceed to do some other setup using these values in same frame will work better than initializing defaults at spawn node to get class instance constructor behavior we desire, then what is point in having variables exposed to spawn in first place?

It’s same issue as described above. We often have to add delays and such in our systems as order of operations can be different than what we expect when coding it, whether in blueprints or C++. Your timer handle is solution that I often use as well for this type of issue. Unfortunately, this order of operations behavior would require a major overhaul of current system, so there is no resolution planned at this time. In meantime adding delays or calling things after a delay is best way to get around these sorts of issue.

Have a great day