Why can we not create Custom Spring Arm components? We can create almost every OTHER kind of component, why not this?

I guess my greater question is “How can I create a custom spring arm component child class that I can name and reference by class name more specifically?”, but if there is no way to do that, knowing WHY Epic decided that the only component you can’t make a custom one of should be the Spring Arm component? Like what the heck is going through their head that they seem to think their Spring Arm component is SO PERFECT that it doesn’t have ANY possibility for anyone needing to make child classes of it?

Here’s basically why I wanna know this:

In my custom camera system, I have multiple different kinds of cameras with pre-defined settings and custom functionality. Up until yesterday, the system I had in place was working perfectly (I mean technically it still is, but I can’t add the extra functionality I want to add to it. you’ll see why if you keep reading) but only assuming that the cameras were attached to an actor that ALSO already had either a mesh or spring arm also attached to them (depending on the camera type. first person style cameras require a head bone in a mesh to add to to MAKE it first person, others are different varieties of third person cameras that have different settings and functionality and need a spring arm with specific settings to get it to work just right). While this system I set up works out-of-the-box, requiring the person using it to KNOW to attach other components as well feels like it’s just asking for failure. My system already checks to make sure that all the things it needs to work are already also included, or it fails gracefully printing out a string stating what is missing. But that’s not good enough for me.

So I decided that in the event that things that are needed aren’t also included, I started adding code to create the missing things that are needed. In the case of an actor that has no skeletal mesh (or at least has no “head” in the mesh to attach first person cameras to), I simply said “ok I’ll make it a very close-by third person camera, and add a spring arm.” (I can’t exactly add a mesh in case their mesh is just different). This worked fine because in the case of first person cameras there’d be no spring arm needed so this 1 spring arm created in this way is fine. Then I moved onto my third person follow camera, and things started to break. In the case of not having a spring arm at all, I could just add one and it’d be fine right? Well what if they had a spring arm for some other purpose? Well then I just get all components of spring arm class and create an array of them, but then there was no way in the code to know ahead of time how many spring arms they already have or what they’re for, so I couldn’t go “is there a spring arm for x purpose?” and branch off cause there’d BE spring arms but maybe not a free one. OR maybe there WOULD be one meant just for that, but if my code didn’t know ahead of time, it would make a new one. Suddenly I needed to get specific spring arms attached, without knowing ahead of time about some future-available component. I can’t have it go owner → get spring arm by name, because there is no such node. And I can’t just add a spring arm and drag off the reference from the owner because, again, the character could possibly not have a spring arm, and then the code won’t compile or work. Sure I could get a list of all spring arms, assume there’s NEVER one available, make a new one, and add it onto the end of the array, thus increasing the array length by 1 and, having stored the size of the array ahead of time, knowing precisely what array index is my new spring arm created in blueprints for that camera, thus ignoring any and all spring arms made by the user. But that too has it’s problems, in that I can’t see all the values that will be preset when that spring arm is created, nor can I expect the user to see them either for them to modify to THEIR needs because that spring arm does not exist within the editor, only within the memory of the game being run.

TLDR: I could not specifically determine the existence of a spring arm need for my cameras to work without adding the spring arms myself and REQUIRING the end user to start by using MY custom character class and building off of that, or without giving them some heavy “How to Use” instructions telling them they MUST add for each camera type a Spring Arm to the actor that’s getting the cameras in question and then going into the code and manually getting the reference to each spring arm for each camera to attach themselves to.

Shorter TLDR: I can’t assume the end user of my system will know what they’re doing, but I can’t make it as Idiot-Proof as I’d like to without having a way to specifically create Custom Spring Arm Components that I can call by class name (as there’s apparently no other way to reference them except by Get Class and Is Child Of nodes to get a True or False response).

My first thought is…Why not just use the component tag which is available on the spring arm. Give each spring arm a tag depending on its intended role and if there is no spring arm with a particular tag then that role is not available for that particular character.

@KratonHaddock You can make a custom spring arm with c++ and embed the needed logic there.

I would have to make it from scratch then. If I knew all the inner workings of the spring arms, I could do that. But to get that I’d have to spend way too much time with the spring arms, it would not really be worth the research time.

Custom spring arm with blueprint implementable CustomInit function to call on begin play.
Is blueprint spawnable.
Now you can make custom blueprint spring arms with their own function calls on load.

Header file

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/SpringArmComponent.h"
#include "CustomSpringArmComponent.generated.h"

/**
 * 
 */
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent))
class REPLACE_WITH_YOUR_PROJECT_API UCustomSpringArmComponent : public USpringArmComponent
{
	GENERATED_BODY()
public:
		UCustomSpringArmComponent(const FObjectInitializer& ObjectInitializer);
	
		virtual void BeginPlay();
		
		UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Init")
		void CustomInit();
};

Cpp file

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

#include "CustomSpringArmComponent.h"

UCustomSpringArmComponent::UCustomSpringArmComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer) {	
}

void UCustomSpringArmComponent::BeginPlay()
{
	Super::BeginPlay();
	CustomInit();
}
1 Like

Thanks for this, but I realized something when discussing the issue with my spouse…

I’ve been looking at this problem too long. I couldn’t see the forest for the trees, so to speak.

My main issue has been needing to be able to look for specific child class of spring arm to ensure that they have also attached the spring arms that ALREADY have the settings the cameras need for them to work perfectly (without having to modify things like transform data etc themselves), only because I wanted it to be plug and play with no work required of the end user. And that was an issue because I didn’t want to assume they did or didn’t want to set up their own and thus overwrite what they did with my “setup” code through blueprints…

I was explaining my issue to my spouse, who then said “why not, before your setup code, put a bool and a branch and name the bool ‘setup for me’ or something like that, and if they click the checkbox it tries to set up for them, and if they don’t, it does nothing and expects them to know what they’re doing?” and I went… “omg. that’s such a simple solution.”

So instead of trying to “find out” through the blueprints if the end-user set up their own spring arms etc to connect the cameras to, I’m just going let the end user select if they want me to try and set it up for them, and then have it run my create spring arms etc code.

Such a simple solution, I don’t know why I didn’t think of that.

Thanks for the suggestion, though I found a much simpler solution to my overall problem.

Basically I’m just going to add a bool and a branch and call the bool “TryToSetupForMe” and put all my setup code after that. So if the end user wants to set up their own spring arms etc for and connect the cameras where they should go manually, they can. If they click that bool checkbox, I’ll assume they’ve done nothing and I’ll have it do all the work through my code.