Hello developers
I’ve been trying to develop a realistic goalkeeper using IK, BodyVelocity and AlignOrientation. (Ragdoll as well)
The problem emerges when I use ragdoll when the GK is diving.
Here is a video
The results of the radgoll are not I was looking for. I’m looking for the ragdoll follows the dive and the orientation don’t change so much like in real life or in videogames.
This is an example of I want:
The ragdoll’s script (it’s a module script) for the GK is this:
local module = {}
local PhysicsService = game:GetService("PhysicsService")
local function getNearestPlayer( position )
local Players = game.Players:GetChildren();
local dist = math.huge;
local ret = nil;
for i=1,#Players do
local Player = Players[i];
local Character = Player.Character;
if ( Character ~= nil ) then
local Root = Character:FindFirstChild("HumanoidRootPart");
if ( Root ~= nil ) then
local t = (position - Root.Position).magnitude;
if ( t < dist ) then
dist = t;
ret = Player;
end
end
end
end
return ret;
end
local RootLimbData = {
{
["WeldTo"] = "LowerTorso",
["WeldRoot"] = "HumanoidRootPart",
["AttachmentName"] = "Root",
["NeedsCollider"] = false,
["UpperAngle"] = 10
},
{
["WeldTo"] = "UpperTorso",
["WeldRoot"] = "LowerTorso",
["AttachmentName"] = "Waist",
["ColliderOffset"] = CFrame.new(0, 0.5, 0),
["UpperAngle"] = 0
},
{
["WeldTo"] = "Head",
["WeldRoot"] = "UpperTorso",
["AttachmentName"] = "Neck",
["ColliderOffset"] = CFrame.new(),
["UpperAngle"] = 20
},
{
["WeldTo"] = "LeftUpperLeg",
["WeldRoot"] = "LowerTorso",
["AttachmentName"] = "LeftHip",
["ColliderOffset"] = CFrame.new(0, -0.5, 0)
},
{
["WeldTo"] = "RightUpperLeg",
["WeldRoot"] = "LowerTorso",
["AttachmentName"] = "RightHip",
["ColliderOffset"] = CFrame.new(0, -0.5, 0)
},
{
["WeldTo"] = "RightLowerLeg",
["WeldRoot"] = "RightUpperLeg",
["AttachmentName"] = "RightKnee",
["ColliderOffset"] = CFrame.new(0, -0.5, 0)
},
{
["WeldTo"] = "LeftLowerLeg",
["WeldRoot"] = "LeftUpperLeg",
["AttachmentName"] = "LeftKnee",
["ColliderOffset"] = CFrame.new(-0.05, -0.5, 0)
},
{
["WeldTo"] = "RightUpperArm",
["WeldRoot"] = "UpperTorso",
["AttachmentName"] = "RightShoulder",
["ColliderOffset"] = CFrame.new(0.05, 0.45, 0.15),
},
{
["WeldTo"] = "LeftUpperArm",
["WeldRoot"] = "UpperTorso",
["AttachmentName"] = "LeftShoulder",
["ColliderOffset"] = CFrame.new(0, 0.45, 0.15),
},
{
["WeldTo"] = "LeftLowerArm",
["WeldRoot"] = "LeftUpperArm",
["AttachmentName"] = "LeftElbow",
["ColliderOffset"] = CFrame.new(0, 0.125, 0),
["UpperAngle"] = 10
},
{
["WeldTo"] = "RightLowerArm",
["WeldRoot"] = "RightUpperArm",
["AttachmentName"] = "RightElbow",
["ColliderOffset"] = CFrame.new(0, 0.125, 0),
["UpperAngle"] = 10
},
{
["WeldTo"] = "RightHand",
["WeldRoot"] = "RightLowerArm",
["AttachmentName"] = "RightWrist",
["ColliderOffset"] = CFrame.new(0, 0.125, 0),
["UpperAngle"] = 0
},
{
["WeldTo"] = "LeftHand",
["WeldRoot"] = "LeftLowerArm",
["AttachmentName"] = "LeftWrist",
["ColliderOffset"] = CFrame.new(0, 0.125, 0),
["UpperAngle"] = 0
},
{
["WeldTo"] = "LeftFoot",
["WeldRoot"] = "LeftLowerLeg",
["AttachmentName"] = "LeftAnkle",
["NeedsCollider"] = false,
["UpperAngle"] = 0
},
{
["WeldTo"] = "RightFoot",
["WeldRoot"] = "RightLowerLeg",
["AttachmentName"] = "RightAnkle",
["NeedsCollider"] = false,
["UpperAngle"] = 0
},
}
local RootPart = nil;
local MotorList = {};
local GlueList = {};
local ColliderList = {};
-- Función para habilitar el ragdoll
function module:activate(Char)
print("Ragdolling");
local Character = Char;
local Humanoid = Char:FindFirstChild("Humanoid");
local HumanoidRoot = Char:FindFirstChild("HumanoidRootPart");
if ( HumanoidRoot == nil ) then
print("Cannot create ragdoll");
return;
end
local Position = Char.HumanoidRootPart.Position;
Humanoid.PlatformStand = true;
local ActivateOnDeath = Instance.new("BoolValue"); --ActivateOnDeath.Value = true
-- Handle death specific ragdoll. Will Clone you, then destroy you.
local RagDollModel = Character;
if ActivateOnDeath.Value then
Character:FindFirstChild("HumanoidRootPart"):Destroy();
Character.Archivable = true;
RagDollModel = Character:Clone();
RagDollModel.Name = "RagDoll";
local t = RagDollModel:GetChildren();
for i=1,#t do
local t2 = t[i];
if ( t2:IsA("Script") or t2:IsA("LocalScript") ) then
t2:Destroy();
end
end
spawn(function()
wait();
RagDollModel.Humanoid.PlatformStand = true;
--game.Debris:AddItem(RagDollModel, 10);
end)
RagDollModel.Humanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None;
RagDollModel.Humanoid.HealthDisplayType = Enum.HumanoidHealthDisplayType.AlwaysOff;
RagDollModel.Humanoid.Health = 0;
RagDollModel.Parent = game.Workspace;
local RagDollPointer = Instance.new("ObjectValue");
RagDollPointer.Value = RagDollModel;
RagDollPointer.Name = "RagDoll";
RagDollPointer.Parent = Character;
end
local ApplyRandomVelocity = Instance.new("BoolValue"); ApplyRandomVelocity.Value = true
local Force = Instance.new("NumberValue"); Force.Value = 20
local WeldHead = Instance.new("BoolValue"); WeldHead.Value = true
-- Reglue The Character
for i=1,#RootLimbData do
local limbData = RootLimbData[i];
local partName = limbData["WeldTo"];
local weldName = limbData["WeldRoot"];
local PartTo = RagDollModel:FindFirstChild(partName);
local WeldTo = RagDollModel:FindFirstChild(weldName);
if ( PartTo ~= nil and WeldTo ~= nil ) then
if ( RagDollModel ~= nil ) then
if ( ApplyRandomVelocity.Value ) then
local scale = Force.Value;
local vecX = (math.random()-math.random())*scale;
local vecY = (math.random()-math.random())*scale;
local vecZ = (math.random()-math.random())*scale;
--PartTo.Velocity = PartTo.Velocity + Vector3.new(vecX, vecY, vecZ);
end
PartTo.Parent = RagDollModel;
end
-- Create New Constraint
local UpperAngle = limbData["UpperAngle"];
local Joint = Instance.new("BallSocketConstraint");
if ( (UpperAngle ~= nil and UpperAngle == 0) or (WeldHead.Value and partName == "Head") ) then
Joint = Instance.new("HingeConstraint");
Joint.UpperAngle = 0;
Joint.LowerAngle = 0;
end
Joint.Name = limbData["AttachmentName"];
Joint.LimitsEnabled = true;
if not Joint:IsA("HingeConstraint") then
Joint.TwistLimitsEnabled = true;
end
Joint.Attachment0 = PartTo:FindFirstChild(Joint.Name .. "RigAttachment");
Joint.Attachment1 = WeldTo:FindFirstChild(Joint.Name .. "RigAttachment");
Joint.Parent = PartTo;
GlueList[#GlueList+1] = Joint;
if ( UpperAngle ~= nil ) then
Joint.UpperAngle = UpperAngle;
end
-- Destroy the motor attaching it
local Motor = PartTo:FindFirstChildOfClass("Motor6D");
if ( Motor ~= nil ) then
if ( Humanoid.Health <= 0 ) then
Motor:Destroy();
else
MotorList[#MotorList+1] = { PartTo, Motor };
Motor.Parent = nil;
end
end
-- Create Collider
local needsCollider = limbData["NeedsCollider"];
if ( needsCollider == nil ) then
needsCollider = true;
end
if ( needsCollider ) then
local B = Instance.new("Part");
B.CanCollide = true;
B.TopSurface = 0;
B.BottomSurface = 0;
B.formFactor = "Symmetric";
B.Size = Vector3.new(0.7, 0.7, 0.7);
B.Transparency = 1;
B.BrickColor = BrickColor.Red();
B.Parent = RagDollModel;
local W = Instance.new("Weld");
W.Part0 = PartTo;
W.Part1 = B;
W.C0 = limbData["ColliderOffset"];
W.Parent = PartTo;
ColliderList[#ColliderList+1] = B;
end
end
end
-- Destroy Root Part
local root = Character:FindFirstChild("HumanoidRootPart");
if ( root ~= nil ) then
RootPart = root;
if ( Humanoid.Health <= 0 ) then
RootPart:Destroy();
else
RootPart.Parent = nil;
end
end
-- Delete all my parts if we made a new ragdoll
if ( RagDollModel ~= Character ) then
print("Deleting character");
local children = Character:GetChildren();
for i=1,#children do
local child = children[i];
if ( child:IsA("BasePart") or child:IsA("Accessory") ) then
child:Destroy();
end
end
end
-- Give player physics
local GivePlayerPhysics = Instance.new("BoolValue"); GivePlayerPhysics.Value = true
local ForceNearestPlayer = Instance.new("BoolValue")
if ( GivePlayerPhysics.Value ) then
local PlayerPhysics = Char;
if ( ForceNearestPlayer.Value ) then
PlayerPhysics = getNearestPlayer( Position );
end
local Children = RagDollModel:GetChildren();
for i=1,#Children do
local Child = Children[i];
if ( Child:IsA("BasePart") ) then
Child:SetNetworkOwner(PlayerPhysics);
end
end
end
-- Copy plugins into ragdoll
--local Plugins = script.Plugins:GetChildren();
--for i=1,#Plugins do
-- local Plugin = Plugins[i];
-- local Copy = Plugin:Clone();
-- if ( Copy:IsA("Script") ) then
--- Copy.Disabled = false;
-- end
-- Copy.Parent = RagDollModel;
--end
end
I’ve tried to modify the alignOrientation (Didn’t work) and I was thinking in a solution but my mind is clear rn.
If you have any suggestions or ideas, it’ll be greatly appreciated!
Thanks for reading!