How to know if I can move an Actor to NewLocation before calling SetActorLocation(NewLocation)

Hi!

I’m developing a Tetris like game with Unreal 5.2.1 and C++.

I’m having a problem with how to detect if I can move the block or in its next location there is another block or is the background.

The way I move the block is the following: I move it every tick the same size of its Z dimension. For example, if it is a cube of 100x100x100, and its first location is (X, Y, 850), I will move it to (X, Y, 750).

This is the header of the file:


UCLASS()
class TETRIS_API ATBlock : public AActor
{
	GENERATED_BODY()

public:

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UStaticMeshComponent* Mesh = nullptr;

	ATBlock();

	virtual void Tick(float DeltaTime) override;

	UPROPERTY(BlueprintReadWrite, Category = "Movement")
	float IntervalInSeconds = 1.0f;

	UPROPERTY(BlueprintReadWrite, Category = "Movement")
	float SpaceToMove = 100.0f;

	UFUNCTION()
	void OnComponentHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);

private:
	FVector GetNewLocation() const;

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

};

And, this the code:


#include "TBlock.h"

// Sets default values
ATBlock::ATBlock()
{
	PrimaryActorTick.bCanEverTick = true;
	Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));

	RootComponent = Mesh;

	SetActorTickInterval(IntervalInSeconds);

}

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

	const FDateTime CurrentDateTime = FDateTime::Now();
	UE_LOG(LogTemp, Log, TEXT("%s"), *CurrentDateTime.ToString());

	SetActorLocation(GetNewLocation());
}

void ATBlock::OnComponentHit(
	UPrimitiveComponent* HitComp,
	AActor* OtherActor,
	UPrimitiveComponent* OtherComp,
	FVector NormalImpulse,
	const FHitResult& Hit)
{
	UE_LOG(LogTemp, Warning, TEXT("Block HIT"));
	SetActorTickEnabled(false);

}

FVector ATBlock::GetNewLocation() const
{
	const FVector CurrentLocation = GetActorLocation();

	return FVector(CurrentLocation.X, CurrentLocation.Y, CurrentLocation.Z - SpaceToMove);
}

void ATBlock::BeginPlay()
{
	Super::BeginPlay();

	if (Mesh)
	{
		Mesh->OnComponentHit.AddDynamic(this, &ATBlock::OnComponentHit);
	}
}

I’ve been thinking about how to stop movement if there is something that blocks that movement.

First, I tried with collisions, but it doesn’t work or I don’t know how to do it.

Second, I’ve thought that maybe there is a way to know if there is something on the location where I want to move and check it before using SetActorLocation(NewLocation).

Finally, I’ve thought to use a matrix to know which cells are free to move there.

How can I do it?

Is there another method to know if I can move to NewLocation before using SetActorLocation(NewLocation)?

Someone has suggested me to use the overlap check functions, but I don’t know what those functions are.

Thanks.

run some sort of collsion check before moving, since you cube has a static size you could probably do a line trace in the direction you want to move, just remember to ignore self

Sweep does both:

No need to do it every frame. You Sweep once from where the actor is to where you want it to be. It will stop early if collision is detected. But that’s instantaneous. However you can use the resulting data and feed it into the timeline to animate it.

edit: quick example:

Essentially, sweep returns a bunch of data - you could play animation based on that.

This would not work for anything but a simple geo. Since this is a Tetris-like game, you’d have L-blocks, T-blocks and who knows what else, why not make a Starfish-block. Sweeping respects collider shapes:

Something a box / sphere trace cannot do.


Technically, you could move with sweep continuously but then it’s too late to do something with the data since we’ve already moved.


Also, The Tetris God

The Tetris God

3 Likes

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