C++ Component to Component Casting - Can't change variable values

Hello,

I am new to coding and may be making a simple mistake.

I would appreciate any advice regarding my problem.

Is it possible to change a local variable inside a component by casting from a second component of a different class?

I’m able to call an event in another component by casting, but when I try to update any variables it causes a crash.

I have found that global variables do work, but for my project I cannot use them. As there will be many instances in the same actor - which each require different values for every variable.

For testing purposes, I have created two simple Uclasses components which are derived from a scene component. They only have the bare minimum functionality required to replicate the crash.

The project download is available here:

code snippet below:

  • The header files are shown before the
    constructors.
  • The first component casts to the
    second component class.
  • Casting is done via component hit.

Code as follows:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "Components/SphereComponent.h"
#include "CompReceive.h"
#include "CompCastFrom.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class COMPCASTTEST_API UCompCastFrom : public USceneComponent
{
	GENERATED_BODY()

public:	
	UCompCastFrom();


	UFUNCTION(BlueprintCallable)
		void OnDelegateHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);


	UPROPERTY(EditAnywhere)
		USphereComponent* CastingCollision = nullptr;

	UPROPERTY(EditAnywhere)
		bool HasCast;

		
};

// Fill out your copyright notice in the Description page of Project Settings.


#include "CompCastFrom.h"

UCompCastFrom::UCompCastFrom()
{
	CastingCollision = CreateDefaultSubobject<USphereComponent>(FName("CastingCollisionName"));
	CastingCollision->SetMobility(EComponentMobility::Movable);
	CastingCollision->SetVisibility(true, false);
	CastingCollision->SetHiddenInGame(false, false);
	CastingCollision->AttachToComponent(this, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
	CastingCollision->SetCollisionEnabled(ECollisionEnabled::Type::QueryAndPhysics);
	CastingCollision->SetCollisionProfileName("BlockAll", true);
	CastingCollision->SetSimulatePhysics(true);
	CastingCollision->SetWorldScale3D(FVector(2, 2, 2));
	CastingCollision->SetNotifyRigidBodyCollision(true);
	CastingCollision->OnComponentHit.AddDynamic(this, &UCompCastFrom::OnDelegateHit);


	HasCast = false;

}


void UCompCastFrom::OnDelegateHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
	if (HasCast == false)
	{
		
		Cast<UCompReceive>(OtherComp)->CastMessage(true);

		HasCast = true;
	}
}
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "Components/SphereComponent.h"
#include "CompCastFrom.h"
#include "CompReceive.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class COMPCASTTEST_API UCompReceive : public USceneComponent
{
	GENERATED_BODY()

public:	
	UCompReceive();

	UFUNCTION(BlueprintCallable)
		void CastMessage(bool MessageBool);

	UPROPERTY(EditAnywhere)
		USphereComponent* ReceiveCollision = nullptr;

	UPROPERTY(EditAnywhere)
		bool HasReceivedCast;

		
};

// Fill out your copyright notice in the Description page of Project Settings.


#include "CompReceive.h"


UCompReceive::UCompReceive()
{
	ReceiveCollision = CreateDefaultSubobject<USphereComponent>(FName("ReceiveCollisionName"));
	ReceiveCollision->SetMobility(EComponentMobility::Movable);
	ReceiveCollision->SetVisibility(true, false);
	ReceiveCollision->SetHiddenInGame(false, false);
	ReceiveCollision->AttachToComponent(this, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
	ReceiveCollision->SetCollisionEnabled(ECollisionEnabled::Type::QueryAndPhysics);
	ReceiveCollision->SetCollisionProfileName("BlockAll", true);
	ReceiveCollision->SetSimulatePhysics(true);
	ReceiveCollision->SetWorldScale3D(FVector(2, 2, 2));
	ReceiveCollision->SetNotifyRigidBodyCollision(true);

	HasReceivedCast = false;
		
}


void UCompReceive::CastMessage(bool MessageBool)
{
	//Print String shows when HasReceivedCast bool value unchanged - confirming that a component can call an event in another component
	GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, (TEXT("Message Received")));

	//Causes crash when this bool value is updated
	HasReceivedCast = MessageBool;

	//Print string to check HasReceivedCast bool was changed - not seen due to engine crash
	FString PrintStringResult = HasReceivedCast ? TEXT("true") : TEXT("false");
	GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, PrintStringResult);
		

}