Hi,
This is my first experience getting my hands dirty with coding for video games. I am in the process of creating an Item system, and so far, I am populating my Structures class (which would be static build/place-able items in the game world).
I am trying to incorporate audio to these items - specifically, generic sounds such as impact and destruction. The class does contain an audio component, but I do not want the class to contain lists or arrays of sound clips to play - it seems like squandered resources when all items use the same set of sounds anyways.
I thought of creating a static class or a bunch of static methods to handle the process - this means, there exists a general static class (i.e AudioManager) that contain all types of impact sounds. When an item needs to play a clip, it calls a static method to fetch an audio clip and proceeds to play it via the Audio Component. I am unaware if this is the go-to way to handle this problem, but nonetheless, I face some uncertainty in the implementation.
-
Where does the Audio Manager class get its audio assets from? Ideally, I will want to create an ItemDataTable row struct that houses a bunch of array for each sound category, but how do I access DataTables when I am in C++? The DataTable object is created and managed inside the editor - I am unaware of the appropriate way to fetch data from DataTables via C++.
-
Could a similar functionality be implemented using Blueprint Function Libraries - is it more recommended? Similar to the above, I am still unsure how to access blueprints from my C++ code.
I will leave my class definition and partial implementation below if that provides any helpful context - just be aware that this is my first attempt with game programming, as such, some definitions, functionalities, and properties might not seem non-intuitive or unjustified.
.HPP
UCLASS()
class PROJECTGINGER_API ABaseStructureItems : public ABaseGameItem
{
GENERATED_BODY()
UPROPERTY(EditDefaultsOnly, Category = "Base Structure Properties")
float totalHealth;
UPROPERTY(EditDefaultsOnly, Category = "Base Structure Properties")
float health;
UPROPERTY(EditDefaultsOnly, Category = "Base Structure Properties")
UStaticMeshComponent* itemStaticMesh;
UPROPERTY(EditDefaultsOnly, Category = "Base Structure Properties")
UBoxComponent* placementBox;
UPROPERTY(EditDefaultsOnly, Category = "Base Structure Properties")
UAudioComponent* itemAudio;
UPROPERTY(EditDefaultsOnly, Category = "Base Structure Properties")
UParticleSystemComponent* itemParticles;
UPROPERTY(EditDefaultsOnly, Category = "Base Structure Properties")
EPhysicalMaterials structureMaterial;
// Constructor
public:
ABaseStructureItems();
// SECTION:
// Class Main Functions
UFUNCTION(BlueprintCallable, Category = "Base Structure Functions")
void InflictDamage(float damage);
// SECTION:
// Class Events
UFUNCTION(BlueprintNativeEvent, Category = "Base Structure Event")
void OnDeath();
UFUNCTION(BlueprintNativeEvent, Category = "Base Structure Event")
void OnHit(FVector hitLocation, float damage);
// SECTION:
// Helper Functions. Functions are to be abstracted from Blueprints.
UFUNCTION()
void PlayHitSound();
UFUNCTION()
void PlayDeathSound();
UFUNCTION()
void PlaySpawnSound();
UFUNCTION()
void PlayDestroySequence();
UFUNCTION()
void PlaySpawnSequence();
};
.CPP
#include "Items/StructureItems/BaseStructureItems.h"
// Default Constructor
ABaseStructureItems::ABaseStructureItems()
{
totalHealth = 500;
health = totalHealth;
structureMaterial = EPhysicalMaterials::M_Stone;
placementBox = CreateDefaultSubobject<UBoxComponent>(TEXT("Placement Box"));
placementBox->SetBoxExtent(FVector(200.f, 200.f, 96.f));
placementBox->bDynamicObstacle = true;
RootComponent = placementBox;
itemStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Structure Mesh"));
itemStaticMesh->SetupAttachment(GetRootComponent());
// Initializes the audio system component and de-activates it by default.
itemAudio = CreateDefaultSubobject<UAudioComponent>(TEXT("Audio Component"));
itemAudio->SetupAttachment(GetRootComponent());
itemAudio->Deactivate();
// Initializes the particle system component and de-activates it by default.
itemParticles = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("Item Particles"));
itemParticles->SetupAttachment(GetRootComponent());
itemParticles->DeactivateSystem();
}
void ABaseStructureItems::InflictDamage(float damage)
{
health = FMath::Clamp((health-damage), 0.f, 20000.f);
if (health <= 0)
{
OnDeath();
}
}
void ABaseStructureItems::OnDeath_Implementation()
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Destroyed Structure!"));
Destroy();
}
void ABaseStructureItems::OnHit_Implementation(FVector hitLocation, float damage)
{
InflictDamage(damage);
// Strong Impact - Use heavy impact sounds and particles.
if(damage > 0.25*totalHealth)
{ }
// Medium Impact - Use Medium impact sounds and particles.
else if(damage > 0.05*totalHealth && damage <= 0.25*totalHealth)
{}
// Weak Impact - Use Weak impact sounds and particles.
else
{ }
}
// SECTION:
// Helper Functions. Functions are to be abstracted from Blueprints.
// FUNCTION: Play Hit Sound
// Activates the Audio components to play the provided sound clip.
// Decativates Audio component when done.
void ABaseStructureItems::PlayHitSound() {}
void ABaseStructureItems::PlayDeathSound() {}
void ABaseStructureItems::PlaySpawnSound() {}
void ABaseStructureItems::PlayDestroySequence() {}
void ABaseStructureItems::PlaySpawnSequence() {}