JIT
making ik foot targets visible to all players in your script
My script has a folder named "IKArmTargets " that is in the workspace. Each player has two sets of Inverse kinematic feet or arms, whichever way you look at it, that are used to maneuver. The only downside that I'm trying to figure out is how I can make it so each player can see each other's foot targets left and right? All they can see is the starter character I made for all players, not the IK foot targets. Here's the script: -- Enhanced R6 IK with Wall Walking Physics local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local Players = game:GetService("Players") local Workspace = game:GetService("Workspace") -- Configuration local FOOT_HEIGHT_OFFSET = 0.3 local MAX_STEP_HEIGHT = 0.4 local STEP_SPEED = 11 local FOOT_DISTANCE = 1.5 local FOOT_WIDTH = 1.5 local ARM_SWING_AMOUNT = 10 local LEG_LERP_SPEED = 20.0 local ARM_LERP_SPEED = 15.0 local MOVE_SPEED = 18 local TURN_SPEED = 43 local GROUND_CHECK_DISTANCE = 0.5 local REQUIRED_GROUND_ANGLE = math.rad(45) local CLIMB_CHECK_DISTANCE = 3.0 local JUMP_POWER = 10 local JUMP_BOUNCE = 10 local ANCHOR_DELAY = 0 local ARM_ANCHOR_HEIGHT = 0.5 local CLIMB_GRAB_DISTANCE = 5 local CLIMB_PULL_FORCE = 5 local SPIDER_LEG_SPREAD = 5 -- Wall Walking Physics local WALL_WALK_GRAVITY = 1 local WALL_JUMP_FORCE = 10 local WALL_STICK_FORCE = 300 local CAMERA_LERP_SPEED = 0 local MAX_WALL_ANGLE = math.rad(45) local WALL_CHECK_DISTANCE = 5 -- Services local Players = game:GetService("Players") local Camera = workspace.CurrentCamera -- Create shared folders for all players to see local sharedIKFolder = Instance.new("Folder") sharedIKFolder.Name = "SharedIKTargets" sharedIKFolder.Parent = workspace -- Persistent arm storage local armTargetsFolder = Instance.new("Folder") armTargetsFolder.Name = "IKArmTargets" armTargetsFolder.Parent = workspace -- Get character local player = Players.LocalPlayer local character = player.Character or player.CharacterAdded:Wait() local humanoid = character:WaitForChild("Humanoid") local rootPart = character:WaitForChild("HumanoidRootPart") -- Wall Walking State local currentWallNormal = Vector3.new(0, 1, 0) local isWallWalking = false local lastWallNormal = Vector3.new(0, 1, 0) -- Function to create or get arm targets with collision local function ensureArmTargets() local leftArmTarget = armTargetsFolder:FindFirstChild("LeftArmIKTarget") local rightArmTarget = armTargetsFolder:FindFirstChild("RightArmIKTarget") if not leftArmTarget then leftArmTarget = Instance.new("Part") leftArmTarget.Name = "LeftArmIKTarget" leftArmTarget.Anchored = true leftArmTarget.CanCollide = false leftArmTarget.Transparency = 0.5 leftArmTarget.Color = Color3.fromRGB(255, 0, 0) leftArmTarget.Size = Vector3.new(1, 1, 1) leftArmTarget.Parent = armTargetsFolder local collision = Instance.new("BallSocketConstraint") collision.Parent = leftArmTarget end if not rightArmTarget then rightArmTarget = leftArmTarget:Clone() rightArmTarget.Name = "RightArmIKTarget" rightArmTarget.Color = Color3.fromRGB(0, 0, 255) rightArmTarget.Parent = armTargetsFolder end return leftArmTarget, rightArmTarget end -- Function to setup character parts with shared foot targets local function setupCharacterParts() local leftLeg = character:FindFirstChild("Left Leg") local rightLeg = character:FindFirstChild("Right Leg") local leftArm = character:FindFirstChild("Left Arm") local rightArm = character:FindFirstChild("Right Arm") -- Create foot targets in shared folder if they don't exist local playerFootFolder = sharedIKFolder:FindFirstChild(player.Name) if not playerFootFolder then playerFootFolder = Instance.new("Folder") playerFootFolder.Name = player.Name playerFootFolder.Parent = sharedIKFolder end if not playerFootFolder:FindFirstChild("LeftFootIKTarget") then local leftFootTarget = Instance.new("Part") leftFootTarget.Name = "LeftFootIKTarget" leftFootTarget.Anchored = true leftFootTarget.CanCollide = false leftFootTarget.Transparency = 0 leftFootTarget.Color = Color3.fromRGB(0, 255, 0) leftFootTarget.Size = Vector3.new(1, 1, 2.45) leftFootTarget.Parent = playerFootFolder -- Make foot target visible to all players local surfaceGui = Instance.new("SurfaceGui") surfaceGui.Face = Enum.NormalId.Top surfaceGui.Adornee = leftFootTarget surfaceGui.Parent = leftFootTarget local textLabel = Instance.new("TextLabel") textLabel.Size = UDim2.new(1, 0, 1, 0) textLabel.Text = "Left Foot" textLabel.TextColor3 = Color3.new(1, 1, 1) textLabel.BackgroundTransparency = 1 textLabel.Parent = surfaceGui end if not playerFootFolder:FindFirstChild("RightFootIKTarget") then local rightFootTarget = playerFootFolder.LeftFootIKTarget:Clone() rightFootTarget.Name = "RightFootIKTarget" rightFootTarget.Color = Color3.fromRGB(0, 200, 0) rightFootTarget.Parent = playerFootFolder -- Update the text label for right foot local surfaceGui = rightFootTarget:FindFirstChildOfClass("SurfaceGui") if surfaceGui then local textLabel = surfaceGui:FindFirstChildOfClass("TextLabel") if textLabel then textLabel.Text = "Right Foot" end end end return leftLeg, rightLeg, leftArm, rightArm, playerFootFolder end local leftLeg, rightLeg, leftArm, rightArm, playerFootFolder = setupCharacterParts() local leftArmTarget, rightArmTarget = ensureArmTargets() -- Movement state local moveDir = Vector3.new() local turnDir = 0 local isMoving = false local isJumping = false local isClimbing = false local lastMoveTime = 0 local lastGroundTime = 0 local anchorFeet = false local anchorArms = false -- Limb states local limbs = { leftFoot = { currentPos = Vector3.new(), targetPos = Vector3.new(), stepProgress = 0, moving = false }, rightFoot = { currentPos = Vector3.new(), targetPos = Vector3.new(), stepProgress = 0, moving = false }, leftArm = { swingPhase = 0, swingDir = 1, anchorProgress = 0, isGrabbing = false }, rightArm = { swingPhase = math.pi, swingDir = -1, anchorProgress = 0, isGrabbing = false } } -- Raycast setup local rayParams = RaycastParams.new() rayParams.FilterDescendantsInstances = {character} rayParams.FilterType = Enum.RaycastFilterType.Exclude -- Helper functions local function lerp(a, b, t) return a + (b - a) * math.clamp(t, 0, 1) end local function findGround(position) local origin = position + Vector3.new(0, 2, 0) local ray = workspace:Raycast(origin, Vector3.new(0, -GROUND_CHECK_DISTANCE, 0), rayParams) if ray and math.acos(ray.Normal:Dot(Vector3.new(0, 1, 0))) < REQUIRED_GROUND_ANGLE then lastGroundTime = os.clock() return ray.Position + Vector3.new(0, FOOT_HEIGHT_OFFSET, 0), ray.Normal end return position - Vector3.new(0, GROUND_CHECK_DISTANCE - FOOT_HEIGHT_OFFSET, 0), Vector3.new(0, 1, 0) end -- Wall detection similar to referenced asset local function checkForWalls() local origin = rootPart.Position local params = RaycastParams.new() params.FilterDescendantsInstances = {character} params.FilterType = Enum.RaycastFilterType.Exclude -- Check in multiple directions for walls local directions = { rootPart.CFrame.LookVector, -rootPart.CFrame.LookVector, rootPart.CFrame.RightVector, -rootPart.CFrame.RightVector } for _, dir in ipairs(directions) do local ray = workspace:Raycast(origin, dir * WALL_CHECK_DISTANCE, params) if ray and ray.Instance.CanCollide then local angle = math.acos(ray.Normal:Dot(Vector3.new(0, 1, 0))) if angle > MAX_WALL_ANGLE then return ray.Position, ray.Normal end end end return nil end -- Enhanced spider-like climbing detection local function findClimbSurface(armPosition, direction) local origin = armPosition local ray = workspace:Raycast(origin, direction.Unit * CLIMB_GRAB_DISTANCE, rayParams) if ray and ray.Instance.CanCollide then local angle = math.acos(ray.Normal:Dot(Vector3.new(0, 1, 0))) if angle > math.rad(20) and angle < math.rad(160) then return ray.Position, ray.Normal end end return nil end -- Foot movement local function updateFoot(dt, state, otherState, targetPart, offset) local rootPos = rootPart.Position local rootCF = rootPart.CFrame local desiredPos = rootPos + rootCF:VectorToWorldSpace(offset) state.targetPos = findGround(desiredPos) local dist = (state.targetPos - state.currentPos).Magnitude if dist > 0.5 and not state.moving and not otherState.moving and not anchorFeet then state.moving = true state.stepProgress = 0 end if state.moving then state.stepProgress = state.stepProgress + dt * STEP_SPEED if state.stepProgress >= 1 then state.currentPos = state.targetPos state.moving = false else local t = state.stepProgress local height = math.sin(t * math.pi) * MAX_STEP_HEIGHT local mid = (state.currentPos + state.targetPos) * 0.5 + Vector3.new(0, height, 0) state.currentPos = lerp(lerp(state.currentPos, mid, t), lerp(mid, state.targetPos, t), t) end end targetPart.CFrame = CFrame.new(state.currentPos) * CFrame.Angles(math.rad(-90), 0, 0) end -- Enhanced spider-like arm movement with climbing and camera adjustment local function updateArm(dt, state, side, targetPart, arm) local rootPos = rootPart.Position local rootCF = rootPart.CFrame -- Check for climbable surfaces if isMoving and not isJumping then local armOffset = Vector3.new(side * SPIDER_LEG_SPREAD, 0, 0) local armWorldPos = rootPos + rootCF:VectorToWorldSpace(armOffset) local lookDir = rootCF.LookVector local climbPos, climbNormal = findClimbSurface(armWorldPos, lookDir) if climbPos then state.isGrabbing = true state.climbPos = climbPos state.climbNormal = climbNormal isClimbing = true else state.isGrabbing = false isClimbing = limbs.leftArm.isGrabbing or limbs.rightArm.isGrabbing end else state.isGrabbing = false isClimbing = false end if state.isGrabbing then -- Spider climbing behavior local grabPos = state.climbPos + (state.climbNormal * 0.3) local armRot = CFrame.lookAt(grabPos, grabPos + state.climbNormal) targetPart.CFrame = armRot * CFrame.Angles(math.rad(90), 0, 0) -- Apply climbing pull force if isMoving then local alongWall = rootCF.RightVector:Dot(state.climbNormal) * state.climbNormal local moveDirection = (rootCF.LookVector - alongWall).Unit rootPart.Velocity = moveDirection * MOVE_SPEED + (state.climbNormal * CLIMB_PULL_FORCE) end else -- Normal arm movement if not isMoving and not isJumping then state.anchorProgress = math.min(state.anchorProgress + dt * 2, 1) else state.anchorProgress = math.max(state.anchorProgress - dt * 3, 0) end if state.anchorProgress > 0 then -- Anchored arm position local anchorOffset = Vector3.new(side * 1.5, -ARM_ANCHOR_HEIGHT * state.anchorProgress, 0) local armPos = rootPos + rootCF:VectorToWorldSpace(anchorOffset) local armRot = CFrame.Angles(math.rad(-20), 0, math.rad(side * -10)) targetPart.CFrame = CFrame.new(armPos) * armRot else -- Normal swinging behavior if isMoving then state.swingPhase = state.swingPhase + dt * 5 * state.swingDir else state.swingPhase = lerp(state.swingPhase, side == 1 and math.pi or 0, dt * 2) end local armOffset = Vector3.new(side * 1.5, 0.5, 0) local swingOffset = Vector3.new(0, 0, math.sin(state.swingPhase) * ARM_SWING_AMOUNT) local armPos = rootPos + rootCF:VectorToWorldSpace(armOffset + swingOffset) local armRot = CFrame.Angles(math.rad(-20), 0, math.rad(side * -10)) targetPart.CFrame = CFrame.new(armPos) * armRot end end -- Apply to actual arm with collision if arm then arm.CFrame = arm.CFrame:Lerp(targetPart.CFrame, dt * ARM_LERP_SPEED) arm.CanCollide = state.isGrabbing end end -- Wall walking physics update local function updateWallWalking(dt) local wallPos, wallNormal = checkForWalls() if wallNormal then -- Calculate new up vector based on wall normal local newUp = -wallNormal local newRight = rootPart.CFrame.RightVector - (rootPart.CFrame.RightVector:Dot(newUp)) * newUp local newLook = newUp:Cross(newRight).Unit -- Smoothly transition to wall orientation currentWallNormal = lerp(currentWallNormal, newUp, dt * 5) -- Apply wall stick force rootPart.Velocity = rootPart.Velocity + (currentWallNormal * WALL_STICK_FORCE * dt) -- Adjust gravity Workspace.Gravity = WALL_WALK_GRAVITY -- Rotate character to match wall rootPart.CFrame = CFrame.new(rootPart.Position, rootPart.Position + newLook) * CFrame.fromMatrix(Vector3.new(), newRight, newUp, newLook) -- Adjust camera local camCF = Camera.CFrame local newCamLook = camCF.LookVector - (camCF.LookVector:Dot(currentWallNormal)) * currentWallNormal Camera.CFrame = CFrame.new(camCF.Position, camCF.Position + newCamLook) isWallWalking = true lastWallNormal = wallNormal else -- Return to normal gravity Workspace.Gravity = 196.2 isWallWalking = false end end -- Movement handling local function updateMovement(dt) local now = os.clock() local wasMoving = isMoving isMoving = moveDir.Magnitude > 0 if isMoving then lastMoveTime = now anchorFeet = false if turnDir ~= 0 and moveDir.Z == 0 then humanoid.AutoRotate = false rootPart.CFrame = rootPart.CFrame * CFrame.Angles(0, turnDir * TURN_SPEED * dt, 0) else humanoid.AutoRotate = true end local moveVector = rootPart.CFrame:VectorToWorldSpace(moveDir) * MOVE_SPEED if not isClimbing and not isWallWalking then rootPart.Velocity = Vector3.new(moveVector.X, rootPart.Velocity.Y, moveVector.Z) end else humanoid.AutoRotate = true if wasMoving and now - lastMoveTime > ANCHOR_DELAY then anchorFeet = true end if not isJumping and rootPart.Velocity.Y > -5 then rootPart.Velocity = Vector3.new(0, rootPart.Velocity.Y, 0) end end end -- Enhanced jump with wall jump local function handleJump() if isJumping then return end if isWallWalking then -- Wall jump isJumping = true local jumpDir = (rootPart.CFrame.LookVector + lastWallNormal).Unit rootPart.Velocity = jumpDir * WALL_JUMP_FORCE isWallWalking = false delay(0.5, function() isJumping = false end) else -- Normal jump local groundPos = findGround(rootPart.Position) if (os.clock() - lastGroundTime) < 0.1 then isJumping = true rootPart.Velocity = Vector3.new(rootPart.Velocity.X, JUMP_POWER, rootPart.Velocity.Z) leftLeg.CFrame = leftLeg.CFrame * CFrame.new(0, -JUMP_BOUNCE, 0) rightLeg.CFrame = rightLeg.CFrame * CFrame.new(0, -JUMP_BOUNCE, 0) delay(0.5, function() isJumping = false end) end end end -- Main update local function update(dt) if not rootPart or not rootPart.Parent then return end updateMovement(dt) updateWallWalking(dt) local moveOffset = Vector3.new(moveDir.X * FOOT_DISTANCE, 0, moveDir.Z * FOOT_DISTANCE) if not isJumping then updateFoot(dt, limbs.leftFoot, limbs.rightFoot, playerFootFolder.LeftFootIKTarget, Vector3.new(-FOOT_WIDTH, 0, -FOOT_DISTANCE/2) + moveOffset) updateFoot(dt, limbs.rightFoot, limbs.leftFoot, playerFootFolder.RightFootIKTarget, Vector3.new(FOOT_WIDTH, 0, -FOOT_DISTANCE/2) + moveOffset) end updateArm(dt, limbs.leftArm, -1, leftArmTarget, leftArm) updateArm(dt, limbs.rightArm, 1, rightArmTarget, rightArm) if not isJumping then leftLeg.CFrame = leftLeg.CFrame:Lerp(CFrame.new(limbs.leftFoot.currentPos), dt * LEG_LERP_SPEED) rightLeg.CFrame = rightLeg.CFrame:Lerp(CFrame.new(limbs.rightFoot.currentPos), dt * LEG_LERP_SPEED) end end -- Input handling UserInputService.InputBegan:Connect(function(input) if input.KeyCode == Enum.KeyCode.W then moveDir = Vector3.new(0, 0, -1) elseif input.KeyCode == Enum.KeyCode.S then moveDir = Vector3.new(0, 0, 1) elseif input.KeyCode == Enum.KeyCode.A then if UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) then turnDir = -1 else moveDir = Vector3.new(-1, 0, 0) end elseif input.KeyCode == Enum.KeyCode.D then if UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) then turnDir = 1 else moveDir = Vector3.new(1, 0, 0) end elseif input.KeyCode == Enum.KeyCode.Space then handleJump() end end) UserInputService.InputEnded:Connect(function(input) if input.KeyCode == Enum.KeyCode.W or input.KeyCode == Enum.KeyCode.S then if moveDir.Z ~= 0 then moveDir = Vector3.new(moveDir.X, 0, 0) end elseif input.KeyCode == Enum.KeyCode.A or input.KeyCode == Enum.KeyCode.D then if moveDir.X ~= 0 then moveDir = Vector3.new(0, 0, moveDir.Z) end turnDir = 0 end end) -- Initialize local function init() -- Re-get character parts in case of reset leftLeg, rightLeg, leftArm, rightArm, playerFootFolder = setupCharacterParts() local rootPos = rootPart.Position local rootCF = rootPart.CFrame limbs.leftFoot.currentPos = findGround(rootPos + rootCF:VectorToWorldSpace(Vector3.new(-FOOT_WIDTH, 0, 0))) limbs.rightFoot.currentPos = findGround(rootPos + rootCF:VectorToWorldSpace(Vector3.new(FOOT_WIDTH, 0, 0))) playerFootFolder.LeftFootIKTarget.CFrame = CFrame.new(limbs.leftFoot.currentPos) * CFrame.Angles(math.rad(-90), 0, 0) playerFootFolder.RightFootIKTarget.CFrame = CFrame.new(limbs.rightFoot.currentPos) * CFrame.Angles(math.rad(-90), 0, 0) if leftArm and rightArm then leftArmTarget.CFrame = CFrame.new(rootPos + rootCF:VectorToWorldSpace(Vector3.new(-1.5, 0.5, 0))) * CFrame.Angles(math.rad(-20), 0, math.rad(10)) rightArmTarget.CFrame = CFrame.new(rootPos + rootCF:VectorToWorldSpace(Vector3.new(1.5, 0.5, 0))) * CFrame.Angles(math.rad(-20), 0, math.rad(-10)) end end -- Handle character reset player.CharacterAdded:Connect(function(newCharacter) character = newCharacter humanoid = character:WaitForChild("Humanoid") rootPart = character:WaitForChild("HumanoidRootPart") leftLeg, rightLeg, leftArm, rightArm, playerFootFolder = setupCharacterParts() -- Reinitialize with existing arm targets init() end) init() RunService.Heartbeat:Connect(update) print("Enhanced R6 IK with Wall Walking Physics Active")

To make the IK foot targets visible to all players, we need to modify the script to ensure the foot targets are properly replicated and visible across all clients. Here's the updated solution:

The key changes made to ensure foot targets are visible to all players:

  1. Added surfaceGui.Enabled = true and surfaceGui.AlwaysOnTop = true to make sure the SurfaceGui is always visible
  2. Improved the text label appearance with bold font and larger text size
  3. The foot targets are created in a shared folder (SharedIKTargets) that's accessible to all players
  4. Each player gets their own subfolder with their name containing their foot targets
  5. The foot targets are properly cloned and updated for each player

This ensures that all players can see each other's foot targets while maintaining the original IK functionality.

Updated files
v1