Hey, I wanted to make a system where equipped towers in my tower defense game would follow the player kind of like pets in a simulator. They follow the way I want but only in 2 directions. The other 2 directions have them misaligned and all weird. I also wanted to have them look at the tower Infront of them so it could be a smoother “train” per say.
local runService = game:GetService("RunService")
local towers = ReplicatedStorage:WaitForChild("Towers")
local towerPets = {}
-- Load the selected towers and place them in the workspace
for i, v in pairs(playerData.SelectedTowers) do
local tower = ReplicatedStorage.Towers:FindFirstChild(v):Clone()
tower:WaitForChild("HumanoidRootPart").CFrame = game.Players.LocalPlayer.Character:WaitForChild("HumanoidRootPart").CFrame
tower.Parent = workspace
table.insert(towerPets, tower)
end
-- Function to create a tween for smooth movement
local function createTween(target, goal, time)
local tweenInfo = TweenInfo.new(time, Enum.EasingStyle.Linear, Enum.EasingDirection.Out)
return TweenService:Create(target, tweenInfo, goal)
end
-- Function to get the ground position below a given point using raycasting
local function getGroundPosition(position)
local rayOrigin = position
local rayDirection = Vector3.new(0, -1000, 0)
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = towerPets
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if raycastResult then
return raycastResult.Position
else
return position
end
end
-- Main loop to continuously update positions
runService.RenderStepped:Connect(function(deltaTime)
local playerCFrame = game.Players.LocalPlayer.Character.PrimaryPart.CFrame
local previousCFrame = playerCFrame * CFrame.new(0, 0, 2) -- Start directly behind the player
for i, tower in ipairs(towerPets) do
local humanoidRootPart = tower:WaitForChild("HumanoidRootPart")
local offset = CFrame.new(0, 0, 1.5) -- Spacing of 2 studs apart
-- Calculate the target position based on the previous position and offset
local targetCFrame = previousCFrame * offset
-- Get the ground position below the target position
local groundPosition = getGroundPosition(targetCFrame.Position)
targetCFrame = CFrame.new(groundPosition) * CFrame.Angles(0, targetCFrame:ToEulerAnglesXYZ())
createTween(humanoidRootPart, {CFrame = targetCFrame}, 0.1):Play()
-- Update the previous position and orientation for the next tower
previousCFrame = humanoidRootPart.CFrame
end
end)
I tried using chatgpt for this but it took forever to get working like it is right now and it never figured out the rotation that I wanted.