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);
}