Another solution to handle platform trigger activation

Here is another way to do this if anybody is interested. First of all, inside the Platform trigger I created a boolean and a function to get the boolean

UPROPERTY(Replicated)
bool bIsOverlapped;

public:
bool GetIsOverlapped();

Inside .CPP we are just settings the bool when actor overlaps this actor

void APPlatformTrigger::NotifyActorBeginOverlap(AActor * OtherActor)
{
	//UE_LOG(LogTemp, Warning, TEXT("Overlapped2"));
	if (HasAuthority())
	{
		bIsOverlapped = true;
	}
	
}

void APPlatformTrigger::NotifyActorEndOverlap(AActor * OtherActor)
{
	if (HasAuthority())
	{
		bIsOverlapped = false;
	}
}

Of course, the bool needs to be replicated also.

void APPlatformTrigger::GetLifetimeReplicatedProps(TArray < FLifetimeProperty > & OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(APPlatformTrigger, bIsOverlapped);
}

Now, inside the moving platform class I created couple variables. One variable is just for the editcondition so it can be used to grey out other variables. Other variable is pointing to specific Trigger we just created.

	UPROPERTY(EditInstanceOnly)
	bool MovedThroughTrigger;
	UPROPERTY(EditInstanceOnly, meta = (editcondition = MovedThroughTrigger))
	APPlatformTrigger* ActivatingTrigger;

To see how the editcondition looks inside game:
exampl

As you can see, we cannot set the trigger if we don’t activate bool. This is great way to be extra carefully for not using the null pointers.

If we would want to platform be moved by some specific Trigger, we can just click it and then use pipet tool to set correct trigger to this platform.

Now we just need to edit the movement logic:

MovedThroughTrigger && ActivatingTrigger && ActivatingTrigger->GetIsOverlapped() ? Forward ? SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction)) : SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction *-1)) : !MovedThroughTrigger ? Forward ? SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction)) : SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction *-1)) : 0;

Basically we are checking if the MovedThroughTrigger boolean is true, ActivatingTrigger class is not nullptr and then we are checking if the ActivatingTrigger is overlapped or not (we created that function). If all these are true, we are checking few other if statements and run the logic.

edit:
Just noticed that in this video, we created platform that can be controlled by multiple triggers. Here is the full code that handles that also.

.H file:

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

#pragma once

#include "CoreMinimal.h"
#include "Engine/StaticMeshActor.h"
#include "PMovingPlatform.generated.h"

class APPlatformTrigger;

/**
 * 
 */
UCLASS()
class PUZZLEPLATFORMS_API APMovingPlatform : public AStaticMeshActor
{
	GENERATED_BODY()

public:
	APMovingPlatform();
	

protected:
	virtual void BeginPlay() override;
	virtual void Tick(float Deltatime) override;

private:
	UPROPERTY(EditAnywhere, Category ="Settings")
	float PlatformSpeed;

	UPROPERTY(EditAnywhere, Category = "Settings", Meta = (MakeEditWidget = true))
	FVector TargetLocation;

	FVector GlobalStartLocation;
	FVector GlobalTargetLocation;

	bool Forward;
	bool bCanMoveIfTriggerControlled;

	UPROPERTY(EditInstanceOnly)
	bool MovedThroughTrigger;
	UPROPERTY(EditInstanceOnly, meta = (editcondition = MovedThroughTrigger))
	TArray<APPlatformTrigger*> ActivatingTriggers;
};

.CPP

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

#include "Public/PMovingPlatform.h"
#include "Kismet/KismetMathLibrary.h"
#include "Public/PPlatformTrigger.h"

APMovingPlatform::APMovingPlatform()
{
	PrimaryActorTick.bCanEverTick = true;
	SetMobility(EComponentMobility::Movable);
	// Speed which platform moves
	PlatformSpeed = 100;

	Forward = true;
	
}

void APMovingPlatform::BeginPlay()
{
	Super::BeginPlay();
	if (HasAuthority())
	{
		// We are going to replicate this actors movement.
		SetReplicates(true);
		SetReplicateMovement(true);
		GlobalStartLocation = GetActorLocation();
		// Change local position to Global position of this Vector.
		GlobalTargetLocation = GetTransform().TransformPosition(TargetLocation);

	}
	
}

void APMovingPlatform::Tick(float Deltatime)
{
	Super::Tick(Deltatime);
	
	// Are we server
	if (HasAuthority())
	{	
		bCanMoveIfTriggerControlled= false;
		FVector Direction = (GlobalTargetLocation - GlobalStartLocation).GetSafeNormal();
		// We compare if we are going forward or backward and are we at the Start or the End location. Then change the boolean
		Forward && FVector((GlobalStartLocation - GetActorLocation())).Size() > FVector((GlobalStartLocation - GlobalTargetLocation)).Size() ? Forward = false : !Forward && FVector((GlobalTargetLocation - GetActorLocation())).Size() > FVector((GlobalTargetLocation - GlobalStartLocation)).Size() ? Forward = true : 0;
		FVector Location = GetActorLocation();		
		// Direction vector is Vector B - Vector A		
		// Location is X centimeters per seconds in specific direction
		if (MovedThroughTrigger)
		{
			for (auto Trigger : ActivatingTriggers)
			{
				Trigger->GetIsOverlapped() ? bCanMoveIfTriggerControlled = true : 0;
			}
		}
		
		MovedThroughTrigger && bCanMoveIfTriggerControlled ? Forward ? SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction)) : SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction *-1)) : !MovedThroughTrigger ? Forward ? SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction)) : SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction *-1)) : 0;
		//MovedThroughTrigger && ActivatingTrigger && ActivatingTrigger->GetIsOverlapped() ? Forward ? SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction)) : SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction *-1)) : !MovedThroughTrigger ? Forward ? SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction)) : SetActorLocation(GetActorLocation() + (PlatformSpeed * Deltatime * Direction *-1)) : 0;
	}

}
1 Like

Interesting, are you sure bIsOverlapped needs to be replicated?

Because the clients never need to check bIsOverlapped, in fact, GetIsOverlapped() is also run inside a HasAuthority() so that’s all on the server and doesn’t need to be replicated.

However it would need replication if you had a blueprint on the client changing color on the switch if it overlaps, then it would need to be replicated.

Privacy & Terms