Unreal Engine scene component returning null when attached to actor

I have a scene component that uses addforce() to create a gravity-esque acceleration that points in the owner’s z axis. When added to an asset that is not based off of a C++ or Blueprint class, the component works as it should, but when attached to an asset that is based off of a C++ or Blueprint class the component returns a nullptr exception. I think that the component is unable to find the owner when attached to class based asset but I am unsure as to why. (I am not completely confident in this hypothesis as I am still inexperienced with Unreal.) Here is my c++ code:

#pragma once

#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "SceneGravity.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class TESTS_API USceneGravity : public USceneComponent
{
	GENERATED_BODY()

public:	
	// Sets default values for this component's properties
	USceneGravity();

protected:
	// Called when the game starts
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

	UStaticMeshComponent* Mesh;
	UPROPERTY(EditAnywhere)
		float GravStrength = -2000.0f;
};
#include "SceneGravity.h"

// Sets default values for this component's properties
USceneGravity::USceneGravity()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;

	// ...
}


// Called when the game starts
void USceneGravity::BeginPlay()
{
	Super::BeginPlay();
	Mesh = Cast<UStaticMeshComponent>(GetOwner()->GetRootComponent());
	// ...
	if (Mesh == nullptr){
		UE_LOG(LogTemp, Warning, TEXT("Gravity references nullptr"));
	}
}


// Called every frame
void USceneGravity::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	const FVector Force = this->GetUpVector();
	if (Mesh != nullptr) {
		/*Exception thrown : read access violation.
		this->Mesh was nullptr.*/
		Mesh->AddForce(Force * Mesh->GetMass() * GravStrength);
	}
	// ...
}

.


#include "SceneGravity.h"

// Sets default values for this component's properties
USceneGravity::USceneGravity()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;

	// ...
}


// Called when the game starts
void USceneGravity::BeginPlay()
{
	Super::BeginPlay();
	Mesh = Cast<UStaticMeshComponent>(GetOwner()->GetRootComponent());
	// ...
	if (Mesh == nullptr){
		UE_LOG(LogTemp, Warning, TEXT("Gravity references nullptr"));
	}
}


// Called every frame
void USceneGravity::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	const FVector Force = this->GetUpVector();
	if (Mesh != nullptr) {
		/*Exception thrown : read access violation.
		this->Mesh was nullptr.*/
		Mesh->AddForce(Force * Mesh->GetMass() * GravStrength);
	}
	// ...
}


What do you mean by “non-actor”? A component can only be added to actors that’s why they the base class is called UActorComponent. Judging by your code you mean one without a static mesh?

You would want UPrimitiveComponent if you want it a more general component.

My bad. I meant that assets that weren’t based off of a blueprint or c++ class would work just fine while assets that were based off of c++ and blueprint classes would result in the given exception. Unfortunately, I set out to use this on my player character which is based off of a C++ class. Apologies for misusing the terminology, I can understand how that would be confusing.

Your player character most likely doesn’t have a static mesh component and instead has a skeletal mesh component. So this code is going to result in nullptr being assigned to Mesh

Mesh = Cast<UStaticMeshComponent>(GetOwner()->GetRootComponent());

Both Skeletal and Static Mesh component’s derive from UMeshComponent so you can use that instead.

Both Skeletal and Static Mesh component’s derive from UMeshComponent so you can use that instead.

Unfortunately, that doesn’t seem to work. I am still getting the same exception after using UMeshComponent. I might look for a different solution for my desired mechanic if I can’t find a way to resolve this issue, one other than addforce(), addimpulse(), and SetPhysicsLinearVelocity(). Thanks for making an effort to help, it is much appreciated.

Well if all you need is those 3 functions then that would be a UPrimitiveComponent so using that instead would work with more types.

Also are you sure the root component is what you expect it to be?

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms