Fairly new to Unreal C++, though ive learnt a lot recently
im trying to implement ragdoll physics on death but im a little confused as to how i should go about doing that.
Ive got my code here:
if (Health <= 0.0f && !IsDead)
{
// Dead
IsDead = true;
GetMovementComponent()->StopMovementImmediately();
GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
DetachFromControllerPendingDestroy();
SetLifeSpan(10.0f);
}
not exactly sure how to implement “ragdolling”.
I tried SetSimulatePhysics(true) but that didnt really seem to work.
Ah yeah ive seen that, i followed the Udemy Course but im now trying to expand on it with my own features.
In the course we created a Delegate and used that to create a custom even when taking damage, so im trying to implement the above method with that delegate but its proving to be quite difficult
Depending on how your delegate works, whenever u take damage and the character run out of healt, u can call the Die method.
For a more complex ragdoll example, u can checkout github unreal tournament source code which is sometime complex but a very good learning source (see UTCharacter::StartRagdoll())
Can u show example of your delegate and how u use it?
I tend to write pretty much my entire game in C++ but use native/blueprint events to be able to implement and/or override events in blueprint, which might be usefull for prototyping/quick testing and allowing modding later on. There are only few places where im using delegates, but its been almost 6 month now i worked on the game, so it’s all a bit rusty
//This is my HealthComponent.h file
DECLARE_DYNAMIC_MULTICAST_DELEGATE_SixParams(FOnHealthChangedSignature, UTPSHealthComponent*, OwningHealthComp, float, Health,
float, HealthDelta, const class UDamageType*, DamageType, class AController*, InstigatedBy, AActor*, DamageCauser);
UCLASS( ClassGroup=(TPS), meta=(BlueprintSpawnableComponent) )
class TP_SHOOTER_API UTPSHealthComponent : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UTPSHealthComponent();
protected:
// Called when the game starts
virtual void BeginPlay() override;
UPROPERTY(BlueprintReadOnly, Category = "HealthComponent")
float Health;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HealthComponent")
float DefaultHealth;
UFUNCTION()
void HandleTakeAnyDamage(AActor* DamagedActor, float Damage, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser);
public:
UPROPERTY(BlueprintAssignable, Category = "Events")
FOnHealthChangedSignature OnHealthChanged;
};
// The HealthComponent.cpp method
void UTPSHealthComponent::HandleTakeAnyDamage(AActor* DamagedActor, float Damage, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser)
{
if (Damage <= 0.0f) {return;}
Health = FMath::Clamp(Health - Damage, 0.0f, DefaultHealth);
OnHealthChanged.Broadcast(this, Health, Damage, DamageType, InstigatedBy, DamageCauser);
}
// This is the method in my Character.cpp file that handles damage, enemies use the same health component.
void ATPSCharacter::OnHealthChanged(UTPSHealthComponent* OwningHealthComp, float Health, float HealthDelta, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser)
{
if (Health <= 0.0f && !IsDead)
{
// Dead
IsDead = true;
GetMovementComponent()->StopMovementImmediately();
GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
DetachFromControllerPendingDestroy();
SetLifeSpan(10.0f);
}
}
I tried the second method, adding an extra delegate, but cant seem to get it to work.
Ive also tries the first method but for that i would still need access to FDamageEvent const& DamageEvent, wouldnt i?
I just need to be able to access FDamageEvent const& DamageEvent so i can use the ImpulseAtLocation and use the bone name.
U can change your existing delegate by adding the DamageEvent parameter.
But creating a new delegate should also work. Can u post the code u tried and does not work?
If u changed the delegate, did u also change the function bound to the delegate to add the extra parameter?
I think the main problem is the OnTakeAnyDamage delegate which comes from AActor, but does not contain the DamageEvent parameter, so even when u extend your OnHealthChanged delegate, u have no access to the DamageEvent at all.
What u can do is remove the OnTakeAnyDamage delegate from the HealthComponent BeginPlay, override the TakeDamage on your character and any other actor that have a health component and inside this method, call your TakeDamage method on the health component.
yes, that seems correct, just make sure if u change the delegate that all functions bound to the delegate also get the extra parameter and your health component include the parameter when calling the callback