Hello! I’m working on a game where your character is a custom Skinned Mesh character. When you eat fruit your character will get bigger. To achieve this I update the Humanoid Description’s properties (DepthScale, HeightScale, WidthScale, etc).
My first issue was that although I was scaling the mesh of my character, the armature/skeleton wasn’t being scaled. Which created weird issues like this:
For reference, this is what it’s suppose to look like:
I took me a long time to figure out, that I needed to scale the armature. Once I figured that out, I found a function on Devforum that achieves this:
local function scaleRecursive(part, instance, scaleFactor)
if instance:isA("Bone") then
local bone = instance
local parentCFrame
if (bone.Parent:IsA("Bone")) then -- parent can be either the MeshPart or another Bone
parentCFrame = bone.Parent.WorldCFrame
else
parentCFrame = bone.Parent.CFrame
end
local parentInPartCFrame = Monke.CFrame:Inverse() * parentCFrame
local parentInPartRotationCFrame = parentInPartCFrame - parentInPartCFrame.Position
local pivotOffsetInPartSpace = parentInPartRotationCFrame * bone.Position
local scaledPivotOffsetInPartSpace = pivotOffsetInPartSpace * Vector3.new(scaleFactor, scaleFactor, scaleFactor)
local partToParentRotationCFrame = parentInPartRotationCFrame:inverse()
bone.Position = partToParentRotationCFrame * scaledPivotOffsetInPartSpace
end
local children = instance:GetChildren()
for i = 1, #children do
local child = children[i]
scaleRecursive(part, child, scaleFactor)
end
end
My issue with this function is it Multiplies the existing size of the model with a scale factor. Which means for example if the model is scaled to 2 (twice it’s original size), and I want to set the scale to 3. Rather than increasing it’s size by 1, it will set the size to 2 * 3, which is 6. The issue is my game’s code works by setting the scale to a specific value and increasing that value when the player eats fruit.
So to sum up my question, how could I make this function set the scale rather than multiply it exponentially. I’m not very experienced with Skinned Meshes and Bones, so I figured I would ask here :P
If your current scale is 1.2 and you want to change it to 1.5, you need to multiply it by 1.5/1.2, so pass that to the function. This requires you to know both the old and new scale of course, but I assume you have that.
Thank you! That seems to work, although I noticed it still distorts my rig.
local function scaleRecursive(part, instance, scaleFactor)
if instance:isA("Bone") then
-- move bone local translation to part space, scale xyz in part space, then move back to bone parent space
local bone = instance
local parentCFrame
if (bone.Parent:IsA("Bone")) then -- parent can be either the MeshPart or another Bone
parentCFrame = bone.Parent.WorldCFrame
else
parentCFrame = bone.Parent.CFrame
end
local parentInPartCFrame = Monke.CFrame:Inverse() * parentCFrame
local parentInPartRotationCFrame = parentInPartCFrame - parentInPartCFrame.Position
local pivotOffsetInPartSpace = parentInPartRotationCFrame * bone.Position
local Scale = scaleFactor / CurrentSize
local scaledPivotOffsetInPartSpace = pivotOffsetInPartSpace * Vector3.new(Scale, Scale, Scale)
local partToParentRotationCFrame = parentInPartRotationCFrame:inverse()
bone.Position = partToParentRotationCFrame * scaledPivotOffsetInPartSpace
end
local children = instance:GetChildren()
for i = 1, #children do
local child = children[i]
scaleRecursive(part, child, scaleFactor)
end
end
For the Humanoid Description I am setting DepthScale, WidthScale, and HeightScale all to the scale of the gorilla.
Do you have any ideas for why this could be happening?
The code you found might not be right for how your character is structured. If you have a pure Bone-based character, where all the Bone instances are in a tree under the same part (e.g. your root part), then scaling the armature is a whole lot simpler, since you just need to scale Bone.Position. Bone.Position is aready a translation in the space of the parent. So no CFrame math is needed, just scaling Vector3s.
If you have more than one tree of Bones, parented to different parts that are connected with Motor6Ds, the situation gets more complicated.
Thank you! It seems to have a little bit better proportions although it is still pretty cursed XD
I think this definitely has to do with the animations not being designed for such a large character. Do you think there’s a way I could correct/alter the animations with code? Or could these issues be fixed in blender?
Does your animation have translation in the poses? Character animation usually has just pure joint rotations on all but the root-most joint, and rotations are not affected by scaling.
instead of applying the scale factor to the existing size, you can replace the size completely with the desired scale:
local function scaleRecursive(part, instance, scaleFactor)
if instance:IsA("Bone") then
local bone = instance
local parentCFrame
if bone.Parent:IsA("Bone") then -- parent can be either the MeshPart or another Bone
parentCFrame = bone.Parent.WorldCFrame
else
parentCFrame = bone.Parent.CFrame
end
local parentInPartCFrame = part.CFrame:Inverse() * parentCFrame
local parentInPartRotationCFrame = parentInPartCFrame - parentInPartCFrame.Position
local pivotOffsetInPartSpace = parentInPartRotationCFrame * bone.Position
local scaledPivotOffsetInPartSpace = pivotOffsetInPartSpace * Vector3.new(scaleFactor.X, scaleFactor.Y, scaleFactor.Z)
local partToParentRotationCFrame = parentInPartRotationCFrame:Inverse()
bone.Position = partToParentRotationCFrame * scaledPivotOffsetInPartSpace
end
local children = instance:GetChildren()
for i = 1, #children do
local child = children[i]
scaleRecursive(part, child, scaleFactor)
end
end
I don’t know what you mean by translation in the poses as I’m not very familiar with this topic. Although I do agree it’s a little strange as animations typically just change the degrees of joints. The only reason why I think it has to do with animations is because when it’s standing like a human it’s scaled correctly, and it’s only when it’s “all fours” animations are played that is has issues.
A handy scale API was recently released for models. Works perfectly on skinned meshes. There is noticeable ‘rubber banding’ when scaling a moving character though. Hopefully they’ll fix that soon.
Yeah that’s why I went with it. I use a function from HD admin as I felt it was the most reliable.
local function ChangeProperties(plr, properties) -- Forked from HD Admin
if Humanoid then
for a,b in pairs(Humanoid:GetChildren()) do
local targetName = string.lower(b.Name)
for propName, propValue in pairs(properties) do
propName = string.lower(propName)
if string.sub(targetName, -#propName) == propName then
b.Value = propValue
break
end
end
end
end
end
ChangeProperties(Player, {DepthScale = 1 * MonkeySize, HeightScale = 1 * MonkeySize, WidthScale = 1 * MonkeySize, HeadScale = 1 * MonkeySize})
Exactly, relying on the Humanoid Description just changes the mesh for Skinned Meshes, but it doesn’t change bones at all. That’s why I created this post as I’m unsure of a bug free way to scale bones correctly.
Indeed. The first thing I do with any Bone-based character is set Humanoid.AutomaticScalingEnabled to false, and manually set the HipHeight. This makes sure that the body scale value things aren’t messing with the character scaling. Those body width, height, depth, etc. are only for Motor6D-based avatars with the standard R15 parts and joint names; they will give you nothing but problems with a custom skinned character with Bones.
Alright so I disabled Humanoid.AutomaticScalingEnabled and I commented out all code involving the body scale values. I figured it would be easier to just change MeshPart.Size which ended up working well (feel free to suggest a better method). I still have my distortion issue which makes me believe something is wrong with the function? But then again the issues only occur when the “all fours” animations are playing. So I’m a little bit stumped on this one.
Alright so my new solution is to just use Character:ScaleTo() on the client, which doesn’t have it’s lag issues. This will just be a temporary fix until changing the Character on the server gets fixed, which is luckily already a known issue and is going to be fixed soon.
Keep in mind using Character:ScaleTo() doesn’t replicate to the server, so if you have any weapons or features that requires the server to handle, I recommend waiting until this is fixed in a few days.