Sunday, February 25, 2024

Coding Knowledge update- this part has given me the most trouble.

 SO I've started making a game every monthh, r every few weeks. Just to experiment, and obviously get better at game development. 


A few days ago I started a ball project. Where the goal is to get the ball across a goal, under a certain amount of time, without dying. 

You die by hitting the edges of the maze, and if the timer reaches zero. 


RIght now it plays like this. 


Right now the code is basically being all done in side of the player character pawn. 


The first week, I added the movement controls. This was, and is continously the trickiest part. 

I'll outline it in a few steps. 


Since I was Using Enhanced Action Input; I"ll be describing my process using that. 



Step 1 - 

In the headerfile; I had to declare a few things. I had to declare where the Input Mapping was going to go. 

And I had declare where the Input Action was going to go. 

When I made a blue print based of this class, this is where I'll put the Input Mapping Context, and the INput Action , when I make em. 


The Header file contrains these lines of code


UPROPERTY(EditAnywhere, Blueprintreadwrite, Category = Input)

UInputAction* MyActionInput;

///The above is where you're going to put the Input Action that you made/make in Unreal


UPROPERTY(EditAnywhere, Category = Input)

UInputMappingContext* MyMappingContext;

///The Above line here is where you're going to put the Mapping Context that you've made in Unreal

As you can see. with the pointer after the Class, I was forward declaring in the header. That looks like this. 

class UInputAction;

class UInput;

class UInputMappingContext;

You put that near the top. 

    So the next part, is always super confusing to me, I imagine I'll look back on this fondly for the times when I thought THIS was complicated. However as of now, this part is still very confusing for me haha. 

    The next step, Is we're getting the player controller ( we need this for later also) and we're getting it by initializing our own controller class and casting from that to get the GetPlayerController Function. 
That looks like
So over on the CPP it looks like this

APlayerController* MyController

then casting from this class, to get our player controller, and that looks...

APlayerController* MyController = Cast<MyController>(GetPlayerController());


Now if this cast is succesful, now we have to get the EnhancedLocalInput Subsystem. 
(Truth be told. I dont know much about Subsystems in Unreal, but I do know the steps that initalize our Local Subsystem)

So again, 
We can check if the cast is succesfull with a simple IF statement. 

if(MyController){}

This will check if the cast will work. Once there, we can add the cast of the subsystem into body of the IF statement. That'll look like this. 

If(MyController){
    If(UEnhancedInputLocalPlayerSubsystem* MySubystem = 

}

Now for the Subsystem, now we need to call the "GetSubsystem" function, which is a function of the ULocalPlayer  class.  That looks like this. 



If(MyController)
{
If(UEnhancedInputLocalPlayerSubsystem* MySubsystem = ULocalPlayer::GetSubystem<UEnhancedInputLocalPlayerSubsystem>(MyController->GetLocalPlayer()); 
}

/// The GetSubsystem Function Template is in the ULocalPlayer Namespace

Now this a bit complicated (to 2024 Paul).
This is all to get and check if we have a subsystem. Once that part is done, THEN we can initalize the subsystem with thhe Mapping Context that we made before. 

So take that code above, and add this 

APlayerController* MyController = Cast<MyController>(GetPlayerController());

IF(MyController)
{
If(UEnhancedInputLocalPlayerSubsystem* MySubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(MyController->GetLocalPlayer())
{
MySubsystem->AddMappingContext(MyMappingContext, 0); 
}

To quickly go over what we're seeing. 
- We're casting to the MyController type, to GetPlayer Controller
- We check with an if statement if that cast was succesful
- Inside that if statement we  Get the subsystem thru the LocalPlayersubsystem Type by callin ght eGetlocal player function
- and from there, we acces the AddmappingContxt function in the MySubsystem class

This is all done in the EventBeginPlay to use our MappingContext. 


So now that we've got that part done, we need to bind our Mapping Context, and have it access a function.

This part is much shorter, but also complicated. I still dont completely understand it, but I"ll do my best to expalin it to future me. 
You'll need to bind ur inputs in the function called AYourActor::SetupPlayerINputComponent(UInputComponent( PlayerInputComponent)

What we're going to do here is cast from an input component, and check. IF the cast is succesfull then we're going to access the BindAction() function from the UenhancedInputComponent Class. That code looks like this. 

If(UEnhancedInputComponent* MyInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent)){
MyInputComponent->BindAction(InputAction, EtriggerEvent::Triggered(or whatever event you've designated in your INput Action), this ( the object it effects), AC_YourActor::WhateverMovementFunction);
}

From there its pretty simple, we just define the function that we're binding and go from there. 

I hope this helps future paul quite a bit!. 
Back to some tutorials ;)