x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Character class spawns multiple actors with different behavior

This has me baffled. I had this working in blueprints but decided I wanted this core structure in C++, but I'm experiencing some very weird behavior. Basic principal is this: I have a Character class called SuspectCharacter (that will not be human controlled) that has a basic skeletal mesh. In the editor, I added two sockets: LeftEyeSocket and RightEyeSocket. I have another class called DynamicEye that contains some code in the overridden Tick function to calculate a rotation to look at the human character's head, so the eyes always look at the player 0 as he/she runs around. In my SuspectCharacter class, I create two DynamicEyes and attach them to the LeftEyeSocket and RightEyeSocket. Here is my code:

Not sure if they DynamicEye code is important, but here it is for reference:

 ADynamicEye::ADynamicEye(const class FPostConstructInitializeProperties& PCIP)
     : Super(PCIP)
 {
     this->SetActorTickEnabled(true);
     PrimaryActorTick.bCanEverTick = true;
 
     SceneComponent = PCIP.CreateDefaultSubobject<USceneComponent>(this, TEXT("SceneComp"));
     RootComponent = SceneComponent;
 
     MeshComponent = PCIP.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("MeshComp"));
     MeshComponent->AttachParent = RootComponent;
     
     static ConstructorHelpers::FObjectFinder<UStaticMesh> EyeMesh(TEXT("StaticMesh'/Game/Eye/cone.Cone'"));
     
     MeshComponent->SetStaticMesh(EyeMesh.Object);
     MeshComponent->SetRelativeScale3D(FVector(2.0f, 2.0f, 2.0f));
 }
 
 void ADynamicEye::Tick(float DeltaSeconds) {
     Super::Tick(DeltaSeconds);
 
         // Get the location of the human player's head
         const FVector HeadLocation = Cast<AFPSCharacter>(UGameplayStatics::GetPlayerPawn(this, 0))->Mesh->GetBoneLocation("head");
         
         // Get the location of this eye instance
         FVector EyeLocation = MeshComponent->GetComponentLocation();
 
         // Calculate the difference in the two vectors
         FVector Forward = (HeadLocation - EyeLocation);
 
         // Make rotation matrix from x-axis.  this means the Y and Z axis will rotate around X
         FRotator EyeRotation = FRotationMatrix::MakeFromX(Forward).Rotator();
         
         // Rotate this eye relative to the socket it's in
         MeshComponent->SetRelativeRotation(EyeRotation, true);
 }

And here is my SuspectCharacter class:

 ASuspectCharacter::ASuspectCharacter(const class FPostConstructInitializeProperties& PCIP)
     : Super(PCIP)
 {
     static ConstructorHelpers::FObjectFinder<USkeletalMesh> SkelMeshOb_AW1(TEXT("SkeletalMesh'/Game/GenericMale.GenericMale'"));
     Mesh->SetSkeletalMesh(SkelMeshOb_AW1.Object);
     Mesh->SetRelativeTransform(FTransform(FVector(0, 0, -90.0f)));
     
     UWorld* const World = GetWorld();
     if (World) {
         FActorSpawnParameters SpawnParams;
         SpawnParams.Owner = this;
         SpawnParams.Instigator = Instigator;
         RightEye = World->SpawnActor<ADynamicEye>(Mesh->GetSocketLocation("RightEyeSocket"), FRotator::ZeroRotator, SpawnParams);
         LeftEye = World->SpawnActor<ADynamicEye>(Mesh->GetSocketLocation("LeftEyeSocket"), FRotator::ZeroRotator, SpawnParams);
         LeftEye->AttachRootComponentTo(Mesh, "LeftEyeSocket", EAttachLocation::SnapToTarget);
         RightEye->AttachRootComponentTo(Mesh, "RightEyeSocket", EAttachLocation::SnapToTarget);
     }
 }

In the editor, I create a blueprint of SuspectCharacter called "BP_SuspectCharacter2". When I drag a copy of it into my level, it instantly (before I release the mouse) spawns two eyes near the origin of the level. Once I start playing, two more eyes are spawned on my character's eye sockets (Note, I'm not an artist at all, so for now I just created a cone in Maya that lays on it's side... the normal of the bottom flat part of the code is what should be following the player).

So here's the odd part. The eyes that spawned behave exactly as I want. As I move around the level, they track my head everywhere I go. The eyes that spawn on the SuspectCharacter start pointing straight up, then move around, but they don't track me at all.

alt text

One of the floating eyes that tracks me properly is clipping through the floor, so you can only see one. It took me quite a while to even find these guys spawning under my level! Anyway, when I delete my SuspectCharacter in the level, it leaves behind the eyes and I have to remove them manually from the Scene Outliner.

I tried moving the code that spawns the DynamicEyes out of the SuspectCharacter's constructor and into an overridden BeginPlay function, but all that does is destroy the free-floating eyes that work properly and keep the ones in the socket locations that don't.

I FEEL like the proper place to really have this is BeginPlay and not in the constructor. Also, when they eyes get instantiated in BeginPlay, they automatically get deleted when I delete The SuspectCharacter. It's almost like the socket is rotating the entire coordinate system of my DynamicEye. Can anybody please offer me some help?

Product Version: Not Selected
Tags:
ue debugging.jpg (48.5 kB)
more ▼

asked Aug 14 '14 at 12:13 AM in C++ Programming

avatar image

turick
0 1 3 6

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

Well, of course I spend hours and hours on this and the minute after I post the question, I get it working. It seems that the socket itself does have a rotation, and my code to control they eye sets the relative location instead of the world rotation.

I just changed the last line in DynamicEye to:

 MeshComponent->SetWorldRotation(EyeRotation, true);

Can you control the rotation at which a socket attaches to a bone? Or is it completely based on the orientation of the bone? Is my solution the right solution -- the socket could be oriented in a different vector, so just use world rotation?

more ▼

answered Aug 14 '14 at 12:31 AM

avatar image

turick
0 1 3 6

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question