Download

Best practice for adding to a SceneComponent child class (or something proximal)?

I’m trying to create a component which I can attach to any arbitrary actor which will act as its “targetable center”. By placing this component on any actor in the world (or actor class) I can mark that actor as an object which can be targeted, by doing an overlap check for actors and then checking for the presence of this TargetComponent, and then use its world transform to create a vector pointing to the exact spot I am targeting. This all seems very straightforward.

This is perfectly viable, but the issue I’m having is that I can’t actually define this child class of a SceneComponent to be anything but, effectively, a blank SceneComponent. I can’t, for example, give it a collision capsule or a billboard sprite or something to make it easy to identify where it exists on an actor. I can’t define some inner or outer bounds for it and easily see those bounds on an actor. etc.

I tried to create a child component based on Sphere Collision, but the engine won’t allow this (at least not without doing extra exposing work in BP). I know I could just create basic Sphere Collision components on actors, and it’s true that those would do what I want, but the issue is I can’t be sure, when I do some check and gather up an array of Sphere Component references, that all of these are valid target components. Any place sphere collision is used would return a valid response, even if it was just, you know, spherical collision, and not a marker for this kind of check.

This shouldn’t be especially difficult in theory, because it’s how a character is fundamentally built; it has some component (its capsule collider) which is not rendered in game but which is accessible and provides some sort of “root” for that object in the world. It should be possible to create other objects of this kind and add them as components to actors, shouldn’t it? What am I missing?

Project settings → Engine → Collision
Create a new “Trace Channel”… e.g. Targetable, set it’s default response to Ignore.

Add your Sphere Collision, set collision preset to custom. Collision responses: Ignore all, Overlap Targetable

Trace By Channel

I appreciate that, it does actually solve the problem for the specific case I outlined, but I’m talking more generally. Is there no way to specify some collision-based thing with some kind of internal logic to act as a component on an actor? At least without including a rendered mesh (since you can always inherit from Static Mesh Component if you have something you want to render)? In the case of doing nothing but detecting an object in the world using a collision channel is fine, but what if I had wanted to call a function ON that component?

You can create a custom class that has the collision for trace, custom functions/events etc. Spawn the class (begin play/construct) in your targetable actor, attach it to a specified component.

Trace for the channel, Get hit actor -> call function.

So what you’re saying is it can’t actually be done using a component, it has to be an attached (or child) actor in its own right?

Correct. You cannot add components to an Actor Component class. AC’s are logic/data only.

I’m assuming your post is at its core about not having to duplicate code/logic etc for multiple different classes. If so, then creating an Actor Class with your components etc would be the approach to take.

I can whip up an example later this evening if you’d like.

Well, not entirely. e.g. a StaticMeshComponent is a static mesh. You can add logic to it, but it’s still a static mesh. You can actually add collision components as components, too, you just can’t create classes that inherit from them.

In my specific case, I think I’m going to go with a general-purpose data component and just also use collider components with a special channel as you mentioned.

I was referring specifically to the Actor Component class.

@RhythmScript
What exactly is the end goal mechanic?

The end goal is solved; I needed a component which would serve as a way to mark objects in the game world as “taking damage from the player” (not using the UE4 native Damage system because what I’m doing is far more convoluted and requires from-the-ground-up work) and there are many instances where I want to “find targets” for actions using some sort of world check which looks for all valid objects containing one of these components.

My desire to have a Scene-based component was driven by future-proofing weakpoint logic; large actors may have multiple “areas of attack”; if I am looking for a target for a melee swing, and the character is so tall I can run between his legs, swinging at his center of mass will cause me to swing at nothing. So I need to specify, sometimes, multiple locations on a single actor, which may or may not take damage independently, and the ability to trace for components would allow me to handily wrap up the “what am I aiming at” logic inside the same component used for all the logic tied to damage and receiving attacks.

Since it’s not really something that can be handled natively, I’ll just use a dedicated collision channel to find these colliders, then check if the colliders themselves belong to a parent actor which implements a Damage Taking Component, and if so, I can call functions on that component while targeting the colliders. Not quite as clean but it gets the job done.

I’ve attempted to avoid using Actor Components/Child Actors because I’ve heard horror stories (granted this was many versions of UE4 back, I’ve been using it since 4.2, but this stuff sticks with you) about issues with cooking due to cyclic dependencies when there are a lot of Actor/Child Actor communications, so I wanted to use component-based logic.