WeldConstraint Position Problem

Hello! I’m struggling with making a system, that equips Halo (animated with TweenService) on the player’s head.

  1. What do you want to achieve?
    I want Halo to be cloned to the character’s head with Tween animation.

  2. What is the issue?
    My script works perfectly fine, however there is a strange thing with Halo’s position when its being cloned to the character’s head, it makes a feeling that it’s like being “Anchored” to the position.

image - Before moving.

- After moving.

- Here is a video.

  1. What solutions have you tried so far?

It works perfectly with Weld and WeldConstraint if Halo is static (without Tween), but I want it to be animated.
I tried searching on YT and tried to make a Handle for it, but It didn’t work.

Here is a snippet of my code, which is being used:
(To clone it to the character’s head)

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local eventFolder = game.ReplicatedStorage.Events

local halo = ReplicatedStorage.Halo

eventFolder.EquipHalo.OnServerEvent:Connect(function(plr)
	
	local head = plr.Character:FindFirstChild("Head")
-----------------------------------------------------------
	
	local cloneHalo = ReplicatedStorage.Halo:Clone()
	cloneHalo.Parent = head
	cloneHalo:PivotTo(head.CFrame)
	local weldHalo = Instance.new("WeldConstraint")
	weldHalo.Parent = cloneHalo
	weldHalo.Part0 = cloneHalo
	weldHalo.Part1 = head

	
	print("Weld Done!")
	
	cloneHalo.Position = head.Position + Vector3.new(0, 0.7, 0)
	
end)

Here is a code which is a child of Halo
(Animation)

local TweenService = game:GetService("TweenService")
local halo = script.Parent

local rotation = {}
rotation.Orientation = halo.Orientation + Vector3.new(0, 360, 0)

local tweenInfo = TweenInfo.new(
	
	8,
	Enum.EasingStyle.Linear,
	Enum.EasingDirection.InOut,
	-1,
	false,
	0	
)

local tween = TweenService:Create(halo,tweenInfo,rotation):Play()


---------- Tween 2 (Up and Down) ----------
local upAndDw = {}
upAndDw.Position = halo.Position + Vector3.new(0, 0.2, 0)

local tweenInfo2 = TweenInfo.new(
	
	4,
	Enum.EasingStyle.Sine,
	Enum.EasingDirection.InOut,
	-1,
	true,
	0
)

local tweenUaD = TweenService:Create(halo,tweenInfo2, upAndDw):Play()

P.S I’m new to DevForum, so If I made a mistake in formatting my text, let me know!
Also, if my code is messy or if it’s possible optimize it, I would be happy to hear that!

Thank you!

You’re setting the world position of the halo instead of the weld’s offset: this leads to the halo’s movement not being relative to the player so it kinda drifts.

First of all, weldconstraints do not have editable offset components so make sure weldHalo is just a “Weld” instead of “WeldConstraint”
Secondly, instead of

cloneHalo.Position = head.Position + Vector3.new(0, 0.7, 0)

We’re gonna have to edit the weld’s offset:

weldHalo.C0 = CFrame.new(0, 0.7, 0)

I would recommend doing something like this for your animation script (ensuring the RunContext is set to client to ensure it doesn’t create server lag):

local halo = script.Parent
local weld = halo.Weld
local rs = game:GetService("RunService")

rs.RenderStepped:Connect(function() -- every frame run this function
	weld.C1 = CFrame.new(0, math.sin(tick())*0.1, 0) * CFrame.Angles(0, tick() * math.pi/4, 0)
end)

If you need any clarification I’ll be happy to help.

yes, weld is better

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local eventFolder = game.ReplicatedStorage.Events

local halo = ReplicatedStorage.Halo

eventFolder.EquipHalo.OnServerEvent:Connect(function(plr)
	local head = plr.Character.Head
	-----------------------------------------------------------

	local cloneHalo = halo:Clone()
	cloneHalo.Parent = head
	
	local weldHalo = Instance.new("Weld")
	weldHalo.Parent = cloneHalo
	weldHalo.Part0 = cloneHalo
	weldHalo.C0 = CFrame.new(0, -0.7, 0)
	weldHalo.Part1 = head
	
	print("Weld Done!")
end)
local TweenService = game:GetService("TweenService")
local halo = script.Parent

local weld: Weld = halo:WaitForChild("Weld")

-- up and down
TweenService:Create(weld, TweenInfo.new(
		1,
		Enum.EasingStyle.Linear,
		Enum.EasingDirection.InOut,
		-1,
		true,
		0	
	), {
		["C0"] = CFrame.new(0, weld.C0.Y - 0.2, 0)
	}
):Play()

-- rotation.. 
TweenService:Create(weld, TweenInfo.new(
	1,
	Enum.EasingStyle.Linear,
	Enum.EasingDirection.InOut,
	-1,
	false,
	0	
	), {
		["C1"] = CFrame.Angles(0, math.rad(180), 0)
	}
):Play()

So, I might try to make this through RemoteEvents from client to client? (Halo visible for player only?)

No, since the script will run for everybody there is no need to send data across clients.

Oh!!! Thank you!!!
This one works perfectly!!!

So, the problem was in WeldConstraint, and I setted it’s position (Vector3 or CFrame to players’s head) and it as a Halo’s world position as mentioned @goldenguy9 ?

It’s actually pretty hard for me to understand because I never met with these problems before and across-data scripts are a bit tough for me :sweat:

So, making a script (aka. RunContext) to client, makes it work for everyone?

There are two different types of client scripts in ROBLOX. The first, which you are most likely familiar with is LocalScript. This only runs for you if it is inside certain client side folders or your own character model. As such, it won’t run for anyone else but you.

However, if you have a regular script with its “RunContext” set to client, it will run on every players’ computer as long as it exists for them (so not in a location that only exists for you, like GUI).

Therefore for certain things like visual effects, it’s easier to use one of these instead of using a remote event since they don’t require data from the server to work.

I still recommend setting RunContext to client in this case to prevent server lag, even if you didn’t use my approach.

Oh, so RunContext doesn’t turn Script into a Local Script??
It’s the same Script, but it runs like a Local Script?

Oh, I got it!
Your solution worked as well!
Thank you! @goldenguy9 , @nds_w

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.