How to run Unreal blueprint nodes on BeginPlay that depend on another blueprint - unreal-engine4

I need blueprint A to run nodes in BeginPlay which rely on a variable in blueprint B, but that variable is null until set in B's BeginPlay function. Of course, A's BeginPlay could run before B's and I would run into errors. I can think of two ways to get around this, but neither feel like a proper approach:
In A's BeginPlay, add a Delay node with a second or less duration in the hopes that B's variable has been initialized by then. It seems like this could easy break things and isn't smooth.
Have an Event Dispatcher in B called "VariableSet". A binds an event to it in BeginPlay and that event runs the dependent code. This usually works but I haven't heard of anyone doing this.
Is there a proven, documented method to avoid null pointers in BeginPlay?

I've faced the similar problem in the past.
And in my case I just used Event Dispatchers. I'm not too proud of that aproach but It did a job.
Parent is calling ED at the end of BeginPlay execution flow
Child is binding ED to CustomEvent at the beggining of its own BeginPlay execution flow
When Parent's BeginPlay is finished (which calls ED), logic in Child's CustomEvent runs
For me it worked really well because one Parent had a lot of Childs and these Childs had their own Childs, etc, etc...
and due to Dispatchers and Events I was able to easily track what was going on.

Related

Unity3D get an Object in start Method

Hey im trying to get an object which is referenced in another script (dictionary).
But when i try to get the object in the start method it seems like the dictionary isnt populated jet.
Error: NullReferenceException: Object reference not set to an instance of an object
If I run this line of code in the update method it works completely fine.
Is there an easy way to let this line run after the dictionary is populated?
Grid Manager Script
Camera Movement Script
Both your code snippets run in Start.
There is no way to predict in which order these two Start messages will be invoked (at least not from the user perspective).
To solve this kind of race conditions (see Order of execution for event functions).
The Awake function is called on all objects in the Scene before any object's Start function is called.
my general thumb-rule is:
Use Awake
to initialize the component itself where it doesn't depend on values
from other components.
E.g. initializing your fields, filling your collections, using GetComponent etc to initialize references (but stop there)
Use Start to then initialize things where you do depend on other components being already initialized.
Like in your case access the collections of the other component
This usually covers most of the cases.
In your case simply converting GridManager.Start to GridManager.Awake should already solve the issue.
Where this is not enough you either can start and tweak the Script Execution Order and basically enforce a certain order in which the event methods get invoked or implement a more complex event based initialization system
Populate the dictionary in Awake() method instead of Start(), then it would be ready by the time you need it in Start() of another script.

UE4 -ApplyDamage to specific Actor

I have an issue I've been trying to fix for about a week now, but for the life of me cannot figure it out.
I have a function
DamageOnOverlap(AActor* HitActor, AActor* OtherActor
which deals damage on overlap. Within that function, I have the following function
UGameplayStatics::ApplyDamage(OtherActor, 25.0f, GetWorld()->GetFirstPlayerController(), this, UDamageType::StaticClass());
which deals damage to the overlapped actor. These two functions are in my
ZombieBasic.cpp
so then they overlap each other, they take damage and Destroy when their health is 0.
Is there a way to do a check or something so they're unable to cause damage to themselves?
I have done the following check
if(OtherActor == mainCharacter)
{
UGameplayStatics::ApplyDamage(OtherActor, 20.f, GetWorld()->GetFirstPlayerController(), this, UDamageType::StaticClass());
}
But either the they all still take damage or no damage is applied at all.
OtherActor will call AMainCharacter (AMainCharacter* mainCharacter is defined in the header file for ref).
So, I'm basically trying to stop ApplyDamage OR DamageOnOverlap from damaging other actors of the same type, which in this case, stop AZombieBasic from damaging another ABasicZombie.
Sorry if this is a rubbish explanation.
With some investigation, I have managed to fix the problem.
TL;DR
I added an Actor Tag to the mainCharacter class and did a check in ZombieBasic to see if an actor has the specified tag.
Read if you're interested
Adding an Actor tag to 'AMainCharacter' within the Blueprint Class under the Actor section and adding a new tag of Player. In ZombieBasic.cpp, in the DamageOnOverlap function I did a basic check of
if(OtherActor->ActorHasTag("Player")
{
// Deal Damage
}
Now when BP_BasicZombie overlap with themselves they no longer deal damage to themselves.

Understanding GLib Task and Context

I don't understand the GTask functionality? why do I need this?
In my mind it is like callback.. you set a callback to a source in some context and this callback is then called when event is happening.
In general, i'm a bit confused about what is a Context and a Task in GLib and why do we need them.
In my understanding there is a main loop (only 1?) that can run several contexts (what is a context?) and each context is related to several sources which in their turn have callbacks that are like handlers.
So can someone please make some sense for me in it all.
I don't understand the GTask functionality? why do I need this? In my mind it is like callback.. you set a callback to a source in some context and this callback is then called when event is happening.
The main functionality GTask exposes is easily and safely running a task in a thread and returning the result back to the main thread.
In general, i'm a bit confused about what is a Context and a Task in GLib and why do we need them. In my understanding there is a main loop (only 1?) that can run several contexts (what is a context?) and each context is related to several sources which in their turn have callbacks that are like handlers.
For simplicity I think its safe to consider contexts and loops the same thing and there can be multiple of them. So in order to be thread-safe the task must know which context the result is returned to.

Measuring Duration Of Service Fabric Actor Methods

I wish to measure the time it takes for some of my Actor methods to execute. I plan to use OnPreActorMethodAsync and OnPostActorMethodAsync to log when these methods have begun and finished execution.
However I also wish to measure the time it takes for these methods to execute. My original plan was to use an instance of StopWatch to begin timing in the OnPreActorMethodAsync class and stop in the OnPostActorMethodAsync class. However I'm unsure how I can accessthe same StopWatch instance in the second method. If there is a better way of doing this I would be very interested.
If anyone could point me in the right direction on this matter that would be great.
Many Thanks
By using some dirty reflection tricks you can access the Actors' call context.
More about it here: https://stackoverflow.com/a/39526751/5946937
(Disclaimer: Actor internals may have changed since then)

runBlock not working in sequence?

I am trying to create a basic spawn sequence- the block must be created, moveDownLeft, and then removeLeft. moveDownLeft and removeLeft work fine on their own when the block is added using self.addChild(block1) previously, however I need to have self.addchild within the sequence.
The only way that I can see to do this is use runBlock, and I looked at this question when I got an error using that: Swift: SKAction.runBlock -> Missing argument for parameter 'completion' in call BUT WHY?
So now I am left with this:
block1.runAction(SKAction.sequence([SKAction.runBlock({ self.addChild(self.block1) }), moveDownLeft, removeLeft]))
And nothing in the sequence works because the block is not created in the first place. Why is this happening?
Your code fragment is too short but it looks like a typical chicken and egg problem.
node can only run actions once it has been added as child and thus becomes part of the scene graph
your node is supposed to run an action that will eventually add itself to the scene graph but it's not in the scene graph yet so it won't run that action
Add the node as child first, then run the action. If you need the node to be inactive for some time, simply set it's visible property to NO for the duration. You kay also ned to change other properties, ie postpone creation of the physics body.