I have a error when I try to build my cpp code for Unreal Engine 4.26. I'm try to add to my game feature to determine surface type when I play. That why I added UDeterminSurfaceType function. The part of the code is looking like this:
SurfaceType = UPhysicalMaterial::DetermineSurfaceType(Hit.PhysMaterial.Get());
UParticleSystem* SelectedEffect = nullptr;
switch (SurfaceType)
{
case SurfaceType1:
SelectedEffect = FleshImpactEffect;
break;
case SurfaceType2:
SelectedEffect = FleshImpactEffect;
break;
default:
SelectedEffect = DefaultImpactEffect;
break;
}
if (SelectedEffect)
{
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), SelectedEffect, Hit.ImpactPoint,
Hit.ImpactNormal.Rotation());
}
I know the fact is not polished yet, I will do this later. After I added this lines and build the project, I got LNK2019 error.
Error LNK2019 unresolved external symbol "__declspec(dllimport) public: static enum
EPhysicalSurface __cdecl UPhysicalMaterial::DetermineSurfaceType(class UPhysicalMaterial const *)"
(__imp_?DetermineSurfaceType@UPhysicalMaterial@@SA?AW4EPhysicalSurface@@PEBV1@@Z) referenced in
function "public: virtual void __cdecl ASWeapon::Fire(void)" (?Fire@ASWeapon@@UEAAXXZ)
This error means, I have a method called "Fire" in my ASWeapon class header file but it doesn't exist in your SWeapon.CPP file. So, the linker creates an OBJ file for your weapon class and then when it tries to match the declarations with the implementations, it can't find the implementation and you get this lovely linker error. But I already have method "Fire" in both CPP and header file. It is created here:
public:
UFUNCTION(BlueprintCallable, Category = "Weapon")
virtual void Fire();
Here is the entire SWeapon.cpp code:
static int32 DebugWeaponsDrawing = 0;
FAutoConsoleVariableRef CVARDebugWeaponDrawing(
TEXT("COOP.DebugWeapons"),
DebugWeaponsDrawing,
TEXT("Draw Debug Lines for Weapons"),
ECVF_Cheat);
// Sets default values
ASWeapon::ASWeapon()
{
MeshComp = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MeshComp"));
RootComponent = MeshComp;
MuzzleSocketName = "MuzzleSocket";
TracerTargetName = "Target";
}
void ASWeapon::Fire()
{
// urmarirea mapei din ochii pionului pana la locatia tintei
AActor* MyOwner = GetOwner();
if (MyOwner)
{
FVector EyeLocation;
FRotator EyeRotation;
MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotation);
FVector ShotDirection = EyeRotation.Vector();
FVector TraceEnd = EyeLocation + (ShotDirection * 10000);
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(MyOwner);
QueryParams.AddIgnoredActor(this);
QueryParams.bTraceComplex = true;
// parametrul pentru particulele tintei
FVector TracerEndPoint = TraceEnd;
EPhysicalSurface SurfaceType = SurfaceType_Default;
FHitResult Hit;
if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, ECC_Visibility,
QueryParams))
{
// Blocare lovitura, cauzeaza daune
AActor* HitActor = Hit.GetActor();
UGameplayStatics::ApplyPointDamage(HitActor, 20.0f, ShotDirection, Hit, MyOwner-
>GetInstigatorController(), this, DamageType);
SurfaceType = UPhysicalMaterial::DetermineSurfaceType(Hit.PhysMaterial.Get());
UParticleSystem* SelectedEffect = nullptr;
switch (SurfaceType)
{
case SurfaceType1:
SelectedEffect = FleshImpactEffect;
break;
case SurfaceType2:
SelectedEffect = FleshImpactEffect;
break;
default:
SelectedEffect = DefaultImpactEffect;
break;
}
if (SelectedEffect)
{
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), SelectedEffect, Hit.ImpactPoint,
Hit.ImpactNormal.Rotation());
}
TracerEndPoint = Hit.ImpactPoint;
}
if (DebugWeaponsDrawing > 0)
{
DrawDebugLine(GetWorld(), EyeLocation, TraceEnd, FColor::White, false, 1.0f, 0, 1.0f);
}
PlayFireEffects(TracerEndPoint);
}
}
void ASWeapon::PlayFireEffects(FVector TraceEnd)
{
if (MuzzleEffect)
{
UGameplayStatics::SpawnEmitterAttached(MuzzleEffect, MeshComp, MuzzleSocketName);
}
if (TracerEffect)
{
FVector MuzzleLocation = MeshComp->GetSocketLocation(MuzzleSocketName);
UParticleSystemComponent* TracerComp = UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), TracerEffect, MuzzleLocation);
if (TracerComp)
{
TracerComp->SetVectorParameter(TracerTargetName, TraceEnd);
}
}
APawn* MyOwner = Cast<APawn>(GetOwner());
if (MyOwner)
{
APlayerController* PC = Cast<APlayerController>(MyOwner->GetController());
if (PC)
{
PC->ClientPlayCameraShake(FireCamShake);
}
}
}
And here is the header code:
class USkeletalMeshComponent;
class UDamageType;
class UParticleSystem;
UCLASS()
class GAME_API ASWeapon : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ASWeapon();
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
USkeletalMeshComponent* MeshComp;
void PlayFireEffects(FVector TraceEnd);
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
TSubclassOf<UDamageType> DamageType;
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
FName MuzzleSocketName;
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
FName TracerTargetName;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
UParticleSystem* MuzzleEffect;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
UParticleSystem* DefaultImpactEffect;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
UParticleSystem* FleshImpactEffect;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
UParticleSystem* TracerEffect;
UPROPERTY(EditDefaultsOnly, Category = "Weapon")
TSubclassOf<UCameraShakeBase> FireCamShake;
public:
UFUNCTION(BlueprintCallable, Category = "Weapon")
virtual void Fire();
};
The rest of the code works perfectly fine before adding the Surface Type detector. If you have any idea how to fix this I will be greatful.