Mass keeps getting set back to 0

I’m having some difficulty with the challenge to create a weight trigger.

So far, when the player releases the Grab button while holding an object at the trigger component, the mover only seems to “shake” the door. Debugging with UE_LOGs shows that while the mass of the actor is recorded as the user releases the button, the calculated mass is set to 0 in subsequent ticks (until the user grabs and stops grabbing the item again). I’m not sure why this is happening.

Here’s my code:
In TriggerComponent.h, I store the Overlapping actors in a private TArray TArray<AActor*> OverlappingActors;

Here’s the Weight Threshold code, which is located in the tick function of TriggerComponent.cpp:

else if (TriggerOption == TriggerOptions::WeightThreshold)
	{

		if (Mover == nullptr)
		{
			return;
		}
	
		if (MeetsThreshold(OverlappingActors))
		{
			for (AActor* overlappingActor : OverlappingActors)
			{
				UPrimitiveComponent* Component = Cast<UPrimitiveComponent>(overlappingActor->GetRootComponent());

				if (Component != nullptr)
				{
					Component->SetSimulatePhysics(false);
				}
				overlappingActor->AttachToComponent(this, FAttachmentTransformRules::KeepWorldTransform);
			}
			Mover->SetIsOverlapping(true);
		}
		else
		{
			Mover->SetIsOverlapping(false);
		}
	}

The function MeetsThreshold is defined as:

bool UTriggerComponent::MeetsThreshold(TArray<AActor*>& Actors)
{
	float calculatedMass = 0;
	GetOverlappingActors(Actors);
	
	TInlineComponentArray<UPrimitiveComponent*> componentsOfActor;
	for (AActor* Actor : Actors)
	{
		UE_LOG(LogTemp, Error, TEXT("Actor found"));
		if (!Actor->ActorHasTag("Grabbed"))
		{
			Actor->GetComponents(componentsOfActor);
			if (componentsOfActor.IsEmpty())
			{
				//UE_LOG(LogTemp, Error, TEXT("No components"));
			}
			for (int i = 0; i < componentsOfActor.Num(); i++)
			{
				UE_LOG(LogTemp, Error, TEXT("%s"), *componentsOfActor[i]->GetName());
				//Mass can't be obtained for non-physics objects
				if (componentsOfActor[i]->IsSimulatingPhysics())
				{
					UE_LOG(LogTemp, Error, TEXT("%s"), *componentsOfActor[i]->GetName());
					calculatedMass += componentsOfActor[i]->GetMass();
				}
			}

			//Clear all elements so we can just get masses of next component
			componentsOfActor.Empty();
		}
	}
	if (calculatedMass < MinimumRequiredWeight)
	{
		return false;
	}
	return true;
}

I would appreciate any assistance! Thanks.

You should create your own Mass instead of using the physical one on the actor which is used for physics simulation.
You’re turning SimulatePhysics on and off so you’re going to mess with your calculation.


A couple of code comments:

  • You are inconsistent with casing.
  • componentsOfActor isn’t used outside of the loop so you can just define it within the loop and that removes your need to clear it.
  • It also has a constructor so instead of
    TInlineComponentArray<UPrimitiveComponent*> componentsOfActor;
    Actor->GetComponents(componentsOfActor);
    
    you can do it in one step
    TInlineComponentArray<UPrimitiveComponent*> ComponentsOfActor(Actor);
    
  • Your indexed based loop could be a ranged-for.

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

Privacy & Terms