NewObject, USphereComponent & Overlap Events - Where does it go wrong?

Hey All,

Edit: Issue’s have been resolved! see last few posts!

Let me begin by saying that i’ve been reading the forum & awnserhub on overlap events for almost a week now, really sorry to add yet another thread on the subject, i just cant for the life of me figure out what the hell is wrong with my setup. I either get UE4 to crash entirely (like, the editor even) or i get something that doesnt work or show up, and im reaching a point where i just wanna say f*ck it and give up on UE4 development all together, which obviously isnt good.

In short, what im trying to do is this, i have a USceneComponent derived class, which is intended to be a ‘grabber’ for a VR game, in that class i try to create a USphereComponent so that later down the line i can check for overlap events between that and things i want my player to be able to grab. The problem is that my created USphereComponent seems broken if i create it with NewObject, or i crash UE4 if i try create my USphereComponent in the class construct or a BeginPlay via the CreateDefaultSubObject function (which i dont even want, i want to create it at runtime when a function is called, but ive been trying things i see others do successfully)

Im coming too the above conclusion that “my USphereComponent seems broken” because (when created with NewObject at runtime) while i am able to log its position, and can verify that yes, it is changing as i move my controller, when i run the console command ‘show Collision’ it doesn’t actually show my USphereComponent on the controller? (i’ve also verified that the radius i set is actually set, and that the coordinates match those of my controller) and thus not fire the overlap events (since theres nothing overlapping?)

So yea, really puzzled here, since im still pretty new too the engine im sure its just some small thing im overlooking, but after sifting trough dozens of similar threads/questions, watching a few youtubes on the subject, i still cant figure out what im missing here. Below some thoughts i keep looping trough

  • I guess maybe i need to fire some function on the USphereComponent to ‘create the shape’?
  • Something is off with the coordinates, even though looking at log output seems to suggest it positions fine?
  • Maybe it does actually have the USphereComponent at the right position, it has the right size and everything, it just doesn’t show when i run the console command ‘show Collision’ because whatever, and the overlap events dont fire because of something else?

I am a 100% sure that the objects im trying to get overlap events from (StaticMeshes) support that by the way, all the proper checkboxes are set, and i can get overlap events with them trough other routes.

Finally, the important bit, a trimmed version of my code:

UCustVR_MyGrabber.h



//...
UENUM(BlueprintType)
enum class UCustVR_EGrabberShapes : uint8 // The different Grab shapes
{
	BOX     UMETA(DisplayName = " Box "),
	SPHERE     UMETA(DisplayName = " Sphere "),
	CAPSULE     UMETA(DisplayName = " Capsule ")
};
//...
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class CUSTOMVRPLUGIN_API UCustVR_MyGrabber : public USceneComponent
{
	GENERATED_BODY()

public:
	//...
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR")
		bool EnableGrabber = true; // Enable the Grabber

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "VR")
		UCustVR_EGrabberShapes Grabber_Shape = UCustVR_EGrabberShapes::SPHERE; // The shape of the Grabber

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR")
		int Grabber_Shape_Radius = 16; // The Radius of the Grabber, used for Sphere & Capsule shapes
	//...
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR")
		FVector Grabber_PositionOffset = FVector::ZeroVector;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR")
		FRotator Grabber_AngleOffset = FRotator::ZeroRotator;

	// Setup the grabbers
	UFUNCTION(BlueprintCallable, Category = "VR")
		void SetupGrabbers();	

	// Delegate functions that'll be called during begin & end of overlap 
	UFUNCTION()
		void Grabber_OnBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
		void Grabber_OnEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
	//...

private:
	//...
	USphereComponent* Grabber_USphereComponent;
	//...
};


UCustVR_MyGrabber.cpp


//...
void UCustVR_MyGrabber::SetupGrabbers() {
	if(EnableGrabber) {
		switch (Grabber_Shape) {
			case UCustVR_EGrabberShapes::BOX:
				//...
				break;
			case UCustVR_EGrabberShapes::SPHERE:
				Grabber_USphereComponent = NewObject<USphereComponent>(this, FName("GrabberComponent"));
				Grabber_USphereComponent->SetSphereRadius(Grabber_Shape_Radius);
				Grabber_USphereComponent->SetWorldLocation(GetOwner()->GetActorLocation() + Grabber_PositionOffset);
				Grabber_USphereComponent->SetWorldRotation(GetOwner()->GetActorRotation() + Grabber_AngleOffset);
				Grabber_USphereComponent->AttachToComponent(GetAttachParent(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, NAME_None);
				Grabber_USphereComponent->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
				Grabber_USphereComponent->BodyInstance.SetResponseToChannel(ECC_PhysicsBody, ECR_Overlap);
				Grabber_USphereComponent->OnComponentBeginOverlap.AddDynamic(this, &UCustVR_MyGrabber::Grabber_OnBeginOverlap);
				Grabber_USphereComponent->OnComponentEndOverlap.AddDynamic(this, &UCustVR_MyGrabber::Grabber_OnEndOverlap);
				UE_LOG(LogTemp, Warning, TEXT("Created Grabber Sphere!?!??"));
				if (Grabber_USphereComponent) {
					UE_LOG(LogTemp, Warning, TEXT("Location: %s"), *Grabber_USphereComponent->GetComponentLocation().ToString());
					UE_LOG(LogTemp, Warning, TEXT("Radius: %f | %f"), Grabber_USphereComponent->GetScaledSphereRadius(), Grabber_USphereComponent->GetUnscaledSphereRadius());
				}
				break;
			case UCustVR_EGrabberShapes::CAPSULE:
				//...
				break;
		}
	}
	//...
}
//...

void UCustVR_MyGrabber::Grabber_OnBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
{
	//...
	UE_LOG(LogTemp, Warning, TEXT("Grabber OnBeginOverlap Fired!!?!"));
}
void UCustVR_MyGrabber::Grabber_OnEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	//...
	UE_LOG(LogTemp, Warning, TEXT("Grabber OnEndOverlap Fired!!?!"));
}

If anybody has any clue at all to what i might be doing wrong, im open to any and all input, i just cant see how to resolve this or further debug it :confused:

I am not pro at UE4 (yet). What is broken? The collision is not triggering?

I believe you have to call RegisterComponent on it after it’s created.

Yep the collision/overlap-event isnt triggering, and i cant figure out why.

Nice, thanks for the input! sadly this just seems to give me more engine crashes :frowning: investigating this function now tho, may get it working (will obviously report back if i do)

Any other ideas anyone? :slight_smile:

Edit: Just to confirm, nope, cant use RegisterComponent, that can only be used in the constructor of a UObject derived class, but i want to do it elsewhere (because it may not need the shape, depending on certain settings, so i need to do it only when its needed, ie; not on construct)

here is my few cents (might be wrong though, use it with lots of salt)

createdefaultsubobject is only for constructor, it doesnt need registercomponent as it is automatically being registered.

Anywhere else would be NewObject. It requires to be registered.

Usually crashes are due to calling invalid objects that is not created. Try calling RuntimeMesh->IsValidLowLevel() to check if the object exists before doing anything to it.

Yup, am using NewObject :slight_smile: didnt know about IsValidLowLevel yet though, trying! :smiley: thanks for the input, will report back here how it goes :slight_smile:

Edit:
Tried it, and while it does let me use the RegisterComponent function now that its in an if statement that checks IsValidLowLevel, its not changing anything, still dont see the collision sphere of the USphereComponent when i run the console cmd ‘show Collision’, nor am i getting overlap events. (so im guessing it does register automatically then?)

Im looking at the Runtime Mesh Component page now (since that what u apparently use?) and im seeing things like:

and this again ‘fuels’ the idea that theres some functions i will need to fire to update the collision when the USphereComponent has been moved?

Edit2:
Came across the UpdateOverlaps function, tried using that (firing it on tick as a test) but no difference.

Still/again; very much open to any sort of input guys, all ‘few cents’ help so to say, im so puzzled here.

how about this for visibility?

Thanks for the input, but nope, no luck.
I have the below by now (for visibility) and still nothing shows (either ‘as is’ or when i run the ‘show Collision’ console cmd)


Grabber_USphereComponent->bVisualizeComponent = true;
Grabber_USphereComponent->ToggleVisibility(true);
Grabber_USphereComponent->bHiddenInGame = false;
Grabber_USphereComponent->SetHiddenInGame(false);

Im really stumped here, the 3 thoughts i mention in the first post are pretty much exhausted at this point;

  • I’ve tried to call any and all functions that seem even remotely related to ‘create the shape’, no progress.
  • I’ve made some effort to make extra sure that the USphereComponent’s location is what it should be, and it is.
  • I’ve looked at the overlap event problem in any way i can imagine, the events should just fire for all i can tell, but they dont…

Starting to think what im trying (create USphereComponent on runtime and having that trigger overlap events) simply isnt possible, or used to be possible but is broken in 4.14 :confused:

hello a few weeks ago i was trying to do some things similar to what you are trying to achieve here. with the help of some nice forumers i ended up making both a c++ function and a blueprint function to do exactly this . if you want i can share the code and you can take what you need.

here is the bp node in action

and the result

its pretty versatile you can make multiple components of the same type or even a mixture of different ones.

for example here im creating a loop to spawn 5 sphere components

and result

http://image.prntscr.com/image/cd72da8ad26a4432ae58a7f90be88214.png

the c++ version is a bit more powerful as it can actually be used in editor as well as runtime to spawn objects before you even press play. im still working on a way to get my blueprint node to be safe to use during construction script without causing an endless loop and crashing .

if this is what you meant then let me know and ill upload the c++ code

thanks

BIG THANKYOU to forumer smartyMARTY who helped me get this far :-p

Heya EniGmaa,

Thanks for the reply!! :slight_smile: long story short, yes, i would love too see the c++ code behind that! :smiley:
I do see you ‘hook into’ BeginPlay, wondering if thats mandatory for your solution? (ie; do you use NewObject or CreateDefaultSubObject?)

Either way i’d still be very interested, for one i’ve never even seen the USphereComponent’s pop up (from my code anyway) during runtime, and your idea is pretty much 1on1 what i was thinking too, an option to change between different collision shapes, since you got it actually working im gonna just accept that whatever your approach is, thats the way to go, and alter my code accordingly :stuck_out_tongue:

And yea, this is for a c++ plugin that creates a bunch of custom bp nodes, so the similarity between what we('re in my case trying to) do is uncanny :stuck_out_tongue:

Cant wait to hear back from u, feel free to send me a messy or stripped down piece of code if that saves u time, anything that can get me something similar to your screenshots will make my day :o

hello yes i am using new object . no it doesn’t have to use begin play i was just using that for quickness. like i said its quite versatile you can use it multiple ways. like for instance here i have set it up to call the function to create the box component every time i press the t on the keyboard you could set up a function for each component type and call it how ether you want.

and here it is in action

https://www.youtube.com/watch?v=tKBQq158NG8

its a bit messy as like i said i am still kinda playing around with it myself but full source code and project can be found here.

https://github.com/R3KLESS/escapeTheRoom

other_computer_branch

just clone the repo rebuild dlls and regenerate the visual studio files and it should all be set up to go. if you need any help just pm me

BIG THANKYOU to forumer smartyMARTY who helped me get this far :-p

I love you, going over the code now, will report back here with what turns out to be the solution or if i’ve rebuilt my class to get it to work, thanks a million dude, really! <3 :o

Got it about 75% working so far, this is what i have now:


Grabber_USphereComponent = NewObject<USphereComponent>(GetOwner(), FName("GrabberComponent"));
Grabber_USphereComponent->AttachToComponent(GetAttachParent(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, NAME_None);
Grabber_USphereComponent->SetSphereRadius((float)Grabber_Shape_Radius);
Grabber_USphereComponent->SetRelativeLocation(Grabber_PositionOffset);
Grabber_USphereComponent->SetRelativeRotation(Grabber_AngleOffset);

GetOwner()->AddInstanceComponent(Grabber_USphereComponent); // Add to SerializedComponents array so it gets saved
Grabber_USphereComponent->OnComponentCreated(); // Fire off the event that a Component was created
Grabber_USphereComponent->RegisterComponent(); // Register the Component so that it is active in game code

Grabber_USphereComponent->OnComponentBeginOverlap.AddDynamic(this, &UCustVR_MyGrabber::Grabber_OnBeginOverlap); // Overlap events :D
Grabber_USphereComponent->OnComponentEndOverlap.AddDynamic(this, &UCustVR_MyGrabber::Grabber_OnEndOverlap);

Grabber_USphereComponent->SetNotifyRigidBodyCollision(true); // Collision - Simulation Generates Hit Events boolean
Grabber_USphereComponent->bGenerateOverlapEvents = true; // Collision - Generate Overlap Events boolean
Grabber_USphereComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); // Collision - Collision Presets - Collision Enabled
Grabber_USphereComponent->SetCollisionResponseToChannel(ECC_PhysicsBody, ECR_Overlap); // Collision - Collision Presets - Set all Collision Responses to Overlap (? not sure what the ECC_PhysicsBody does since in editor it shows up as set too WorldDynamic)

#if WITH_EDITOR
	GetOwner()->RerunConstructionScripts();
#endif

UE_LOG(LogTemp, Warning, TEXT("Grabber created woopwoop!"));


(line 7-9 came from EniGmaa’s code and solved the USphereComponent creation problem wooh! Thanks again man!)

The problem is that im only getting overlap ‘delegates’/events on running the above code, ie; when the USphereComponent gets created it fires the Grabber_OnBeginOverlap ‘delegate’/event for whatever is overlapping the sphere (before im even getting the “Grabber created …” log message i get the log message set up inside Grabber_OnBeginOverlap for each overlap) but after that, it doesn’t fire anymore when i move the sphere to end overlap / begin new overlap.

I’ve tried the earlier mentioned Grabber_USphereComponent->UpdateOverlaps function on tick (once the component is created) but that doesn’t seem to change anything (and kinda defeats the purpose of events if that’s how its expected to work?)

Im going over the docs & every recent post/question related to overlap events again, checking if i missed something, but if anybody has any tips that be great :slight_smile:


Edit:

Turns out that this bit of code was doing more harm then good:



#if WITH_EDITOR
	GetOwner()->RerunConstructionScripts();
#endif

Remove it from the above snippet and it works :smiley:

Thanks all!!

That bit of code is used to make sure the components show up in the editor details panel so you can edit them. Although if you ate doing all the editing by code it is probably unnecesary .

Normally when an actor is created the construction scripts run automatically and registers all the components, child components etc but in the case of dynamically creating the components the actor already exists so you need to rerun the construction scripts so that it finds the newly created components .

I think if you take it from where it is and put the code straiight under this bit of code

“Grabber_USphereComponent->RegisterComponent(); // Register the Component so that it is active in game code”

It should then work as expected. I think the reason it’s causing problems is because you are basically setting up all the overlap events THEN calling the rerun of the construction scripts which basically reverts all the changes .

Also I noticed you are manually setting the component name on creating it
" FName(“GrabberComponent”));
Grabber"

Which is fine but if you were to ever create another component of the same type it will crash the editor because they cannot have the same name which is why in my code I added all the extra code to check if two components of the same type exist and if so it will append the name with _ and then an integer eg name_01, name_02 and so on

I might be wrong but try moving it and see . Anway seems you got what you needed so good luck

Hey man,

Thanks for all the extra input :smiley: Will give it some thought/try moving things around a bit, but yea, currently its finally workin after about 1,5 week of trying, so not too eager to break it again :stuck_out_tongue: I did try this a bit already, and it appears that im sorta stuck with the current order of calling the different functions, if i move stuff around i either stop getting the overlap events, or crash the engine.

One thing to note, is that the code u shared was for 4.12, and im on 4.14, some of the syntax/arguments changed and some functions appear to be redundant now, like if i comment out the RerunConstructionScripts bit i actually still see the component show up in the editor at runtime, and can be edited as i see fit (wich helped in testing) so something changed there between .12 and .14, or how my NewObject has different arguments then yours, both of those are due to different engine versions.

Either way, yea, thanks a million man, ill play around a bit with putting the RerunConstructionScripts back in, but if that doesnt fly (read; crashes the engine or stops overlap events) ill just omit it and accept that what i have now is the way to go.

Next i will probably turn it into a function like you did so its easier to re-use :slight_smile:
Thanks again, much love <3 :o