Disable diagonal movement 2d top down game

New to the engine and game programming in general. After reading more pages and threads than I really wanted to I still cant find a solution to disabling diagonal movement in a top down 2d game. This should not be this hard to clamp the player movement to only 4 directions. left/right/up/down. I am looking for someone with experience with this who has a legit solution not an idea. Looking for something simple and not a pile of bools. I need to make a grid based movement system that is fluid. Allowing either left or right or up and down but never up/right etc at the same time. I am at the point of paying someone to make this happen. 5 days of playing with code for such a simple thing is very aggrivating.

That means pressing a button would hop you from one grid space to another, locked, not to end up somewhere halfway or diagonally displaced. Easiest way is to set up a teleport system and not use the character or pawn movement component at all. Don’t even use the pathing system that is molten into it. It’s a mess with a 101 features you specifically do not want and will mess up grid movement. Just use a pawn and completely remove any movement component of the engine on that pawn.

Next set up a grid on a GameInstanceSubsystem, it’s a subsystem you can get a reference to from anywhere and persists through level loading. On that subsystem you register the size of the grid (int vector, or int point for 2D), size in cm of a grid tile (float), and obstacles per a point on the grid (TMap<FIntPoint, bool> where bool indicates obstacle).

Programming Subsystems in Unreal Engine | Unreal Engine 5.2 Documentation

If you need to spawn anything in the world, you would get a location for that spawn by taking a position on the grid (for example vector X4, Y8) and multiplying that by the size of a grid tile. Just like a chess board if a chess tile would be defined 100cm then hopping from tile X1Y1 to X1Y2 would teleport you 100cm up.

An obstacle on the grid could be a wall or a pawn, it doesn’t matter just anything you don’t want to share a space with (winwin you don’t even need to set up mesh collision). When you press a directional button on your pawn, ask the grid if there is an obstacle in the neighboring grid space relative to your character, if not teleport the character there. You get movement like in crypt of the necrodancer. You can optionally store the position of obstacles including your character on the grid subsystem as int vector, then you have a central tracker and don’t need to awkwardly round your world position from float to int anytime you need to check your characters grid position.

https://www.youtube.com/watch?v=Rs4Sc6-PjQI

If at some point you do need pathing for AI maybe then that is made easy with vector fields.

https://www.youtube.com/watch?v=ZJZu3zLMYAc

I appreciate your reply but I will need some of the movement system incorporated into the game. Your suggestion would work for a different turn based project I am working on but not for the current one. I am looking for The Legend of Zelda style controls from the original NES game. up down left right.

Well, could do it like this on your pawn:


// On pawn tick, otherwise you would tick on two separate events anyway (MoveRight and MoveUp).
void AYourPawn::Tick(float InDeltaSeconds) {
	Super::Tick(InDeltaSeconds);
	
	// Get the axis value of an input axis binding. Note that it must be bound on this input component.
	const float RightVal = InputComponent->GetAxisValue(TEXT("MoveRight"));
	const float UpVal = InputComponent->GetAxisValue(TEXT("MoveUp"));

	// Check if movement input is up or right based on input size.
	const bool  bGoRight = FMath::Abs(RightVal) > FMath::Abs(UpVal);

	// Either use the actor rotation, camera rotation or if nothing ever rotates just the absolute world vector.
	const FVector MovementDirection = bGoRight ? UKismetMathLibrary::GetRightVector(GetActorRotation()) : UKismetMathLibrary::GetUpVector(GetActorRotation());

	// Get the speed
	const float MovementSpeed = bGoRight ? RightVal : UpVal;

	// Add movement input to be processed by UE default implementation
	AddMovementInput(MovementDirection, MovementSpeed, false);
}

In blueprints this is just the same if you search for the method names you get a node. input axis bindings can be made in the project settings → input.

1 Like

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