Spring Controller seems to be inverted

My Character Pawn is using Spring controller to simulate bouncy parts of the mesh, (Breasts, Hair) The trouble is the spring controller seems to be inverted when the character moves. When the character jumps, they don’t linger in place for a second they shoot up in the air with the mesh and when walking they stretch out in front of the mesh. I thought it was perhaps bone rotation or something but every bone I apply the spring controller to behaves the same way.

Here’s a quick screenshot of the animation blueprint. everything works fine other then that.

Maybe I’m just doing something wrong but It seems more like a bug to me.

Hi JoSilver,

I haven’t had a chance to set this up to test, but just out of curiousity, if you enter a negative value in the field, do you get the desired effect?

Thanks,

No setting any value negative leads to some wildly odd things but nothing inverts the motion, setting alpha to -1 is the same as 0. I’m including a illustration of what is happening . I’m honestly not sure if this is how it’s intended to work but it certainly looks very wrong. When the character moves forward very fast the spring controller bone fly’s forward rather then lag behind a bit.

65589-spring.png

I tried to reproduce this with a fencer lunging forward and applying the spring controller to the neck. The spring controller worked as expected as the body moved forward and the head stayed in place until max distance was reached. Then, at the end of the spring, the head snapped forward and recoiled back.

Also, here is a video showing how to use the spring controller node to represent soft physics (breast movement while walking.)

https://www.youtube.com/watch?v=1dY9PS7oIkc&oref=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D1dY9PS7oIkc&has_verified=1

If you follow this tutorial and the physics are not working as expected, let me know and I’ll continue to investigate.

Thanks

Well, I saw the video to see if I was doing something wrong but no everything looks fine. I made a video to demonstrate what is happening.

Sorry for the poor quality I don’t really have any editing software or decent screen capture software. I applied the spring controller to head and started walking around. As you can see the head is usually in front of the body rather than behind it.

I implemented my own Jiggle Physics solution in my animation blueprint, I ported some code I wrote to blueprints. Just on a straight port I was getting similar results. It calculates the velocity of the body and all I did was Multiply the velocity by -1 and readjust how It get the bone origin and BAM! exactly what I need. Trouble is the original code was meant for 2D so having a bit of trouble getting working 100% (it bugs out when the character rag dolls.)

Lowering damping and stiffness in the spring controller, made it work more as expect however I want to bump those values up a bit. I don’t know maybe the spring controller should have an option to invert it at some point.

I created My own Spring Controller Function for my Animation Blueprint It’s results are smoother then built in spring controller and can be inverted if need be. I thought I’d share the code. It hasn’t been strenuously tested but so far the results are look much better then with the spring controller. The Spring controller is super jittery and this is not.

/*SpringTime - Calculate the Spring Bone Displacement over time. Use Transform Bone, Translation, Add to existing, world space
	Fname SpringBone: The Name of the Bone.
	FVector& BoneJiggle: Vector to store Values over time.
	FVector& Velocity: Vector to store Values over time.
	FVector& PreVelocity: Vector to store Values over time.
	float Stiffness: The Bouncyness of Bone, 0 No Vibrations, 1 More Vibrartion, Keep between 0 and 1.
	float Damping: The Damping of Bone, 0 Instant Decay, 1 No Decay, Keep between 0 and 1.
	float Mass: The Mass of the bone.
	FVector Scale: The Scale of the Simulation, Scale up or down final results relative to parent bone space. Invert Results by setting negative.
	FVector MinStretch: Lower bounds for Stretch. If Bone Stretch exeeds bounds, Bone will be clampped.
	FVector MaxStretch: Upper bounds for Stretch. If Bone Stretch exeeds bounds, Bone will be clampped.
	float ErrorThreshold: If Velocity or acceletation exeeds this Value, reset. Catches Telports.
	bool UseVelocity: Use Velocity instead of Acceleration for Simulation, Causes Bone to be dragged.
	float DeltaTime: Time elapsed.
*/

FVector UPlayerAnimInstance::SpringTime(
FName SpringBone,
UPARAM(ref)FVector& BoneJiggle,
UPARAM(ref)FVector& Velocity,
UPARAM(ref)FVector& PrevVelocity,
float Stiffness, float Damping, float Mass,
FVector Scale,
FVector MinStretch,
FVector MaxStretch,
float ErrorThreshhold,
bool UseVelocity,
float DeltaTime)
{

/* Calculate Spring Bone Origin and Parent Trasform*/

	USkeletalMeshComponent* SK_Owner = GetOwningComponent();
	FName ParentBone = SK_Owner->GetParentBone(SpringBone);
	FTransform ParentTransform = SK_Owner->GetSocketTransform(ParentBone);
	FVector BoneOrigin = ParentTransform.Inverse().TransformVector(SK_Owner->GetSocketLocation(SpringBone));

	//Calculate Accelectation
	FVector acc = (((ParentTransform.TransformVector(BoneOrigin) - BoneJiggle) * Stiffness) / Mass) ;
	FVector newLoc;

	//Calculate Velocity at 60FPS
	PrevVelocity = Velocity;
	Velocity = (acc + Velocity) * FMath::Pow(Damping, (DeltaTime * 60.f));
	BoneJiggle += (Velocity)* (DeltaTime * 60.f);

	if (UseVelocity) {
		//Use Velocity, Bone Drags Behind
		if (Velocity.Size() > ErrorThreshhold) {
			PrevVelocity = Velocity;
			BoneJiggle = BoneOrigin = ParentTransform.TransformVector(BoneOrigin);
		}
		newLoc = ParentTransform.Rotator().UnrotateVector(-Velocity)*Scale;
		newLoc.X = FMath::Clamp(newLoc.X, MinStretch.X, MaxStretch.X);
		newLoc.Y = FMath::Clamp(newLoc.Y, MinStretch.Y, MaxStretch.Y);
		newLoc.Z = FMath::Clamp(newLoc.Z, MinStretch.Z, MaxStretch.Z);

		newLoc = ParentTransform.Rotator().RotateVector(newLoc);
	}
	else {
		//Use Accelaration, Bone is Springy
		acc = Velocity - PrevVelocity;
		if (acc.Size() > ErrorThreshhold) {
			PrevVelocity = Velocity;
			BoneJiggle = BoneOrigin = ParentTransform.TransformVector(BoneOrigin);
		}
		newLoc = ParentTransform.Rotator().UnrotateVector(-acc)*Scale;
		newLoc.X = FMath::Clamp(newLoc.X, MinStretch.X, MaxStretch.X);
		newLoc.Y = FMath::Clamp(newLoc.Y, MinStretch.Y, MaxStretch.Y);
		newLoc.Z = FMath::Clamp(newLoc.Z, MinStretch.Z, MaxStretch.Z);

		newLoc = ParentTransform.Rotator().RotateVector(newLoc);
	}

	return newLoc;
}

Thanks for posting your solution; I have converted it to the answer to the post. Also thanks for providing video of the issue you’ve been experiencing and including all the steps to your eventual solution. However, since the spring controller does appear to work if used in a particular way, I am not adding this as bug at this time.

After receiving another post concerned with this issue, I’ve entered the following bug report: UE-23383. When this issue is corrected in a future release of the engine we will notify you with an update to this post.

Thanks again for the feedback!

Well this sucks. I just encountered the same problem. Why is it that the bug is marked as “Won’t fix”? And with no explanation. The behavior of the physics is clearly bugged. When I move forward, the breast should not be drawn forward as well.
I am glad that JoSilver is one of the users who actually posted a solution when they found one. I’m going to copy his code and hope that it solves the problems