SplineComponent changes not triggering OnConstruction() (vs Construction Script)

Hello!

I have seen threads discussing the C++ “equivalent” (at least a close equivalent) of a Blueprint (Actor’s) Construction Script (eg. equivalent of construction script in c++ - C++ Gameplay Programming - Unreal Engine Forums ). These suggested the class’ constructor (it only gets executed once, not when I change something on the actor in the editor) and OnConstructed() as the “replacement”, which seems to be the closest I got to something that runs whenever my actor changes in the editor, but it seems I’ve found a case where they aren’t working alike.

So here’s what I want to do: I want to run a function each time my (root) SplineComponent changes (even in the editor). If I make a Blueprint Actor, the Construction Script will run whenever I do something with the SplineComponent (it triggers multiple times while I’m moving a control point, it runs when I create a new control point or when I remove a control point). The closest I can get to it in C++ is by implementing OnConstruction(), which sadly doesn’t work in all the mentioned cases:

  • It only runs once when moving a control point: at the end (this is not a huge problem for me)
  • It **does not run at all when I delete a control point (this is a huge problem for me as I can’t keep track of deleted points)

Since I found no way to listen for my SplineComponent’s changes, I ended up with this solution (trying to implement something that runs like the Construction Script), but as you can see, it still doesn’t work as intended. I’d like to avoid ticking, so I ignored that, and I would also like to do this in C++. I tried these as well:

  • **PostEditChangeChainProperty **or **PostEditChangeProperty **are not called when I make changes to the spline in the editor view (they do when I change something on the Details panel, but I can’t really edit my spline from there)
  • I found no extensible (virtual) method on **SplineComponent **that would allow me to fire a delegate that I can listen to in my Actor: *UpdateSpline *is not virtual (I’d try to fire a delegate from there) and **PostEditChangeProperty **and its sibling are again not fired when the spline is edited from the editor view.
  • I’ve looked through AActor’s lifecycle calls (reference: https://docs.unrealengine.com/en-US/…tor/index.html ) but I found no other point worthy of investigating (I tried PreRegisterAllComponents, PostActorCreated and PreInitializeComponents none seem to work )

I’d like to ask if any of you know of something that I could utilize (without changing the engine’s source code or getting my actor(s) to tick) to listen for a SplineComponent’s changes? The spline likely won’t change in runtime, but I would like to run a function whenever it does, at least in the editor. Is there something trivial that I’m missing?

I attached a small component of a spline actor that demonstrates my issue (when I delete a control point, the OnConstructed() method doesn’t get called, which in this case would print a log message, in all the other cases it prints the string “Hello!”).

Nevermind, it seems I just didn’t look hard enough, the AnswerHub had just the same question, and was answered! For those finding my thread instead of the AH post, here are all the details (courtesy of AllJonasNeeds).

TLDR. Implement/override PostEditMove(), which runs whenever the spline component changes (even while moving the component). It also receives a boolean parameter which tells if movement has ended (so you can limit your calculations to only run once you’ve finished dragging the spline). Original AnswerHub post and example implementation: https://answers.unrealengine.com/que…8749/view.html

Code version. Here’s what had to be done:



// MyActor.h
public:
#if WITH_EDITOR
    virtual void PostEditMove(bool bFinished) override;
#endif // WITH_EDITOR


The following implementation will cause OnConstruction() to be called whenever the component changes, just like I experienced with Blueprint Actors.



// MyActor.cpp
#if WITH_EDITOR
void AMyActor::PostEditMove(bool bFinished)
{
    Super::PostEditMove(bFinished);
    if (ReregisterComponentsWhenModified())
    {
        OnConstruction(GetActorTransform());
    }
}
#endif // WITH_EDITOR


Please not that deleting control points causes a call with bFinished == false!

Hello! Sorry, I’m new at scripting and I have this same problem. Where exactly do I implement these lines of codes? can you explain that please?

If you use Blueprints, there is no need to implement anything (so no C++ required): you have to do your things in the Construction Script (there is a separate tab for it in the blueprint editor). The construction script will be executed whenever you move your actor or change your spline (actually I think there is a setting that controls this, but it’s enabled by default). If you are writing a C++ actor and you have a Spline component in it, then you need to paste the first snippet in your header (“.h” file extension) file and then implement the “PostEditMove” function (that you just declared in your header file) in your “.cpp” file. The template upon which you can expand:



#if WITH_EDITOR
void AMyActor::PostEditMove(bool bFinished)
{
  Super::PostEditMove(bFinished);
  if (ReregisterComponentsWhenModified())
  {
    // do your own logic here
  }
}
#endif // WITH_EDITOR


NOTE. Replace “AMyActor” with your actual class name.

TLDR**.** If you use Blueprints, you don’t have to create a C++ class, just put your logic in the construction script and it will be executed whenever you change your spline. If you do, you have to implement the PostEditMove function (since it’s editor only, you have to surround it with the “#if WITH_EDITOR” macro, otherwise it won’t compile when you’re shipping your game as far as I know).

A simpler solution would be setting

bRunConstructionScriptOnDrag = true;

in C++ constructor