x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Office Holiday

Epic Games' offices will be on holiday from June 22nd to July 7th. During this period support will be limited. Our offices will reopen on Monday, July 8th. 

Play Different Particle Effect on AnimNotify Timed Particle Effect

So I have a timed particle effect in my animation. It works great. However, I want to switch it out for a different particle effect when the character has a certain weapon. Rather than copying/pasting the same animation and switching out the particle effect, is there a way I can switch out the particle effect in my anim bp or in C++ ? (either one works for me). I'm sure this is doable, but I just can't find anything out there on it.

Thank you!

Product Version: UE 4.15
Tags:
more ▼

asked Feb 09 '18 at 02:46 PM in Blueprint Scripting

avatar image

FatBalloon
20 2 4 7

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

Hopefully this helps someone! I ended up discovering the answer to this question. I first decided to override the UAnimNotifyState_TimedParticleEffect class. However, there were some compile issues with that. Subsequently, I created a Custom_TimedNotify class and copied the exact same code from UAnimNotifyState_TimedParticleEffect except for the places that were not compiling. IT was just debug stuff that wasn't compiling well. Specifically this location of code:

 #if WITH_EDITORONLY_DATA
     // The following arrays are used to handle property changes during a state. Because we can't
     // store any stateful data here we can't know which emitter is ours. The best metric we have
     // is an emitter on our Mesh Component with the same template and socket name we have defined.
     // Because these can change at any time we need to track previous versions when we are in an
     // editor build. Refactor when stateful data is possible, tracking our component instead.
     UPROPERTY(transient)
     TArray<UParticleSystem*> PreviousPSTemplates;
 
     UPROPERTY(transient)
     TArray<FName> PreviousSocketNames;
     
 #endif


No matter. I ended up creating my own class and then adding my own code into the notify begin area.

// Fill out your copyright notice in the Description page of Project Settings.

 #include "ShooterGame.h"
 #include "Custom_TimedNotify.h"
 #include "ShooterCharacter.h"
 #include "ShooterWeapon.h"
 #include "Components/SkeletalMeshComponent.h"
 #include "Particles/ParticleSystemComponent.h"
 #include "Kismet/GameplayStatics.h"
 
 UCustom_TimedNotify::UCustom_TimedNotify(const FObjectInitializer& ObjectInitializer)
     : Super(ObjectInitializer)
 {
     PSTemplate = nullptr;
     LocationOffset.Set(0.0f, 0.0f, 0.0f);
     RotationOffset = FRotator(0.0f, 0.0f, 0.0f);
 }
 
 
 void UCustom_TimedNotify::ClearEffects()
 {
     PSTemplate = NULL;
     SocketName = "";
 }
 
 void UCustom_TimedNotify::SetParticleEffect(UParticleSystem* particle)
 {
     PSTemplate = particle;
 }
 
 void UCustom_TimedNotify::SetAttachPoint(FName socket)
 {
     SocketName = socket;
 }
 
 
 void UCustom_TimedNotify::NotifyBegin(USkeletalMeshComponent * MeshComp, class UAnimSequenceBase * Animation, float TotalDuration)
 {
    /* Start of custom code to grab the right weapon effects and spawn them in the proper location */
     AShooterCharacter* MyOwner = Cast<AShooterCharacter>(MeshComp->GetOwner());
     if (MyOwner)
     {
         AShooterWeapon* theweapon = Cast<AShooterWeapon>(MyOwner->GetWeapon());
         if (theweapon)
         {
             SocketName = theweapon->GetMuzzleAttachPoint();
             PSTemplate = theweapon->GetMuzzleFX();
         }
     }
 
     /* End of custom code to spawn my own effects in the proper location */

         // Only spawn if we've got valid params
         if (ValidateParameters(MeshComp))
         {
             UParticleSystemComponent* NewComponent = UGameplayStatics::SpawnEmitterAttached(PSTemplate, MeshComp, SocketName, LocationOffset, RotationOffset);
         }
 
         Received_NotifyBegin(MeshComp, Animation, TotalDuration);
     
 
     
 }
 
 void UCustom_TimedNotify::NotifyTick(USkeletalMeshComponent * MeshComp, class UAnimSequenceBase * Animation, float FrameDeltaTime)
 {
     Received_NotifyTick(MeshComp, Animation, FrameDeltaTime);
 }
 
 void UCustom_TimedNotify::NotifyEnd(USkeletalMeshComponent * MeshComp, class UAnimSequenceBase * Animation)
 {
     TArray<USceneComponent*> Children;
     MeshComp->GetChildrenComponents(false, Children);
 
     for (USceneComponent* Component : Children)
     {
         if (UParticleSystemComponent* ParticleComponent = Cast<UParticleSystemComponent>(Component))
         {
             bool bSocketMatch = ParticleComponent->GetAttachSocketName() == SocketName;
             bool bTemplateMatch = ParticleComponent->Template == PSTemplate;
 
             if (bSocketMatch && bTemplateMatch && !ParticleComponent->bWasDeactivated)
             {
                 // Either destroy the component or deactivate it to have it's active particles finish.
                 // The component will auto destroy once all particle are gone.
                 if (bDestroyAtEnd)
                 {
                     ParticleComponent->DestroyComponent();
                 }
                 else
                 {
                     ParticleComponent->bAutoDestroy = true;
                     ParticleComponent->DeactivateSystem();
                 }
                 // Removed a component, no need to continue
                 break;
             }
         }
     }
 
     Received_NotifyEnd(MeshComp, Animation);
 }
 
 bool UCustom_TimedNotify::ValidateParameters(USkeletalMeshComponent* MeshComp)
 {
     bool bValid = true;
 
     if (!PSTemplate)
     {
         bValid = false;
     }
     else if (!MeshComp->DoesSocketExist(SocketName) && MeshComp->GetBoneIndex(SocketName) == INDEX_NONE)
     {
         bValid = false;
     }
 
     return bValid;
 }
 
 FString UCustom_TimedNotify::GetNotifyName_Implementation() const
 {
     if (PSTemplate)
     {
         return PSTemplate->GetName();
     }
 
     return UAnimNotifyState::GetNotifyName_Implementation();
 }


Then voila, you get your own custom notify class when editing your animation!

alt text

customnotify.png (30.9 kB)
more ▼

answered Feb 22 '18 at 02:57 AM

avatar image

FatBalloon
20 2 4 7

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question