How do I override a portion of a large function?

Hi,

I’ve recently started wanting to add to the charactermovementcomponent so I subclassed that and character to make my own, all is working OK but now that I need to make the TickComponent calculate something that goes right by the CheckJumpInput I’m not sure of the best way to get it there.

Before this I was using blueprints, so I’m early into learning how Unreal 4 deals with these things.

Here is the function I want to override. If you scroll down you’ll see the line that I marked with a bold underline. My code needs to go above/under there:


void UCharacterMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	SCOPE_CYCLE_COUNTER(STAT_CharacterMovementTick);

	const FVector InputVector = ConsumeInputVector();
	if (!HasValidData() || ShouldSkipUpdate(DeltaTime))
	{
		return;
	}

	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// See if we fell out of the world.
	const bool bIsSimulatingPhysics = UpdatedComponent->IsSimulatingPhysics();
	if (CharacterOwner->Role == ROLE_Authority)
	{
		if (!bCheatFlying || bIsSimulatingPhysics)
		{
			if (!CharacterOwner->CheckStillInWorld())
			{
				return;
			}
		}
	}

	// We don't update if simulating physics (eg ragdolls).
	if (bIsSimulatingPhysics)
	{
		return;
	}

	if (AvoidanceLockTimer > 0.0f)
	{
		AvoidanceLockTimer -= DeltaTime;
	}

	if (CharacterOwner->Role > ROLE_SimulatedProxy)
	{
		// If we are a client we might have received an update from the server.
		const bool bIsClient = (GetNetMode() == NM_Client && CharacterOwner->Role == ROLE_AutonomousProxy);
		if (bIsClient)
		{
			ClientUpdatePositionAfterServerUpdate();
		}

		// Allow root motion to move characters that have no controller.
		if( CharacterOwner->IsLocallyControlled() || (!CharacterOwner->Controller && bRunPhysicsWithNoController) || (!CharacterOwner->Controller && CharacterOwner->IsPlayingRootMotion()) )
		{
			{
				SCOPE_CYCLE_COUNTER(STAT_CharUpdateAcceleration);

				// We need to check the jump state before adjusting input acceleration, to minimize latency
				// and to make sure acceleration respects our potentially new falling state.
**				CharacterOwner->CheckJumpInput(DeltaTime);**



				// apply input to acceleration
				Acceleration = ScaleInputAcceleration(ConstrainInputAcceleration(InputVector));
				AnalogInputModifier = ComputeAnalogInputModifier();
			}

			if (CharacterOwner->Role == ROLE_Authority)
			{
				PerformMovement(DeltaTime);
			}
			else if (bIsClient)
			{
				ReplicateMoveToServer(DeltaTime, Acceleration);
			}
		}
		else if (CharacterOwner->GetRemoteRole() == ROLE_AutonomousProxy)
		{
			// Server ticking for remote client.
			// Between net updates from the client we need to update position if based on another object,
			// otherwise the object will move on intermediate frames and we won't follow it.
			MaybeUpdateBasedMovement(DeltaTime);
			SaveBaseLocation();
		}
	}
	else if (CharacterOwner->Role == ROLE_SimulatedProxy)
	{
		AdjustProxyCapsuleSize();
		SimulatedTick(DeltaTime);
	}

	UpdateDefaultAvoidance();

	if (bEnablePhysicsInteraction)
	{
		SCOPE_CYCLE_COUNTER(STAT_CharPhysicsInteraction);

		if (CurrentFloor.HitResult.IsValidBlockingHit())
		{
			// Apply downwards force when walking on top of physics objects
			if (UPrimitiveComponent* BaseComp = CurrentFloor.HitResult.GetComponent())
			{
				if (StandingDownwardForceScale != 0.f && BaseComp->IsAnySimulatingPhysics())
				{
					const float GravZ = GetGravityZ();
					const FVector ForceLocation = CurrentFloor.HitResult.ImpactPoint;
					BaseComp->AddForceAtLocation(FVector(0.f, 0.f, GravZ * Mass * StandingDownwardForceScale), ForceLocation, CurrentFloor.HitResult.BoneName);
				}
			}
		}

		ApplyRepulsionForce(DeltaTime);
	}
}

So my dilemma is that’s all I need to do. I don’t want to override the entire function, just insert a snippet of code under that line. What’s the most practical way to do this?

Thanks

It depends on what the code you want to add does, but you have a couple options:

  • Have your character class override CheckJumpInput and have it perform your custom logic.
  • Have your custom logic run in your own movement component’s TickComponent after you call Super_t::TickComponent so all the code above gets executed properly.
  • Copy and Paste that entire method and pray it doesn’t call any private methods. :slight_smile:

If you want to insert custom code on just that line, you’ll really need to override the whole function and cut and paste.

Ideally though, you would write whatever you are trying to do so that it can be done after that entire code is called - that way as AdeptStrain said you could call the Super:: function first then put in your code. Unfortunately that is sometimes just not possible. If you’re not sure, tell us what you are trying to do and someone might have a cleaner way to do it.

Hey guys,

Thanks for both your answers!

For this purpose, overriding CheckJumpInput works perfectly - AdeptStrain’s answer helped a lot because even if I put it in CheckJumpInput now, I might need to do something similar and not know how to.

I understand a lot better now, thanks to you both :slight_smile: Cheers!

Coming from Unity -> UE4 Blueprints I was amazed at how beautifully everything worked both on it’s own and with other components of the engine, now that I’m delving into code that amazement is happening all over again. Can actually make a game instead of redoing all the engine’s functionality :wink: