One of the easier ways is to create 2 collision groups - for the ball and for the body parts. Set these 2 collision groups to be non-collidable and instead of using a Weld, use AlignPosition to align the HumanoidRootPart to the ball.
local PhysicsService = game:GetService("PhysicsService")
PhysicsService:RegisterCollisionGroup("PlayerBodyPart")
PhysicsService:RegisterCollisionGroup("PlayerBall")
PhysicsService:CollisionGroupSetCollidable("PlayerBodyPart", "PlayerBall", false)
game:GetService('Players').PlayerAdded:Connect(function(Player)
local GiveBall = function()
local Character = Player.Character or Player.CharacterAdded:Wait();
local Humanoid = Character:WaitForChild('Humanoid');
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart");
local RootAttachment = HumanoidRootPart:WaitForChild("RootAttachment")
local Ball = Instance.new("Part");
Ball.Name = "Ball"
Ball.Anchored = false;
Ball.Shape = Enum.PartType.Ball;
Ball.Size = Vector3.new(7, 7, 7.375);
Ball.Material = Enum.Material.Plastic;
Ball.CFrame = Player.Character.HumanoidRootPart.CFrame;
Ball.Transparency = 0.85;
Ball.Color = Color3.new(1, 0.32549, 0.337255);
Ball.CustomPhysicalProperties = PhysicalProperties.new(1, 2, 0.2, 1, 1);
Ball.CollisionGroup = "PlayerBall";
local BallAttachment = Instance.new("Attachment")
BallAttachment.Name = "BallAttachment"
BallAttachment.Parent = Ball
local RootAlignPosition = Instance.new("AlignPosition")
RootAlignPosition.Name = "RootAlignPosition"
RootAlignPosition.Attachment0 = RootAttachment
RootAlignPosition.Attachment1 = BallAttachment
RootAlignPosition.MaxForce = math.huge
RootAlignPosition.MaxVelocity = math.huge
RootAlignPosition.Parent = HumanoidRootPart
-- always parent after setting properties/children so there is
-- only one replication to the client as opposed to
-- x amount of property manipulation/children
Ball.Parent = Character;
Ball:SetNetworkOwner(Player);
local function onChildAdded(child)
if child:IsA("BasePart") == true and child ~= Ball then
child.CollisionGroup = "PlayerBodyPart"
end
end
for _, child in Character:GetChildren() do
task.spawn(onChildAdded, child)
end
Character.ChildAdded:Connect(onChildAdded)
end
GiveBall();
Player.CharacterAdded:Connect(function()
GiveBall();
end)
end)
It seems the onChildAdded function isn’t declaring the body parts as non-collidable with the ball. That, and the ball won’t respond to inputs; I believe it may need to be parented to the player.
Can you check if your body parts’ CollisionGroup to PlayerBodyPart and the ball to PlayerBall? If they are, it might be accessories that are still collidable, in which case you can switch to GetDescendants and DescendantAdded instead. Also ensure you are actually registering your collision groups and collidable behavior properly.
I tested the script before sending and works just fine on my end.
Figured it out! Your implementation DOES work, it just needed a single line declaring the ball’s parent as the character, then it works exactly as intended! Just inserted this at line 25 and it worked like a charm.
Ball.Parent = Character
Pretty sure this is because the ball is identified elsewhere as a child of the character, so it only acts accordingly when they’re properly parented. Thank you for the help!!!
Spoke too soon, new problem: it’s inconsistent, my line change did nothing
I don’t know quite why but my hunch is that the ball is spawning in after the character and the function is run late; it always breaks after respawning once.
I’ve tried a couple of different ways to implement this, but nothing seems to be getting every descendant part of the player model. I don’t know what’s not colliding correctly, since as I said before, results are inconsistent.
local function onDescendantAdded(descendant)
if descendant:IsA("BasePart") and descendant ~= Ball then
descendant.CollisionGroup = "PlayerBodyPart"
end
end
for _, descendant in Character:GetDescendants() do
task.spawn(onDescendantAdded, descendant)
end
Character.DescendantAdded:Connect(onDescendantAdded)
end
I’ve swapped out everything and even checked for changes to the parent at some point. Nada.
I meant your entire code. I’m running near similar code from what I posted before and I have no issues with it, even when respawning. Client script never changed from your original.
local PhysicsService = game:GetService("PhysicsService")
PhysicsService:RegisterCollisionGroup("PlayerBodyPart")
PhysicsService:RegisterCollisionGroup("PlayerBall")
PhysicsService:CollisionGroupSetCollidable("PlayerBodyPart", "PlayerBall", false)
game:GetService('Players').PlayerAdded:Connect(function(Player)
local function onCharacterAdded(Character)
local Humanoid = Character:WaitForChild('Humanoid');
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart");
local RootAttachment = HumanoidRootPart:WaitForChild("RootAttachment")
-- setup ball and collision group
local Ball = Instance.new("Part");
Ball.Name = "Ball"
Ball.Anchored = false;
Ball.Shape = Enum.PartType.Ball;
Ball.Size = Vector3.new(7, 7, 7.375);
Ball.Material = Enum.Material.Plastic;
Ball.CFrame = Character.HumanoidRootPart.CFrame;
Ball.Transparency = 0.85;
Ball.Color = Color3.new(1, 0.32549, 0.337255);
Ball.CustomPhysicalProperties = PhysicalProperties.new(1, 2, 0.2, 1, 1);
Ball.CollisionGroup = "PlayerBall";
-- setup ball attachment, parent, and network ownership
local BallAttachment = Instance.new("Attachment")
BallAttachment.Name = "BallAttachment"
BallAttachment.Parent = Ball
Ball.Parent = Character;
Ball:SetNetworkOwner(Player);
-- setup root AlignPosition
local RootAlignPosition = Instance.new("AlignPosition")
RootAlignPosition.Name = "RootAlignPosition"
RootAlignPosition.Attachment0 = RootAttachment
RootAlignPosition.Attachment1 = BallAttachment
RootAlignPosition.MaxForce = math.huge
RootAlignPosition.MaxVelocity = math.huge
RootAlignPosition.Responsiveness = math.huge
RootAlignPosition.Parent = HumanoidRootPart
-- set limbs/accessories to player collision group
local function onDescendantAdded(descendant)
if descendant:IsA("BasePart") == true and descendant:FindFirstAncestorOfClass("Tool") == nil and descendant ~= Ball then
descendant.CollisionGroup = "PlayerBodyPart"
end
end
for _, descendant in Character:GetDescendants() do
task.spawn(onDescendantAdded, descendant)
end
Character.DescendantAdded:Connect(onDescendantAdded)
end
Player.CharacterAdded:Connect(onCharacterAdded)
if Player.Character ~= nil then
task.spawn(onCharacterAdded, Player.Character)
end
end)
Pretty much only the child to descendant stuff was changed. aside from that, I can’t really say what will make a difference. I tried the script you posted here and was met with the same inconsistency.
In your explorer while you’re in game, can you double check these following things for me:
The ball’s CollisionGroup is set to PlayerBall.
All the parts’ CollisionGroup (excluding the ball), including accessories, are set to PlayerBodyPart.
The ball has a BallAttachment in the center (you can view it by clicking the Visible property or clicking the move tool).
The HumanoidRootPart has a RootAttachment and a RootAlignPosition.
The RootAlignPosition’s Attachment0 is set to the RootAttachment and the Attachment1 is set to BallAttachment (this is very important it is in this order).
The RootAlignPosition is Enabled with the MaxForce, MaxVelocity, and Responsiveness set to inf.
Let me know the results from the list above and send me your current server/client script.
Ok, your place file works perfectly on my end, so something’s up with mine.
All the body parts above the legs don’t have their collisions changed, and the rootpart is missing its alignposition. Don’t know why it’s not getting assigned. Does this place being r6 have anything to do with it?
It shouldn’t, since both R6 and R15 rigs have a Humanoid, HumanoidRootPart, and a RootAttachment inside the HumanoidRootPart (double check that for me since I don’t want to publish just to switch rig types), and all limbs are BaseParts. Double check if there are other scripts somehow interfering as well. Also, you still have not sent your version of the script, so I cannot help you at this point in time.
Right, sorry. I swapped out the old one with your implement but there are a couple here, one of which may be interfering. There’s a custom respawn behavior I put in that when disabled makes the place unplayable, but here it is.
I suspect this may be causing problems, but I can’t disable it wholesale. I’m currently trying other scripts in your place, along with r6, and it all works.
Check the output, are there any errors? In your current place, is your workspace.SignalBehavior set to Default or Immediate? If so, set it to Deferred and try again.
Setting it to deferred did the trick!! Output was giving absolutely nothing which is why I was having such a hard time pinpointing the problem. That should do it for now.
I don’t understand why the default SignalBehavior would cause the problem, was the workspace loading stuff in prematurely?
The Default behavior is Immediate, which is what old games before the change used. After the change, confusing as it is, the default property is actually Deferred, not Default. If you would like to read more on deferred behavior, read this post and any information linked: Deferred Engine Events
This affects when your connections gets called. In this case, Immediate mode will trigger your CharacterAdded code without your character even parented in the workspace yet, and internal code to function your character is not done. With Deferred mode, it will trigger at the next cycle and your code will basically run when your character is already in the workspace and the internal code is (almost always) done, avoiding race conditions.