How do you build a custom movement solution that does not break other parts of Unreal?

My mesh does not work as a character or a pawn. Anyone have advice of how to move an asymmetrical object that is not centered and still get collisions to work? Anyone have advice on building a custom solution if that isn’t possible?

Notes:

  • If the pawn uses a collision box as a root I have to move my mesh and then my pivot is messed up.

  • If the pawn uses a scene component as the root then collisions don’t work. You either move the whole actor and then sweeps don’t work because all child components teleport. Or you move the component and the whole actor doesn’t move so references to it’s location in things like state trees don’t work

  • I don’t want hacky solutions that are going to break something else down the line




Your screenshots look like a solid object. Do you have bones on that object? If not, you can just use a normal static mesh component and if you have low polygon count, just use “Complex as Simple” on your mesh. If you have issues with convex portions or holes (I don’t remember if you can use complex as simple with non convex shapes and/or holes). But if you need it, there are several ways to fix that. The simplest is to import it into Blender and add boxes or convex shapes that cover the volume of your object.

For the naming convention of the collision meshes, please refer to the following document under the “Collision” section.

If you can’t do this or want a different way, then you can manually create one or more static mesh components with convex shapes that have “Complex as Simple” set on them and you’d do your collision on those. You’d just hide them during gameplay. This is not advised as you need to know about certain settings I can’t remember atm about having them all act as one. Not sure physics would work either if you’re using that. But it works fine for line traces, overlap events and general collisions. If you can do it any other way like re-importing the collisions with the mesh as mentioned above, I’d do that.

I don’t understand your second point under “Notes”. All actors work fine with a Scene Component as the root. If something is not working, it’s not because of the scene component.

I don’t understand what you’re trying to say. It’s impossible to move the root component without moving the actor. The root component IS the actor for the most part. The actor takes its transform (position, rotation and scale) from the root component. I’ve personally never tried to alter the transform of a root component. It’s possible there could be issues there with triggering events or updates.

If you mean moving the mesh component, then yeah, the actor will not move. That’s not how unreal engine works.

I understand that I can use a static mesh. I just set this up for simplicity here. I also am aware of how to setup collisions on a static mesh. I appreciate it though.
Let me try to explain a bit more of my issue. It has to do with movement and how that ties into collisions.
So let me eplain why I cannot use a scene component as the root component of my pawn.


SetActorLocation seems to be the way to move an actor. Under the hood it calls move component on the root component

bool AActor::SetActorLocation(const FVector& NewLocation, bool bSweep, FHitResult* OutSweepHitResult, ETeleportType Teleport)
{
	if (RootComponent)
	{
		const FVector Delta = NewLocation - GetActorLocation();
		return RootComponent->MoveComponent(Delta, GetActorQuat(), bSweep, OutSweepHitResult, MOVECOMP_NoFlags, Teleport);
	}
	else if (OutSweepHitResult)
	{
		*OutSweepHitResult = FHitResult();
	}

	return false;
}

And here is move component, check out this comment in the @param bSweep

“Only the root component is swept and checked for blocking. child components move without sweeping”

	/**
	 * Tries to move the component by a movement vector (Delta) and sets rotation to NewRotation.
	 * Assumes that the component's current location is valid and that the component does fit in its current Location.
	 * Dispatches blocking hit notifications (if bSweep is true), and calls UpdateOverlaps() after movement to update overlap state.
	 *
	 * @note This simply calls the virtual MoveComponentImpl() which can be overridden to implement custom behavior.
	 * @note The overload taking rotation as an FQuat is slightly faster than the version using FRotator (which will be converted to an FQuat)..
	 * @param Delta			The desired location change in world space.
	 * @param NewRotation	The new desired rotation in world space.
	 * @param bSweep		Whether we sweep to the destination location, triggering overlaps along the way and stopping short of the target if blocked by something.
	 *						Only the root component is swept and checked for blocking collision, child components move without sweeping. If collision is off, this has no effect.
	 * @param Teleport		Whether we teleport the physics state (if physics collision is enabled for this object).
	 *						If TeleportPhysics, physics velocity for this object is unchanged (so ragdoll parts are not affected by change in location).
	 *						If None, physics velocity is updated based on the change in position (affecting ragdoll parts).
	 *						If CCD is on and not teleporting, this will affect objects along the entire swept volume.
	 * @param Hit			Optional output describing the blocking hit that stopped the move, if any.
	 * @param MoveFlags		Flags controlling behavior of the move. @see EMoveComponentFlags
	 * @param Teleport      Determines whether to teleport the physics body or not. Teleporting will maintain constant velocity and avoid collisions along the path
	 * @return				True if some movement occurred, false if no movement occurred.
	 */
	bool MoveComponent( const FVector& Delta, const FQuat& NewRotation,    bool bSweep, FHitResult* Hit=NULL, EMoveComponentFlags MoveFlags = MOVECOMP_NoFlags, ETeleportType Teleport = ETeleportType::None);

And here is the issue. If your scene component is your root component it “has no rendering or collision capabilities.”

/**
 * A SceneComponent has a transform and supports attachment, but has no rendering or collision capabilities.
 * Useful as a 'dummy' component in the hierarchy to offset others.
 * @see [Scene Components](https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Actors/Components/index.html#scenecomponents)
 */
UCLASS(ClassGroup=(Utility, Common), BlueprintType, hideCategories=(Trigger, PhysicsVolume), meta=(BlueprintSpawnableComponent, IgnoreCategoryKeywordsInSubclasses, ShortTooltip="A Scene Component is a component that has a scene transform and can be attached to other scene components."), MinimalAPI)
class USceneComponent : public UActorComponent

It’s child class Primitive component does

/**
 * PrimitiveComponents are SceneComponents that contain or generate some sort of geometry, generally to be rendered or used as collision data.
 * There are several subclasses for the various types of geometry, but the most common by far are the ShapeComponents (Capsule, Sphere, Box), StaticMeshComponent, and SkeletalMeshComponent.
 * ShapeComponents generate geometry that is used for collision detection but are not rendered, while StaticMeshComponents and SkeletalMeshComponents contain pre-built geometry that is rendered, but can also be used for collision detection.
 */
UCLASS(abstract, HideCategories=(Mobility, VirtualTexture), ShowCategories=(PhysicsVolume), MinimalAPI)
class UPrimitiveComponent : public USceneComponent, public INavRelevantInterface, public IInterface_AsyncCompilation, public IPhysicsComponent
public:
	/** 
	 * Begin tracking an overlap interaction with the component specified.
	 * @param OtherComp - The component of the other actor that this component is now overlapping
	 * @param bDoNotifies - True to dispatch appropriate begin/end overlap notifications when these events occur.
	 * @see [Overlap Events](https://docs.unrealengine.com/InteractiveExperiences/Physics/Collision/Overview#overlapandgenerateoverlapevents)
	 */
	ENGINE_API void BeginComponentOverlap(const FOverlapInfo& OtherOverlap, bool bDoNotifies);
	

So when you move your pawn with a scene component as the root it stops all it’s children from sweeping and then only sweeps the root which in this case does not have that functionality, so… you have just removed collisions on move… great.


So why not just use the box collision as the root of a pawn if the character capsule does not work…
That’s what my pictures were trying to show. The collision box does not fit my mesh because the center of my mesh sits back a little.

So if I move my mesh back like this to fit into the collision box it now has it’s pivot is to far forward so it rotates awkwardly.

So I can’t use the Box as the root because it messes with my origin and I can’t use my scene component as my root because it negates collisions.


So I thought what if I make the scene component the root and then call move component directly on the box component child with everything else parented to it. Well that worked, but I am only moving my box component and it’s children relative to it’s parent. It’s parent the root component does not move. So anything calling GetActorLocation() will get the actors root location 0,0,0 in this case while I have moved the children components to say 1524,500,0


So I am at a loss and that is why I was asking. Does anyone have experience making a custom solution to this problem and if so, did it work? or did it mess up other systems later on down the line?
Thanks for responding
I’m open to explain further if that is needed.

Everyone has meshes that aren’t centered. Why is the traditional workflow of just making the capsule bigger (or in this case the box bigger) not acceptable?

If you want better fitting collision meshes, I can help you there if you want, but it’s a separate issue.

I appreciate your help bud, but I’m not sure I am being understood. I don’t think everyone uses a character that has an offset center of gravity and I am unaware of any traditional or documented workflow where you solve this issue by just making the collider larger. If I just make the collision shapes bigger then I don’t collide with objects correctly. There are huge gaps between my character and my collision shape.


I don’t know all the ins and outs of collisions, physics and movement, I just can’t get this to work for crap and it’s super depressing. If I use a character then my mesh needs to fit in a capsule or sphere and then I’m back at my first pictures of the sphere. If I do that my character floats above the ground or things way above him collide with him.


I’m not looking for an argument though, I’m looking for help. maybe I’m stupid or maybe I suck at explaining this or maybe it’s just really complex, but if you have help I’d like to hear it.