Download

AddActorWorldRotation isn't working with my Hierarchy

I have a Pickup class that needs a StaticMeshComponent.

I can’t set it to be the root because otherwise I wouldn’t be able to scale, move and rotate it in the Blueprint child class.

So I read somewhere that in order to edit the Mesh, I need to make a **USceneComponent **as root and then attach the StaticMeshComp to it



USceneComponent* SceneComp = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComp"));
PickupMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PickupMesh"));

RootComponent = SceneComp;
PickupMesh->SetupAttachment(SceneComp);


So this is the Hierarchy

555.jpg

Now, the problem

The problem is that **AddActorWorldRotation() **doesn’t seem to work in the Tick() function



void APickup::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    FRotator rotation = FRotator(0.f, 1.f, 0.f);
    AddActorWorldRotation(rotation);
}


The StaticMesh in-game is completely motionless.

The only way I found is to write



PickupMesh->AddWorldRotation(rotation);


But this is not what I want!

Together with the StaticMesh, in the future I could add some other components that need to rotate together!

So I need the whole Actor to rotate, not just some components.

What am I doing wrong? Thank you in advance.

Up.

I tried to force the Mobility of the Components



RootComponent = SceneComp;

RootComponent->SetMobility(EComponentMobility::Movable);
PickupMesh->SetMobility(EComponentMobility::Movable);

PickupMesh->SetupAttachment(SceneComp);


But nothing changes.

How can I solve this issue?

Do you have this:


PrimaryActorTick.bCanEverTick = true;

Yes, I do!

Up! Is this so complicated?

[USER=“4893”]Tim C[/USER] is this an engine bug?

Hi gedamial,

What Engine version are you using? I tried to reproduce this in 4.18.0, and the actor appeared to be rotating normally for me.

Tim

My Engine version is 4.17.2

You are saying “I have a Pickup class that needs a StaticMeshComponent.”. But what is the parent class of this Pickup class?

It’s AActor

What does your Pickup class represent in the game exactly? Are you sure it is wise to derive it from AActor? Wouldn’t AStaticMeshActor be more appropriate? Or maybe an actor component? It all depends what the role of this pickup class is.

I need a spawnable Actor which plays the role of a classic pickup in videogames… like in Unreal.

But **what I really need **is a way to give my Actor a StaticMesh (3D model) through C++ **AND BE ABLE TO EDIT IT’S PROPERTIES **(scale, rotate) through the Blueprint-child class

then why not making APickup a subclass of AStaticMeshActor?

I’ll try later.

What if I want to derive from AActor and still want to achieve what I described earlier?

Hrm, so it seems like the forums no longer automatically subscribe me to threads I have commented on. Sorry for missing your response to my question.

I recreated my test project in 4.17.2, and my actor appears to be rotating there as well. This is what I have in the code class, which I believe matches what you have set up:


#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()
class TESTROTATION1_API AMyActor : public AActor
{
    GENERATED_BODY()

public:    
    // Sets default values for this actor's properties
    AMyActor();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public:    
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = TestCat)
    UStaticMeshComponent* PickupMesh;
};

------------------------------------------------

#include "MyActor.h"

// Sets default values
AMyActor::AMyActor()
{
     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    USceneComponent* SceneComp = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComp"));
    PickupMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PickupMesh"));

    RootComponent = SceneComp;
    PickupMesh->SetupAttachment(SceneComp);
}

// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
    Super::BeginPlay();

}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    FRotator Rotation = FRotator(0.f, 1.f, 0.f);
    AddActorWorldRotation(Rotation);
}

When I create a Blueprint from that class, set a static mesh, then place it in the level, the actor appears to rotate when I start PIE. Is there anything that I have different from how you are setting up your class and Blueprint?

Tim

Absolutely no problem :slight_smile:

The code is pretty the same, yes:

Pickup.h



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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Pickup.generated.h"

UCLASS()
class MIKETEST_API APickup : public AActor
{
    GENERATED_BODY()    

    UFUNCTION()
    void OnPickup(AActor* OverlappedActor, AActor* OtherActor);

    USceneComponent* SceneComp;

    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Pickup", meta = (AllowPrivateAccess = "true"))
    UStaticMeshComponent* PickupMesh;

public:        
    APickup(const class FObjectInitializer &ObjectInitializer);

protected:
    virtual void BeginPlay() override;

    const float RotationSpeed = 2.0f;

public:    
    virtual void Tick(float DeltaTime) override;    
};


Pickup.cpp



#include "Pickup.h"
#include "Engine.h"
#include "MyCharacter.h"

APickup::APickup(const class FObjectInitializer &ObjectInitializer) : Super(ObjectInitializer)
{
    PrimaryActorTick.bCanEverTick = true;

    OnActorBeginOverlap.AddDynamic(this, &APickup::OnPickup);    

    SceneComp = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComp"));

    // Setup the pickup mesh
    PickupMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PickupMesh"));
    PickupMesh->bCastStaticShadow = false;
    PickupMesh->CastShadow = false;
    PickupMesh->bCastDynamicShadow = false;
    PickupMesh->SetSimulatePhysics(true);

    RootComponent = SceneComp;

    RootComponent->SetMobility(EComponentMobility::Movable);
    PickupMesh->SetMobility(EComponentMobility::Movable);

    PickupMesh->SetupAttachment(SceneComp);



    // Default properties
    isActive = true;
    RespawnDelay = 3.0f;
}

void APickup::BeginPlay()
{
    Super::BeginPlay();
}

void APickup::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    FRotator rotation = FRotator(0.f, RotationSpeed, 0.f);
    AddActorWorldRotation(rotation);
}

void APickup::OnPickup(AActor* OverlappedActor, AActor* OtherActor)
{

}


Hi gedamial,

Thank you for the additional code. It looks like the issue is happening with this line:


PickupMesh->SetSimulatePhysics(true);

With physics set to simulate on the static mesh component, it essentially detaches that component from its parent component. If you simulate the project, you can see that the root scene component is rotating as expected, but the static mesh is not because it has been separated from the root component. As far as the Blueprint is concerned they are still connected, but in terms of movement they are each doing their own thing.

If you need to have the entire actor, and all of its components, rotate as a single entity, then you won’t be able to turn on Simulate Physics. If you need the static mesh to simulate physics, then you will need to make sure to rotate that component in sync with the actor itself.

Tim

Thank you! I set it to false and it seems to work as intended!

In the meantime, I had installed UE4.18 and uninstalled UE4.17.2… only to come across another beautiful bug :smiley:

This Engine knows how to surprise me everytime… in a negative sense