Extracting the mass from each element

I am currently at the Iteration Through Valid Actors lesson, and I’m working on adding up masses of objects that overlap the PressurePlate collision volume we’ve set up. I have a for loop set up here to loop though each object that is contained in the TArray OverlappingActors, which is an out parameter from the GetOverlappingActors function. To make sure the loop is working properly, I log the name of any object that is currently intersecting the collision volume. I’ve attached the whole TotalMassOfActors function for context:

float UOpenDoor::TotalMassOfActors() const
{
	float TotalMass = 0.f;

	// Find All Overlapping Actors.
	TArray<AActor*> OverlappingActors;
	PressurePlate->GetOverlappingActors(OUT OverlappingActors);

	// Add Up Their Masses.
	for (int i = 0; i < OverlappingActors.Num(); i++)
	{
		UE_LOG(LogTemp, Warning, TEXT("%s"), *OverlappingActors[i]->GetName());
	}
	return TotalMass;
}

This all makes sense to me. I’ve worked with for loops plenty. However, one thing that I struggle with in C++ in particular is dealing with the myriad of data types, pointers, references, etc. of objects that are crucial to get just right in order to use a function that I want. I read up on the documentation, and it looks like what I want is either the UPrimitiveComponent::GetMass or the UPrimitiveComponent::CalculateMass function.

My unsuccessful attempts at adding mass inside the for loop look something like this (these lines would be where my UE_LOG is above):

TotalMass += OverlappingActors[i]->GetMass();

or

TotalMass += OverlappingActors[i]->CalculateMass();

I would love to hear from someone who could explain the thought process behind this type of issue: knowing that my object is of type AActor*, knowing that the function I want to use on it requires
it be a UPrimitiveComponent, and how to get my object into that type. If possible here, a more-generalized answer would be most appreciated since this seems to be a reoccurring issue that I come across.

An actor is comprised of (usually) 1 or more components. So you would need to check the components on the actor which you can do using this

And the docs provide a remark about using TInlineComponentArray instead in which its constructor calls GetComponents with the actor provided and stores it internally. So with that you would do

TInlineComponentArray<UPrimitiveComponent> PrimComps(OverlappingActors[i]);
for (UPrimitiveComponent* P : PrimComps)
{
    TotalMass += P->GetMass();
}

Though the mass is usually combined into the root component you could instead just check if the root component is a primitive component and then call GetMass if it is.

UPrimitiveComponent PrimComp = Cast<UPrimitiveComonent>(OverlappingActor[i]->GetRootComponent)
if (PrimComp)
{
    TotalMass += PrimComp->GetMass();
}

Thank you for the reply. I think I understand the first part of what you are saying: I am attempting to use a function on an actor when it should be used on one of its components. In other words, I need to drill down into the components of the actor first and then use the function on a specific component (one called UPrimitiveComponent I would guess?)

Unfortunately I’m a bit lost after this. I am also getting an error in the first block of code on PrimComps:

no suitable conversion function from "UPrimitiveComponent" to "UPrimitiveComponent *" exists

Errors aside, I am interested in the intended logic. I can’t see what TInlineComponentArray is doing here, but in the for loop it looks like you create P to hold the primitive component of each actor in the array and call GetMass() on that.

I’m also getting some errors in the 2nd code block. After fixing some minor typos, I get the same error as above on the Cast<> portion.

If you didn’t fix my typo of the missing * then that would be why.

UPrimitiveComponent* PrimComp = ...

I can’t see what TInlineComponentArray is doing here

It’s a convenience class. All it does is wrap a TArray using the aforementioned TInlineAllocator and use GetComponents on construction.

This is the entire class

template<class T, uint32 NumElements = NumInlinedActorComponents>
class TInlineComponentArray : public TArray<T, TInlineAllocator<NumElements>>
{
	typedef TArray<T, TInlineAllocator<NumElements>> Super;

public:
	TInlineComponentArray() : Super() { }
	TInlineComponentArray(const AActor* Actor, bool bIncludeFromChildActors = false);
};

template<class T, uint32 NumElements>
TInlineComponentArray<T, NumElements>::TInlineComponentArray(const AActor* Actor, bool bIncludeFromChildActors) 
	: Super()
{
	if (Actor)
	{
		Actor->GetComponents(*this, bIncludeFromChildActors);
	}
};

Where NumInlinedActorComponents is 24.

So it would be no different from writing this

TArray<UPrimitiveComponent, TInlineAllocator<24>> PrimComps;
if (OverlappingActors[i])
{
    OverlappingActors[i]->GetComponents(PrimComps);
}

More info on TInlineAllocator here

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms