Unreal Engine 5 Crashing with projectile decal

Hello,

I recently began an Unreal Engine project for a class and part of the tasking was to create a paintball-like splatter effect when firing the projectile. So, I followed the steps provided in our tutorial but experienced two different (but possibly same root cause) crashes.

To start, we were tasked with creating a new material. To this material, we needed to add a 2x2 Splatter texture as a TGA file, connect it to a SubUV_Function and use a Constant2Vector attached to the SubImages(V2) node to define the 2x2 grid that these textures would be pulled from. We would create a Scalar Parameter named Frame to tie into the Frame(S) Node. Then, the alpha from the SubUV_Function would get tied into the Opacity from the Material. For this to happen, we had to ensure that the Material Blend Mode was set to Translucent. So far, so good.

Next, we had to create a Constant3Vector that we would convert into a Parameter and name ā€œColorā€, change this to something like Red that would be visible, and tie it into Base Color. As soon as I did this it would crash with the following error stack:


UnrealEditor_FPSGAM415_patch_0!AFPSGAM415Projectile::OnHit() [C:***Source\FPSGAM415\FPSGAM415Projectile.cpp:61]
UnrealEditor_FPSGAM415_patch_0!AFPSGAM415Projectile::execOnHit() [C:***Intermediate\Build\Win64\UnrealEditor\Inc\FPSGAM415\UHT\FPSGAM415Projectile.gen.cpp:102]
UnrealEditor_CoreUObject
UnrealEditor_CoreUObject
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Core
UnrealEditor_Core
UnrealEditor_Core
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_UnrealEd
UnrealEditor_UnrealEd
UnrealEditor
UnrealEditor
UnrealEditor
UnrealEditor
UnrealEditor
UnrealEditor
kernel32
ntdll

After this, I made a little bit more progress by continuing the tutorial which instructs us to Change the Material Domain to Deferred Decal. Doing this made it so that tying in the ā€˜Colorā€™ Parameter no longer caused the crash, so I continued to work.

Next up, we were instructed to go to the C++ Classes and modify the Projectile class to spawn the decal and randomize the color and frame with every impact, in essence creating a splatter effect.

As soon as the class was saved, it was supposed to be usable. Instead, as soon as I loaded into the play preview, I could run around but as soon as I shot the gun, Unreal would crash on impact of the projectile, right when it should be running all the functions for the decal and color changes.

For reference, here are the new lines of code:

Projectile.h (I tried to just put a screenshot of the code for ease of reading, but that would exceed my attachments limit, so hereā€™s the full thing)

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FPSGAM415Projectile.generated.h"

class USphereComponent;
class UProjectileMovementComponent;

UCLASS(config=Game)
class AFPSGAM415Projectile : public AActor
{
	GENERATED_BODY()

	/** Sphere collision component */
	UPROPERTY(VisibleDefaultsOnly, Category=Projectile)
	USphereComponent* CollisionComp;

	/** Projectile movement component */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = "true"))
	UProjectileMovementComponent* ProjectileMovement;

	UPROPERTY(EditAnywhere)
		UStaticMeshComponent* ballMesh;

	UPROPERTY(EditAnywhere)
		UMaterial* baseMat;

public:
	AFPSGAM415Projectile();

	/** called when projectile hits something */
	UFUNCTION()
	void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);

	/** Returns CollisionComp subobject **/
	USphereComponent* GetCollisionComp() const { return CollisionComp; }
	/** Returns ProjectileMovement subobject **/
	UProjectileMovementComponent* GetProjectileMovement() const { return ProjectileMovement; }
};


Projectile.cpp

#include "FPSGAM415Projectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Components/SphereComponent.h"
#include "Components/DecalComponent.h"
#include "Kismet/KismetMathLibrary.h"
#include "Kismet/GameplayStatics.h"

AFPSGAM415Projectile::AFPSGAM415Projectile() 
{
	// Use a sphere as a simple collision representation
	CollisionComp = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComp"));
	CollisionComp->InitSphereRadius(5.0f);
	CollisionComp->BodyInstance.SetCollisionProfileName("Projectile");
	CollisionComp->OnComponentHit.AddDynamic(this, &AFPSGAM415Projectile::OnHit);		// set up a notification for when this component hits something blocking

	// Players can't walk on it
	CollisionComp->SetWalkableSlopeOverride(FWalkableSlopeOverride(WalkableSlope_Unwalkable, 0.f));
	CollisionComp->CanCharacterStepUpOn = ECB_No;

	ballMesh = CreateDefaultSubobject<UStaticMeshComponent>("Ball Mesh");

	// Set as root component
	RootComponent = CollisionComp;

	ballMesh->SetupAttachment(CollisionComp);

	// Use a ProjectileMovementComponent to govern this projectile's movement
	ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileComp"));
	ProjectileMovement->UpdatedComponent = CollisionComp;
	ProjectileMovement->InitialSpeed = 3000.f;
	ProjectileMovement->MaxSpeed = 3000.f;
	ProjectileMovement->bRotationFollowsVelocity = true;
	ProjectileMovement->bShouldBounce = true;

	// Die after 3 seconds by default
	InitialLifeSpan = 3.0f;
}

void AFPSGAM415Projectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
	// Only add impulse and destroy projectile if we hit a physics
	if ((OtherActor != nullptr) && (OtherActor != this) && (OtherComp != nullptr) && OtherComp->IsSimulatingPhysics())
	{
		OtherComp->AddImpulseAtLocation(GetVelocity() * 100.0f, GetActorLocation());

		Destroy();
	}

	if (OtherActor != nullptr)
	{
		float ranNumX = UKismetMathLibrary::RandomFloatInRange(0.f, 1.f);
		float ranNumY = UKismetMathLibrary::RandomFloatInRange(0.f, 1.f);
		float ranNumZ = UKismetMathLibrary::RandomFloatInRange(0.f, 1.f);
		float frameNum = UKismetMathLibrary::RandomFloatInRange(0.f, 1.f);

		FVector4 randColor = FVector4(ranNumX, ranNumY, ranNumZ, 1.f);

		auto Decal = UGameplayStatics::SpawnDecalAtLocation(GetWorld(), baseMat, FVector(UKismetMathLibrary::RandomFloatInRange(20.f, 40.f)), Hit.Location, Hit.Normal.Rotation(), 0.f);
		auto MatInstance = Decal->CreateDynamicMaterialInstance();

		MatInstance->SetVectorParameterValue("Color", randColor);
		MatInstance->SetScalarParameterValue("Frame", frameNum);
	}
}

Iā€™m sure this is something I am messing up, but Ive gone back through multiple times to recreate the project, following the tutorial, with the same results, and crashes in the same places.

The crash happens at line 61, which line is that in your code?
I would hazard a guess that youā€™re calling Destroy on your projectile and then trying to set parameters on it afterwards, try commenting out Destroy() and see if that works

Line 61 for the code is:

auto MatInstance = Decal->CreateDynamicMaterialInstance();

but I will try the commenting out Destroy thing and see what happens.

itā€™s also worth noting that you should ā€œif checkā€ everything too, so:

auto Decal = UGameplayStatics::SpawnDecalAtLocation(GetWorld(), baseMat, FVector(UKismetMathLibrary::RandomFloatInRange(20.f, 40.f)), Hit.Location, Hit.Normal.Rotation(), 0.f);

if(Decal)
{
		auto MatInstance = Decal->CreateDynamicMaterialInstance();
if(MatInstance)
{
		MatInstance->SetVectorParameterValue("Color", randColor);
		MatInstance->SetScalarParameterValue("Frame", frameNum);
}

makes it easier to debug as well as avoiding crashes when something hasnā€™t gone to plan

Tried to comment out the call to Destroy and it had no effect, still crashes when the projectile impacts.

Another thing I noticed was that on line 10:

AFPSGAM415Projectile::AFPSGAM415Projectile() 

the second AFPSGAM415Projectile says that ā€œAFPSGAM415Projectile::baseMat is uninitializedā€ but this code was following exactly what was posted in our class so Im not sure why it would cause a crash on my end but not the instructorā€™s.

where do you set baseMat?

Donā€™t worry, Iā€™ve followed a lot of courses myself where I would get crashes or a different result than the instructors, usually itā€™s one tiny error that you missed ^^

Tried implementing the code you suggested and am now getting this error:

>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.MakeFile.Targets(44,5): error MSB3073: The command ""C:\Program Files\Epic Games\UE_5.4\Engine\Build\BatchFiles\Build.bat" FPSGAM415Editor Win64 Development -Project="C:***FPSGAM415.uproject" -WaitMutex -FromMsBuild -architecture=x64" exited with code 6.

baseMat was implemented in the header file:

	UPROPERTY(EditAnywhere)
		UMaterial* baseMat;

but I dont see it being mentioned anywhere else in the cpp file. The only use of it is in that ā€œauto Decalā€ statement

you need to be setting it somewhere, likely within the BP, double check youā€™ve set it in there

Im not sure I know what you mean by setting the base material.

If I go to the Projectile Blueprint, it has the default Material of the ā€œFirstPersonProjectileMaterialā€ under the Static Mesh.

The Ball Mesh we created in the cpp file does not have a slot for material despite it being an attachment.

ballMesh->SetupAttachment(CollisionComp);

So would it be beneficial to set it with something like:

ballMesh->SetupAttachment(baseMat);

and then deleting the Static Mesh that is created by default for that BP and make it use the Ball Mesh we created?

I guess the answer to that one is No. Tried adding that line and got the error ā€œargument of UMaterial is incompatible with parameter of type ā€˜USceneComponentā€™ā€

so baseMat has a UPROPERTY of EditAnywhere, which means it lives in the projectile blueprint and you can set the material there. If you go to your BP and search for baseMat, itā€™ll show up in the details panel :slight_smile: Hereā€™s what it would look like:

Screenshot 2024-09-18 095653

note you have to be clicked on ā€œselfā€ on the left, where your BP has all the components

1 Like

Yup, that was it. My Base Material there was empty. Once it was swapped over to the Splatter Material, it all worked. Thanks for your help. Now I need to go review the tape to see if I just obviously missed that step or if it wasnt shown in the instructions.

Thanks again!

Youā€™re most welcome! Trust me, itā€™s probably the most common mistake I see even the instructors making when doing these courses, at least now you know one more place to check if it happens again ^^

1 Like