SmartBone 2 - Simulated Physics and Collision solution for Bones

refer to this‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎

2 Likes

Also, i’m currently using Smartbone 1 is there any way to prevent that false mesh deformation with Smartbone 1? Like editing any scripts or something else?

any fixes to this?
the bones are resetting rotation when i move

Use sine waves they are better,

2 Likes

do you have any links on where to do that?
I know those types of seas are made from using meshparts and editing the tri count, but i barley understand it; you got any scripts or testing places?

There are currently 2 ways to do that but both use the same formula, Editable and skinned mesh oceans.

here is the skinned mesh tutorial for beginers!

Hey! Im a very big noob at programming, where should I add this?

follow the configuration in the test place. there is a script in starterplayer and the modules in replicated storage. Then it runs any smart bone configured object in view

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