Struggling with mouseover events

I’m having a lot of frustration with getting mouseover events working :-(. Been struggling with this for days.

I have two types of pawns. One has a static mesh component for a root component, and here, I can use either the BeginMouseOver event or the NotifyActorBeginCursorOver() method and it works exactly as I would expect. “Hey, great - that was easy!”, thought I :D. But then:

The other pawn has a UPoseableMeshComponent for a root, and none of the mouseover events are working at all, even with all the pre-reqs I know of (ticks enabled, etc) set up. In fact, if I change the object to a SkeletalMeshComponent, then it works! Apparently just Poseable is a problem, but I kind of need that because I need to control the bones.

Ok, so, onto a backup plan. I figure I will attach a UCapsuleComponent under the Poseable, and use that to detect mouseovers. It isn’t ideal, because it doesn’t fit the model as well. It does provide the mouseover events, BUT, if I allocate it like this in BeginPlay():



      auto* shape  = NewObject<UCapsuleComponent>(**GetRootComponent()**);
      //set up capsule radius/halfheight here
      shape->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
      shape->SetCollisionProfileName(TEXT("PhysicsActor"));
      shape->SetMobility(EComponentMobility::Movable);
      shape->SetAbsolute(false, false, false);
      shape->SetRelativeLocation(loc);
      shape->RegisterComponent();

Then it does not follow my main object, so the mouseover events are always in the same absolute world location. I thought SetAbsolute(false) would address that, but it doesn’t. So this is bad, because my object can move.

It turns out that is because for some reason, it doesn’t attach itself to the root component in NewObject, though I have passed that into NewObject. If I attempt to force this by calling AttachTo(GetRootComponent()), then I get crashes in the engine inside of USceneComponent::IsAttachedTo().

So at all turns I am blocked at getting mouseover events on my pawn. I’m not sure what to do.

I can understand that mouseovers might not work on poseable meshes, though I haven’t found that documented anywhere. (Are they supposed to?) Mesh-mousevers would be ideal, but if I can’t have them, at least I have to be able to get this collision-shape approach to work, meaning it has to be relative to my pawn’s position.

Anyone know what I’m doing wrong?

I tried giving up on runtime creation and instead creating the capsule components in a pawn constructor, and attaching them there. I really want them to be dynamic, but I figured I’d try to get a simpler thing working first.

But that doesn’t work either. After calling comp->AttachTo(GetRootComponent()), the AttachParent is still null. After some debugging with GDB, the reason seems to be that the root component is a “Template” component, and the capsule is not. I have no idea why, because I’m creating them in the very same way as far as I can see: both with CreateDefaultSubObject like so:


   RootComponent = CreateDefaultSubobject<UPoseableMeshComponent>(TEXT("Mesh"));

   auto* shape = CreateDefaultSubobject<UBoxComponent>(TEXT("Collision.Box"));

   shape->AttachTo(GetRootComponent());

That leaves the box component NOT attached to the root!

It seems that the engine really, really does not want me attaching a collision mesh to my objects.

Seems like it shouldn’t be that hard :frowning:

Edit I also tried using NewObject instead of CreateDefaultSubObject, and that behaves the same way.

I notice that you aren’t using ObjectInitializer. And you certainly will crash if you try spawning object components outside of the constructor. Code should look something like this (from memory, typing on phone)

.h


MyClass(const FObjectInitializer& ObjectInitializer);

.cpp


MyClass::MyClass(const FObjectInitializer& ObjectInitializer)
 : Super(ObjectInitializer)
{
RootComponent  = ObjectInitializer.CreateDefaultSubobject<UArrowComponent>(this, TEXT("Arrow"));

auto* cap = ObjectInitializer.CreateDefaultSubobject<UCapsuleComponent>(this, TEXT("Capsule"));
cap.AttachParent = RootComponent; 
}  

You might find that relying on a specific root component type is problematic in many cases. You can still add dynamic events to sub components.

Thanks a lot hyperdr1ve, I will try that this evening when I have time and see if it makes a difference.

I was able to finally come up with a solution that involved using the Rename() method, which allows you to re-parent an object, but I felt like it must not be the “right” way to go about it, given how difficult it was to figure out.