Its ok because I seem to have it fixed, its just that it only looks right on one axis (see video above)
I didn’t notice this at first, but if you look frame-by-frame in the last video you sent, you can see that the arms actually slightly shoot backward towards your character and then immediately turn around to go the other way. Very strange.
Questions
- What is being done on the server, and what on the client? Is the arm effect being done on the client as well as the NPC movement?
- Can you
print()
thearm.Size
andarm.Orientation
when they are first spawned (right before you start to move them, when they are inWorkspace
and positioned at the NPC). I believe therngCF:ToWorldSpace()
could be getting “corrupt” due to some unexpected CFrame of that part, causing the 2nd point of the quadratic bezier to be incorrect (which is what is being seen in the video you sent). Post the results for both the direction that it works and where it doesn’t work anymore. - Also, what is the
Size
andOrientation
of the original arm that is inReplicatedStorage
while in Studio?
I reproduced the NPC (using your BodyPosition+BodyGyro code) to test it with that instead of my own character and it works for me so far:
The arms are being cloned, positioned and all of that on the server. The only thing on the client is the movement of the NPC.
Alright, here are the results:
(26.330911636353, 4.4673457145691, 29.651132583618) (0, 0, 0) (1,1,2)
--ORDER: Position, Orientation, Size
This varied every now and them by a few decimals in all of the position numbers. Probably floating point stuff?
Size: Vector3.new(1,1,2)
Orientation: Vector3.new(0,180,0)
How are you positioning them? Are you just placing them at the root part cframe and then doing the function?
This is unlikely to be the issue, but just for the thought, there will technically be a network delay so the server will be behind in where the NPC actually is. I think this could only cause a problem if you somehow have a variable that is not being updated correctly or only updated once.
Does the orientation print different numbers when you turn in a different direction? The 2nd value (Y) of that orientation that is printed should change between -180 and 180 depending on the NPC’s direction.
Yes. I am doing the arm effect on the client though, but I don’t think it matters unless the first thing I said about network delay is the actual problem. Here is my full code:
LocalScript inside StarterCharacterScripts
local util = require(game.ReplicatedStorage:WaitForChild("Utilities"))
local player = game:GetService("Players").LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local playerRoot = character:WaitForChild("HumanoidRootPart")
local dummy = workspace:WaitForChild("Dummy")
local hrp = dummy:WaitForChild("HumanoidRootPart")
local bodyPos: BodyPosition = hrp:WaitForChild("BodyPosition")
bodyPos.MaxForce = Vector3.new(5500, 20000, 5500)
local gyro: BodyGyro = hrp:WaitForChild("BodyGyro")
gyro.D = 300
gyro.MaxTorque = Vector3.new(0, 10000, 0)
local isAttacking = false
game:GetService("RunService"):BindToRenderStep("MoveDummy", Enum.RenderPriority.Character.Value+1, function()
local offset = nil
if isAttacking then
offset = Vector3.new(0, 0, -3.5)
bodyPos.D = 300
else
offset = Vector3.new(-2, 2, 2.5)
bodyPos.D = 700
end
local targetPos = (playerRoot.CFrame * offset)
bodyPos.Position = targetPos
gyro.CFrame = playerRoot.CFrame
end)
--simulate an attack every 5 seconds
while task.wait(5) do
isAttacking = true
for i = 1, 40 do
task.spawn(function()
local arm = game.ReplicatedStorage.Arm:Clone()
arm.Transparency = 0.1
arm.Parent = workspace
arm.CFrame = hrp.CFrame
--print(arm.Position, arm.Orientation, arm.Size)
-- bezier curve
util.CreateBezierCurveArm(arm, (hrp.Position + (hrp.CFrame.LookVector * 3.5)))
end)
task.wait(0.15)
end
isAttacking = false
end
Script inside ServerScriptService
game:GetService("Players").PlayerAdded:Connect(function(player: Player)
local character = player.Character or player.CharacterAdded:Wait()
local playerRoot = character:WaitForChild("HumanoidRootPart")
local dummy = game.ReplicatedStorage.Dummy:Clone()
for i, child in ipairs(dummy:GetDescendants()) do
if child:IsA("BasePart") then
game:GetService("PhysicsService"):SetPartCollisionGroup(child, "NoCollision")
end
end
local hrp: Part = dummy:FindFirstChild("HumanoidRootPart")
local bodyPos: BodyPosition = Instance.new("BodyPosition", hrp)
local gyro: BodyGyro = Instance.new("BodyGyro", hrp)
dummy.Parent = workspace
hrp:SetNetworkOwner(player)
end)
ModuleScript inside ReplicatedStorage
local Utilities = {}
function Utilities.CreateBezierCurveArm(arm, endPoint)
local function QuadraticBezier(Time,Point0,Point1,Point2)
return (1-Time)^2*Point0+2*(1-Time)*Time*Point1+Time^2*Point2; -- bezier curve path
end
local rng = Random.new()
local function positiveOrNegative(num)
local num2 = rng:NextInteger(1,2)
if num2 == 1 then
return num
else
return -num
end
end
local randomCFrameOffset = CFrame.new(positiveOrNegative(rng:NextNumber(3,5)),positiveOrNegative(rng:NextNumber(2,2.5)), 0)
local rngCF = arm.CFrame:ToWorldSpace(randomCFrameOffset)
local pivotCFrame = CFrame.new(endPoint)
local armStartCf = arm.CFrame
local timeElapsed = 0
local speed = 1
local duration = (armStartCf.p - pivotCFrame.Position).Magnitude / speed
local tweenDelay = .1
local TS = game:GetService("TweenService")
while timeElapsed < duration do
local progress = timeElapsed / duration
local pointAtTimeElapsed = QuadraticBezier(progress, armStartCf.p, rngCF.p, pivotCFrame.p)
local lookAt = QuadraticBezier(progress+0.01, armStartCf.p, rngCF.p, pivotCFrame.p)
if timeElapsed == 0 then
arm.CFrame = CFrame.new(pointAtTimeElapsed, QuadraticBezier(progress+.01, armStartCf.p, rngCF.p, pivotCFrame.p)) -- Makes the arm face the right way
end
timeElapsed += speed
local tween = TS:Create(arm,TweenInfo.new(tweenDelay),{CFrame = CFrame.new(pointAtTimeElapsed,lookAt)})
tween:Play()
wait(tweenDelay)
end
local tween = TS:Create(arm,TweenInfo.new(.4),{Transparency = 1})
tween:Play()
tween.Completed:Wait()
arm:Destroy()
end
return Utilities
Does any of that code look unexpectedly different from any of your code, aside from my arm effect being local and that my stuff is hard-coded for the sake of testing?
I have 0 clue how but it just started working after I made one change to where I initially position the arm:
-- BEFORE
arm.CFrame = (hrp.CFrame * CFrame.new(0,0.5,0))
-- I completely forgot to check this line, THE ENTIRE TIME...
-- I guess I tried to offset it upwards by 0.5 studs, but this code obviously doesn't work
-- I didn't really have a good grasp on how any of this worked until this post sooo
-- AFTER
arm.CFrame = hrp.CFrame
It does now!
I changed my code to do that instead, but mine still worked normally like before. Not exactly sure why that would break it (unless your hrp
is rotated+sized differently than mine), but as long as it’s working now, I’m not complaining