Modify Chaos Vehicle Component

Hi,

I’m using Chaos vehicle to create a motorbike and I would like to make some modifications to suit my needs.
First I have tried to access some variables in blueprint but almost nothing is exposed.
For example the center of mass. It is not exposed to the Vehicle Movement component nor Chaos Wheeled comp.
Then I took a look into the .h and I’ve found the var :

	UPROPERTY(EditAnywhere, Category = VehicleSetup, meta = (EditCondition = "bEnableCenterOfMassOverride"))
	FVector CenterOfMassOverride;

It is already “EditAnywhere” but I guess “BlueprintReadWrite” is also required here.

I’ve closed editor, added the specifier, cleaned/built solution and reopen editor but variable still doesn’t show up in bp. I think I can’t modify a plugin file as simply as that.

I’m looking for any advice or solution, thanks in advance.

Notice that the variable has an edit condition

EditCondition = "bEnableCenterOfMassOverride")

You can also swap out components even in c++

For example in my actor AWheeledVehiclePawnEx I swap out the base movement component with a custom extended class UWheeledVehicleMovementCompEX

in header cdo with initializer

AWheeledVehiclePawnEx(const FObjectInitializer& ObjectInitializer);

in cpp

AWheeledVehiclePawnEx::AWheeledVehiclePawnEx(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer.SetDefaultSubobjectClass<UWheeledVehicleMovementCompEX>(VehicleMovementComponentName))
{}

You can also swap out the components in the details panel to access the bp extensions

1 Like

First of all thank you for your prompt reply !

I noticed the edit condition but from my understanding it just allows setting the variable in the detail pannel. In my case it is already checked but it doesn’t allow setting dynamicaly (I should have been more precise about this point :sweat_smile:) :

I took this variable as an example, EnableCenterOfMassOverride doesn’t have edit condition and isn’t available either.

Good news I can swap the component, I was unsure how to do that.

I’m curious about your UWheeledVehicleMovementCompEX. I guess it inherits from the base UWheeledVehicleMovementComp class, but how does it allow dynamic modification in blueprint? I mean does it override parents specifiers?

If I create a child class (in c++) of Wheeled Vehicle Pawn, can I access those variables easily from the component? I think creating public functions I could finally access in BP?

I’m progressing a bit.

I created a child of WheeledVehiclePawn.

Here is my header :

#pragma once

#include "CoreMinimal.h"
#include "WheeledVehiclePawn.h"
#include "ChaosVehicleMovementComponent.h"
#include "CustomWheeledVehiclePawn.generated.h"

/**
 * 
 */
UCLASS()
class MOB_API ACustomWheeledVehiclePawn : public AWheeledVehiclePawn
{
	GENERATED_BODY()
	
public:
	ACustomWheeledVehiclePawn();

	UFUNCTION(BlueprintCallable, Category = "Bike Behavior")
	virtual void SetCenterOfMassOffset(FVector CenterOfMass);
};

And here is my cpp :

#include "CustomWheeledVehiclePawn.h"
#include "ChaosVehicleMovementComponent.h"

ACustomWheeledVehiclePawn::ACustomWheeledVehiclePawn()
{
}

void ACustomWheeledVehiclePawn::SetCenterOfMassOffset(FVector CenterOfMass)
{
	UChaosVehicleMovementComponent* ChaosVehicleMovement = Cast<UChaosVehicleMovementComponent>(GetVehicleMovementComponent());
	if (ChaosVehicleMovement)
	{
		ChaosVehicleMovement->CenterOfMassOverride = CenterOfMass;
		UE_LOG(LogTemp, Warning, TEXT("Valid Component"));
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("Invalid Component"));
	}
}

The function appears now in the BP graph which is great:

Now I have to figure out why it doesn’t have any effect (it prints “Valid Component” in the log so I guess my casted component is ok)

Try:

header:

UFUNCTION(BlueprintCallable)
void SetCOM(FVector newValue, bool bOverride);

UFUNCTION(BlueprintCallable)
FVector GetCOM();

cpp

void UWheeledVehicleMovementCompEX::SetCOM(FVector newValue, bool bOverride)
{
	bEnableCenterOfMassOverride = bOverride;
	CenterOfMassOverride = newValue;
	
	if (UpdatedPrimitive && UpdatedPrimitive->GetBodyInstance())
	{
		UpdateMassProperties(UpdatedPrimitive->GetBodyInstance());
	}
	SetupVehicleMass();
}


FVector UWheeledVehicleMovementCompEX::GetCOM()
{
	FVector COM = FVector::Zero();
	
	if (bEnableCenterOfMassOverride == true)
	{
		COM = CenterOfMassOverride;
	}
	else {
		if (UpdatedPrimitive && UpdatedPrimitive->GetBodyInstance())
		{			
			COM = UpdatedPrimitive->GetBodyInstance()->COMNudge;
		}
	}
	return COM;
}

1 Like

My last attempt was almost working, I mean the log returned correct values (I also use log here instead of using a second function for printing in bp) :

void ACustomWheeledVehiclePawn::SetCenterOfMassOffset(bool Enable, FVector CenterOfMass)
{
	UChaosVehicleMovementComponent* ChaosVehicleMovement = Cast<UChaosVehicleMovementComponent>(GetVehicleMovementComponent());
	if (ChaosVehicleMovement)
	{
		ChaosVehicleMovement->CenterOfMassOverride = CenterOfMass;
		ChaosVehicleMovement->bEnableCenterOfMassOverride = Enable;
		//ChaosVehicleMovement->ResetVehicleState();
		//ChaosVehicleMovement->ResetVehicle();
		//UpdateMassProperties(UpdatedPrimitive->GetBodyInstance());
		UE_LOG(LogTemp, Warning, TEXT("Valid Component"));
		UE_LOG(LogTemp, Warning, TEXT("Center of Mass after modification: %s"), *ChaosVehicleMovement->CenterOfMassOverride.ToString());
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("Invalid Component"));
	}
}

Despite correct values there was no effect until I tried to reset the component, problem is it resets wheels rotation and stop vehicle. I read the documentation and found about “UpdateMassProperties” like you suggest. I didn’t understood how to use it but I guess that’s the function to use.

Here is my new attempt with your code. I’ve changed the class name to match mine, put the log in it and added a reference to the component since visual said “bEnableCenterOfMassOverride” and “CenterOfMassOverride” indentifiers were undefined.

void ACustomWheeledVehiclePawn::SetCOM(FVector newValue, bool bOverride)
{
	UChaosVehicleMovementComponent* ChaosVehicleMovement = Cast<UChaosVehicleMovementComponent>(GetVehicleMovementComponent());
	ChaosVehicleMovement->bEnableCenterOfMassOverride = bOverride;
	ChaosVehicleMovement->CenterOfMassOverride = newValue;

	if (UpdatedPrimitive && UpdatedPrimitive->GetBodyInstance())
	{
		UpdateMassProperties(UpdatedPrimitive->GetBodyInstance());
		UE_LOG(LogTemp, Warning, TEXT("Center of Mass after modification: %s"), *ChaosVehicleMovement->CenterOfMassOverride.ToString());
	}
	SetupVehicleMass();
}

However “UpdatedPrimitive”, “UpdatedPrimitive” and “SetupVehicleMass” are still undefined. Maybe they require reference to something?

The functions I posted in the last version are for the custom Movement component only, not the vehicle pawn, that is why you are missing the variables (they are in the movement component only).

Notice it mentions UWheeledVehicleMovementCompEX as the class.

I extracted them from the vehicle itself and isolated them to the movement component to keep the single responsibility principle.

1 Like

I yes indeed I didn’t notice :sweat_smile:
I’m going to create this component and let you know how it goes

1 Like

I’ve created a fresh project and created my class with exact same names as yours so I don’t get confused.

Here is my new WheeledVehiclePawnEx, I’ve added the include for the component in both .h and .cpp :

#pragma once

#include "CoreMinimal.h"
#include "WheeledVehiclePawn.h"
#include "WheeledVehicleMovementCompEX.h"
#include "WheeledVehiclePawnEx.generated.h"

/**
 * 
 */
UCLASS()
class MOB_API AWheeledVehiclePawnEx : public AWheeledVehiclePawn
{
	GENERATED_BODY()
	
public:

	AWheeledVehiclePawnEx(const FObjectInitializer& ObjectInitializer);
};
#include "WheeledVehiclePawnEx.h"
#include "WheeledVehicleMovementCompEX.h"

AWheeledVehiclePawnEx::AWheeledVehiclePawnEx(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer.SetDefaultSubobjectClass<UWheeledVehicleMovementCompEX>(VehicleMovementComponentName))
{}

Then I created the WheeledVehicleMovementCompEX (from ChaosWheeledVehicleMovementComponent, right?)

#pragma once

#include "CoreMinimal.h"
#include "ChaosWheeledVehicleMovementComponent.h"
#include "WheeledVehicleMovementCompEX.generated.h"

/**
 * 
 */
UCLASS()
class MOB_API UWheeledVehicleMovementCompEX : public UChaosWheeledVehicleMovementComponent
{
	GENERATED_BODY()
	
public:

	UFUNCTION(BlueprintCallable)
	void SetCOM(FVector newValue, bool bOverride);

	UFUNCTION(BlueprintCallable)
	FVector GetCOM();
};

and

#include "WheeledVehicleMovementCompEX.h"

void UWheeledVehicleMovementCompEX::SetCOM(FVector newValue, bool bOverride)
{
	bEnableCenterOfMassOverride = bOverride;
	CenterOfMassOverride = newValue;

	if (UpdatedPrimitive && UpdatedPrimitive->GetBodyInstance())
	{
		UpdateMassProperties(UpdatedPrimitive->GetBodyInstance());
	}
	SetupVehicleMass();
}


FVector UWheeledVehicleMovementCompEX::GetCOM()
{
	FVector COM = FVector::Zero();

	if (bEnableCenterOfMassOverride == true)
	{
		COM = CenterOfMassOverride;
	}
	else {
		if (UpdatedPrimitive && UpdatedPrimitive->GetBodyInstance())
		{
			COM = UpdatedPrimitive->GetBodyInstance()->COMNudge;
		}
	}
	return COM;
}

From this point I get no error in visual, live coding succeed as well.
Then I create a BP based on the vehicle pawn. The component is already initialized to my custom one :

I can now find the function but can’t connect to the component nor the cast (had to uncheck “context sensitive” to find it) :

I understand I can’t connect incompatible objects, but I don’t understand why the component isn’t the class specified in the detail pannel. I can’t swap to the original component either, it doesn’t appear in the dropdown (I guess it is due to initialization in c++?).
I also noticed in your dropdown you have a BP version of the component :

image

I’ve tried to create one but I can’t. I tried also to create an actor component to reparent but that is not possible either :

Actor component :

I’m probably missing something obvious. I apologize if it seems a bit nooby, and once again I thank you for your patience

Edit : Nevermind, I think I’m holding something :

Yeah that finally works! COM changes at runtime. I’m so grateful (and relieved)

1 Like

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