SmartBone 2 - Simulated Physics and Collision solution for Bones

New Smart Bone primitive for open source contribution!
create.roblox.com/store/asset/118242130994347
All setup and ready to go! You can configure the settings and use it for different things from a flag to a curtain!

It works perfectly with smartbone2 and I have turned it into other things like curtains

4 Likes

“If you see this report this as a bug, (NaN Calc world cframe)” Anyone know how to fix this?

1 Like

try commenting out the asserts, specifically this one. I had a similar issue.


Commenting out the asserts actually and data Logging used for debugging can increase your performance significantly.
I think it’s an issue with the bone actors code not properly disconnecting.
I made the modification to the runtime with this code to effectively handle when the object is not rendered locally.

render=RunService.Heartbeat:ConnectParallel(function(deltaTime)
	shared.FrameCounter += 1
	
	if shared.FrameCounter > FrameCounterOverflow then
		shared.FrameCounter = 0
	end

if (BonePhysics.ShouldDestroy or ForceDestroy) or RootObject.Parent==nil then
		task.synchronize()
		cleanup()
		Actor:Destroy()
		return
	end

I have an Idea! What if there could be support for ragdolling a skinned mesh?

Also I tried v.3.1 but it still doesn’t work, this is how my morphs tail originally was


but now for some reason it flattened the tail?

and im using rope constraint, if im not using rope constraint it scrunches up the tail

i really need help with this! Thank you!

I think the way you have your bones setup via blender may be incorrect

why is the discord link nowhere to be found?

OMG it works perfectly! TYSM Life Saver!

i added it to the README on github

its like this, im not sure what your asking me to do

Actually, the patch I mentioned earlier just causes the rig to yeet itself to nan coordinates.
This is what I propose to fix the bug.

local solution=CFrame.new(ParentBone.Position) * Rotation
		if ParentBone.ActiveWeld and ParentBone.RigidWeld then
			ParentBone.CalculatedWorldCFrame = ParentBone.WeldCFrame
		--elseif ShouldAverage then
		--	ParentBone.RotationSum += Vector3.new(Rotation:ToEulerAnglesXYZ())
		elseif not IsNaN(solution) then
			--ParentBone.CalculatedWorldCFrame = BoneParent.WorldCFrame:Lerp(CFrame.new(ParentBone.Position) * Rotation, alpha)
			ParentBone.CalculatedWorldCFrame = solution
		end

image

This is the line located inside the Bone module.

The above solution does not solve the problem.
I actually did just fix it through trial and error, The root cause of the problem is the Velocity becoming infinite.
My fix is constraining the Velocity of the bone through the StepPhysics function.

local VelocityConstraint=100
function Class:StepPhysics(BoneTree, Force: Vector3, Delta: number) -- Parallel safe
do end	
if self.Anchored then
		self.LastPosition = self.AnimatedWorldCFrame.Position
		self.Position = self.AnimatedWorldCFrame.Position
do end		

return
	end

	-- Custom forces per bone
	if self.Force or self.Gravity then
do end		
Force = (self.Gravity or BoneTree.Settings.Gravity)

		Force = (Force + (self.Force or BoneTree.Settings.Force)) * Delta
do end	
end
do end	

local Settings = BoneTree.Settings

	local Velocity = (self.Position - self.LastPosition)
	local Move = (BoneTree.ObjectAcceleration * Settings.Inertia)
	local WindMove = SolveWind(self, BoneTree, Velocity)
	local sum=Velocity * (1 - Settings.Damping) + Force + Move + WindMove
	local function constrainsum(v)
		local c=v
		if v.X>VelocityConstraint then
			c=Vector3.new(VelocityConstraint,v.Y,v.Z)
		elseif v.X<-VelocityConstraint then 
			c=Vector3.new(-VelocityConstraint,v.Y,v.Z)	
		end
		if c.Y>VelocityConstraint then
			c=Vector3.new(c.X,VelocityConstraint,c.Z)
		elseif c.Y<-VelocityConstraint then 
			c=Vector3.new(c.X,-VelocityConstraint,v.Z)	
		end
		if c.Z>VelocityConstraint then
			c=Vector3.new(c.X,c.Y,VelocityConstraint)
		elseif c.Z<-VelocityConstraint then 
			c=Vector3.new(c.X,c.Y,-VelocityConstraint)	
		end
		return c
	end
	self.LastPosition = self.Position
	self.Position += constrainsum(sum)
do end do end

end

With this when the bone reaches critical velocity it instead is clamped to normalized values. Which in my use case of sky diving forever which caused easy replication of the bug caused me to debug and solve the issue through my experience reading this code.
This ‘Class:StepPhysics’ function is located inside the Bone module.
So to perform the patch you would comment out the line that prints() 5000 times and apply the Velocity Constraint on the Physics step.
If the above patch does not work alone I have additionally done this change.

function Class:ApplyTransform(BoneTree)
do end
	
self.SolvedAnimatedCFrame = false

	if self.ParentIndex < 1 then
do end		
return
	end

	local ParentBone: IBone = BoneTree.Bones[self.ParentIndex]
	local BoneParent = ParentBone.Bone

	-- We check if the magnitude of rotation sum is zero because that tells us if it has already been averaged by another bone.
	-- if ParentBone.NumberOfChildren > 1 and ParentBone.RotationSum.Magnitude ~= 0 then
	-- 	local AverageRotation = ParentBone.RotationSum / ParentBone.NumberOfChildren
	-- 	ParentBone.CalculatedWorldCFrame = CFrame.new(ParentBone.Position)
	-- 		* CFrame.fromEulerAnglesXYZ(AverageRotation.X, AverageRotation.Y, AverageRotation.Z)
	-- 	ParentBone.RotationSum = Vector3.zero
	-- end

	if ParentBone and BoneParent then
		if ParentBone.Anchored and BoneTree.Settings.AnchorsRotate == false then -- Anchored and anchors do not rotate
			BoneParent.WorldCFrame = ParentBone.TransformOffset
		--elseif ParentBone.Anchored then -- Anchored and anchors rotate
		--	BoneParent.WorldCFrame = CFrame.new(ParentBone.Position) * ParentBone.CalculatedWorldCFrame.Rotation
		elseif not IsNaN(ParentBone.CalculatedWorldCFrame) then  -- Not anchored
			
			BoneParent.WorldCFrame = ParentBone.CalculatedWorldCFrame
		else 
		--	BoneParent.CFrame=ParentBone.OriginCFrame
			ParentBone.CalculatedWorldCFrame=BoneParent.WorldCFrame
		end
	end
do end
end

This checks if the Bone has a NaN and corrects its. Without the physics patch this causes the bones to remain stationary but continues to have the module propose a nan solution.
Together they should definitely work. I have not been able to break it since applying this fix.
That is given you have this part commented out.
image

The bug still happens, but instead of the full outfit disappearing it just stops moving, originally when this warn showed up the clothing disappeared. This only happens when I use teleporting stuff.

the apply Class:ApplyTransform(BoneTree) fix results in the smartbone object to appear still when the proposed position is NaN. The VelocityConstraint=100
function Class:StepPhysics section clamps the velocity to not exceed a certain value. Which keeps it from being NaN even when you teleport. As I am doing. I am currently not experiencing any bugs. But will take a look if I can replicate your issue.
In the end you may want to change the VelocityConstraint or scale it by the * (Settings.Damping) to effectively handle the variable Velocity Limits if there are any.

I’m using 4.0 and the simulation is jittery when the player is walking, is this a bug or did I do something wrong? I also for some reason can’t get 3.0 to work.

has this been fixed with the latest version of smartbone? Does anyone know how to make it work when its published? Please help.

whats/where is the VelocityConstraint?

There are a lot of Attributes you may wants to look at such as Dampening, Elasticity, Stiffness. High Elasticity may cause the object to be overly jittery

In this, I posted the modified functions SmartBone 2 - Simulated Physics and Collision solution for Bones - #391 by Magus_ArtStudios
It’s a two function modification one for the step physics and the other for the one that makes the bones stationary instead of NaN

I tried a lot of settings but it doesn’t seem to work. I’m using a lot of axis constraints and maybe it has something to do with it