Tool animation takes a split second to display

I’ve set up an idle animation when wielding the wooden rod, but there is this split second display of the character holding the rod horizontally before playing the idle animation, as shown below.

It seems that it occurs because the Motor6D has not connected the right hand to the handle yet.

A hacky solution is to make the tool transparent before the idle animation, but that’s not the desired outcome. I was thinking of changing the default position of the wooden rod to match the start of the idle animation, since the horizontal position of the wooden rod is the initial position of the tool model in the character before I put it into the animation editor (I used Moon Animation Suite). However, changing the positions and orientations of the limbs removes the Motor6D, and when I tried to add a new Motor6D it changes the position of the limb, making it impossible to put it in the desired place.

I’ve also tried instantiating the Motor6D in the LocalScript first but there’s no difference.

Here’s the file explorer:

Screenshot 2020-12-29 at 11.31.11 PM
Screenshot 2020-12-29 at 11.30.47 PM

Here are the scripts:

LocalScript

local player = game:GetService("Players").LocalPlayer
local char = player.Character
local tool = script.Parent
local anims = {script.Parent.Idle, script.Parent.Hit}
local animator
local loadedAnims = {}
local debounce = true
local cooldown = 2

tool.Equipped:Connect(function()
	game.ReplicatedStorage.ConnectM6D:FireServer(tool.Handle)

	local HandleMotor6D = char.RightHand:WaitForChild("HandleMotor6D")

	HandleMotor6D.Part0 = char.RightHand
	HandleMotor6D.Part1 = tool.Handle

	animator = player.Character:WaitForChild("Humanoid"):WaitForChild("Animator")
	if not loadedAnims[1] then
		loadedAnims[1] = animator:LoadAnimation(anims[1])
	end

	loadedAnims[1]:Play()

end)

tool.Activated:Connect(function()

	if debounce then

		debounce = false
		animator = player.Character:WaitForChild("Humanoid"):WaitForChild("Animator")
		if not loadedAnims[2] then
			loadedAnims[2] = animator:LoadAnimation(anims[2])
		end
		loadedAnims[2]:Play()

		wait(cooldown)
		debounce = true
	end
end)

Script

game.ReplicatedStorage.ConnectM6D.OnServerEvent:Connect(function(plr, handle)
	local char = plr.Character

	local HandleMotor6D = Instance.new("Motor6D")
	HandleMotor6D.Name = "HandleMotor6D"
	HandleMotor6D.Parent = char.RightHand
	char.RightHand.HandleMotor6D.Part0 = char.RightHand
	char.RightHand.HandleMotor6D.Part1 = handle
	local RightGrip = char.RightHand:WaitForChild("RightGrip")
	RightGrip:Destroy()
	
end)

Haven’t tested this but just a theory, you could possibly disable the “RequiresHandle” property on the Tool, even with this disabled you could use the Handle, I believe the issue was the tool detecting if there was a handle in the tool so that it can be equipped, let alone activated. Now I may be wrong, but I believe it’s worth a try.

a) You may want to pre-load the animation to the client as opposed to starting up the animation on equip if you want the individual to pass it around a lot. If it is expected to be moved around a lot then it is just economically better to pre-load the animation and when detecting the tool equipped, the animation would play. It may also solve your issue… possibly.

b) I am uncertain of what you code is on the server side, but I highly recommend not sending tool.Handle through FireServer, as that will create a backdoor allowing exploiters to do anything they want in your game.

Do this instead:
local Handle = tool.Handle
:FireServer(Handle)

It makes a big difference trust me. The reason is because roblox scripts will determine what values are okay to be sent through to the server ie string, int, etc. If you attempt to send code then roblox will uplift the restriction for code being sent to the server, allowing exploiters to run any code they wish through your events.

c) If “Animator” is created through your server script then you should know that when you send information to the server it is not immediately resolved. If you are waiting for animator to be added then it could be delayed depending on how animator is created.

1 Like

How do I preload the animation? Do I load the animation on the server then pass the animation track to the client, or do I load the animation when the tool is in the backpack? I tried both ways but my code doesn’t work, maybe you can help me with the code :grimacing:?Thanks for the second tip!

It doesn’t work, it won’t play the idle animation

I haven’t really been able to test out the code so a lot of what I’m going to say is just theory to test bugs but from what it looks like here you are attempting to transform a nil variable unless I’ve read this wrong.

loadedAnims = {}

I don’t see any animations being inserted into that table and I’m pretty sure (I don’t work with tables often so correct me if I’m wrong), but you cannot transform a nil space into something. I also think there are certain rules for tables before editing objects inside of them but I could be wrong about that.

From my brief read it looks like it is attempting to load nil but if the script is only delayed then what I’m saying could just be completely wrong. My apologies if this was no help.

My animation plays but just delays, but I think you are on to something about preloading them, it could be that the loading takes a significant amount of time to cause the delay. I’m not sure how to preload though.

Correct me if I’m wrong, but I believe you should be able to pass the tool inside of a table to ContentProvider:PreloadAsync() and it will preload all the assets needed to use it. Of course if you’re storing the animations for the tool somewhere like ReplicatedStorage you could just pass that in a table to PreloadAsync and it would handle preloading every animation you needed.

game:GetService('ContentProvider'):PreloadAsync({game.Workspace.Tool})
or
game:GetService('ContentProvider'):PreloadAsync({game.ReplicatedStorage})

You’d need to implement a loading screen for this to work.

Api reference: ContentProvider | Documentation - Roblox Creator Hub

It looks better but it still has some delay.

I added the following in the LocalScript:

local ContentProvider = game:GetService("ContentProvider")
ContentProvider:PreloadAsync({script.Parent.Animations})

Now, it displays the default tool idle animation and the position of the tool has been offset using the tool grip editor. There’s still the delay though, which is possibly due to the time taken for the deletion of the weld and the creation of the Motor6D.