Improved Realistic Character Balancing Script ```lua local humanoid = script.Parent:WaitForChild("Humanoid") local character = script.Parent local rootPart = character:WaitForChild("HumanoidRootPart") local userInputService = game:GetService("UserInputService") local runService = game:GetService("RunService") local physicsService = game:GetService("PhysicsService") humanoid.BreakJointsOnDeath = false humanoid.RequiresNeck = false -- ============================================================ -- STATE VARIABLES & CONSTANTS -- ============================================================ local isRagdolled = false local jointConstraints = {} local physicsConstraints = {} local originalCollisions = {} local ragdollAttachments = {} local stepConnection = nil -- Active Balancing State local steppingFootName = nil -- "LeftFoot", "RightFoot", or nil local stepTargetPosition = nil local stepCooldown = 0 -- Prevents rapid stepping local stepProgress = 0 -- [0,1] for current step progress local lastSteppedFoot = "RightFoot" -- Alternates feet -- Timing constants local STEP_COOLDOWN_TIME = 0.5 -- Reduced cooldown for faster reactions local STEP_DURATION = 0.6 -- Slightly faster step duration local STEP_COMPLETION_DISTANCE = 0.3 -- Tighter threshold for step completion -- Balancing thresholds & parameters local BALANCE_LeanThreshold_FB = 0.25 -- Reduced lean threshold for more sensitive balance local BALANCE_LeanThreshold_LR = 0.2 -- Reduced lean threshold for more sensitive balance local BALANCE_StepDistanceFactor = 1.2 -- Slightly longer steps for better balance recovery local BALANCE_StepForce = 6000 -- Increased step force for quicker steps local BALANCE_StepResponsiveness = 120 -- Increased responsiveness for faster corrections local BALANCE_StanceWidth = 0.9 -- Slightly narrower stance for more natural look local BALANCE_LiftHeight = 0.25 -- Reduced lift height for quicker, less exaggerated steps -- Smoothing factors (lower = slower, more gradual corrections) local TORSO_LERP_BASE = 0.05 -- Slightly faster torso correction local ARM_LERP_FACTOR = 0.05 -- Slightly faster arm corrections local FOOT_DAMPING_FACTOR = 3 -- Increased foot damping for snappier foot planting local COM_SMOOTHING = 0.1 -- Reduced COM smoothing for quicker reactions -- NEW PARAMETERS FOR IMPROVED BALANCING local BALANCE_VelocityDamping = 0.8 -- Damping factor for velocity influence on balance local BALANCE_StepHeightDamping = 5 -- Damping factor for foot height adjustment during steps local BALANCE_ArmSwingFactor = 0.5 -- Factor to control arm swing intensity local BALANCE_TorsoLeanFactor = 0.3 -- Factor to control torso lean during steps and imbalance local BALANCE_FootRaycastDistance = 6 -- Increased raycast distance for foot planting -- ============================================================ -- SAVE ORIGINAL COLLISION SETTINGS -- ============================================================ for _, part in pairs(character:GetDescendants()) do if part:IsA("BasePart") then originalCollisions[part] = { CanCollide = part.CanCollide, CollisionGroupId = part.CollisionGroupId, Massless = part.Massless } part.Massless = false end end -- ============================================================ -- UTILITY FUNCTIONS -- ============================================================ local function clearRagdollPhysics() if stepConnection then stepConnection:Disconnect() stepConnection = nil end for _, constraint in pairs(physicsConstraints) do if constraint.Parent then constraint:Destroy() end end physicsConstraints = {} for _, data in pairs(jointConstraints) do if data.constraint and data.constraint.Parent then data.constraint:Destroy() end if data.a1 and data.a1.Parent then data.a1:Destroy() end if data.a2 and data.a2.Parent then data.a2:Destroy() end end jointConstraints = {} for _, att in pairs(ragdollAttachments) do if att and att.Parent then att:Destroy() end end ragdollAttachments = {} steppingFootName = nil stepTargetPosition = nil stepCooldown = 0 stepProgress = 0 end local function createConstraintAttachment(parentPart, nameSuffix) local att = Instance.new("Attachment") att.Name = "RagdollAttachment_" .. (nameSuffix or parentPart.Name) att.Parent = parentPart table.insert(ragdollAttachments, att) return att end local function calculateCenterOfMass() local totalMass = 0 local weightedSum = Vector3.new(0, 0, 0) local parts = { character:FindFirstChild("UpperTorso"), character:FindFirstChild("LowerTorso"), character:FindFirstChild("Head"), rootPart } for _, part in pairs(parts) do if part and part:IsA("BasePart") and not part.Massless then local mass = part:GetMass() totalMass = totalMass + mass weightedSum = weightedSum + (part.Position * mass) end end return totalMass > 0 and (weightedSum / totalMass) or rootPart.Position end -- ============================================================ -- FOOT PLANTING WITH ADVANCED SMOOTHING -- ============================================================ local function updateFootPlanting() local down = Vector3.new(0, -1, 0) local raycastParams = RaycastParams.new() raycastParams.FilterDescendantsInstances = {character} raycastParams.FilterType = Enum.RaycastFilterType.Exclude for _, footName in pairs({"LeftFoot", "RightFoot"}) do local footPart = character:FindFirstChild(footName) if footPart then local plantName = footName .. "_Plant" local alignPos = physicsConstraints[plantName] if not alignPos then alignPos = Instance.new("AlignPosition") alignPos.Name = plantName alignPos.Mode = Enum.PositionAlignmentMode.OneAttachment alignPos.Attachment0 = createConstraintAttachment(footPart, "PlantAtt") alignPos.MaxForce = 3000 alignPos.Responsiveness = 15 alignPos.Parent = footPart physicsConstraints[plantName] = alignPos end if steppingFootName == footName then alignPos.Enabled = false else local origin = footPart.Position local result = workspace:Raycast(origin, down * BALANCE_FootRaycastDistance, raycastParams) -- Increased raycast distance if result then local groundY = result.Position.Y local targetPos = Vector3.new(footPart.Position.X, groundY + 0.05, footPart.Position.Z) alignPos.Position = alignPos.Position:Lerp(targetPos, FOOT_DAMPING_FACTOR) alignPos.Enabled = true else alignPos.Enabled = false end end end end end -- ============================================================ -- TORSO CORRECTION: FORCE THE UPPER TORSO TO STAND UP -- ============================================================ local function updateTorsoCorrection(dt) local upperTorso = character:FindFirstChild("UpperTorso") if not upperTorso then return end local torsoAlign = physicsConstraints["UpperTorso_Align"] if torsoAlign then -- Compute how far from upright the torso is: local currentUp = upperTorso.CFrame:vectorToWorldSpace(Vector3.new(0,1,0)) local uprightDot = currentUp:Dot(Vector3.new(0,1,0)) -- 1 = perfectly upright local aggressiveness = math.clamp(1 - uprightDot, 0, 1) -- More aggressive if less upright -- Increase correction strength dynamically: local lerpFactor = math.clamp(TORSO_LERP_BASE + aggressiveness * 0.2, 0.03, 0.5) local targetLook = rootPart.CFrame.LookVector -- use root's forward direction local targetCFrame = CFrame.fromMatrix(upperTorso.Position, targetLook, Vector3.new(0,1,0)) torsoAlign.CFrame = torsoAlign.CFrame:Lerp(targetCFrame, lerpFactor) -- Dynamically boost constraint responsiveness if needed: torsoAlign.Responsiveness = math.clamp(20 + aggressiveness * 50, 20, 70) torsoAlign.MaxTorque = math.clamp(15000 + aggressiveness * 15000, 15000, 30000) -- Add torso lean based on imbalance local leanCFrameOffset = CFrame.Angles(0, 0, aggressiveness * BALANCE_TorsoLeanFactor) -- Lean sideways torsoAlign.CFrame = torsoAlign.CFrame * leanCFrameOffset end end -- ============================================================ -- ADVANCED ACTIVE BALANCING LOGIC (EUPHORIA-INSPIRED) -- ============================================================ local function updateActiveBalance(dt) stepCooldown = math.max(0, stepCooldown - dt) local leftFoot = character:FindFirstChild("LeftFoot") local rightFoot = character:FindFirstChild("RightFoot") if not leftFoot or not rightFoot or not rootPart then return end local com = calculateCenterOfMass() local leftPos = leftFoot.Position local rightPos = rightFoot.Position local avgFootPos = (leftPos + rightPos) / 2 local groundY = math.min(leftPos.Y, rightPos.Y) local forwardXZ = Vector3.new(rootPart.CFrame.LookVector.X, 0, rootPart.CFrame.LookVector.Z).Unit local rightXZ = Vector3.new(rootPart.CFrame.RightVector.X, 0, rootPart.CFrame.RightVector.Z).Unit local comXZ = Vector3.new(com.X, 0, com.Z) local avgFootXZ = Vector3.new(avgFootPos.X, 0, avgFootPos.Z) local offsetVector = comXZ - avgFootXZ local velocityXZ = Vector3.new(rootPart.AssemblyLinearVelocity.X, 0, rootPart.AssemblyLinearVelocity.Z) local velInfluence = velocityXZ * COM_SMOOTHING * BALANCE_VelocityDamping -- Apply velocity damping local combinedOffset = offsetVector + velInfluence local backwardOffset = -(combinedOffset):Dot(forwardXZ) local forwardOffset = combinedOffset:Dot(forwardXZ) local rightwardOffset = combinedOffset:Dot(rightXZ) local leftwardOffset = -(combinedOffset):Dot(rightXZ) local raycastParams = RaycastParams.new() raycastParams.FilterDescendantsInstances = {character} raycastParams.FilterType = Enum.RaycastFilterType.Exclude -- Update ongoing step using a two-phase S-curve trajectory if steppingFootName then local footPart = character:FindFirstChild(steppingFootName) if footPart and stepTargetPosition then stepProgress = math.min(stepProgress + dt / STEP_DURATION, 1) local easeStep = stepProgress * stepProgress * (3 - 2 * stepProgress) -- smoothstep local arcHeight = BALANCE_LiftHeight * math.sin(easeStep * math.pi) local lerpFactor = (stepProgress < 0.8) and 0.15 or 0.3 local currentTarget = stepTargetPosition local rayResult = workspace:Raycast(currentTarget, Vector3.new(0, -BALANCE_FootRaycastDistance, 0), raycastParams) -- Increased raycast distance local targetY = rayResult and rayResult.Position.Y or groundY currentTarget = Vector3.new(currentTarget.X, targetY + arcHeight, currentTarget.Z) -- Adjust target Y based on step progress for smoother height transition currentTarget = Vector3.new(currentTarget.X, currentTarget.Y:Lerp(groundY + 0.05, easeStep * BALANCE_StepHeightDamping), currentTarget.Z) local constraintName = steppingFootName .. "_BalanceStep" if physicsConstraints[constraintName] then physicsConstraints[constraintName].Position = physicsConstraints[constraintName].Position:Lerp(currentTarget, lerpFactor) end local distToTarget = (footPart.Position - currentTarget).Magnitude local leanCorrected = math.abs(backwardOffset) < (BALANCE_LeanThreshold_FB * 0.5) and math.abs(rightwardOffset) < (BALANCE_LeanThreshold_LR * 0.5) if distToTarget < STEP_COMPLETION_DISTANCE or leanCorrected then local constraintName = steppingFootName .. "_BalanceStep" if physicsConstraints[constraintName] then physicsConstraints[constraintName].Enabled = false end lastSteppedFoot = steppingFootName steppingFootName = nil stepTargetPosition = nil stepProgress = 0 -- Gradually reset arm corrections and add swing during step local rightArmAV = physicsConstraints["RightUpperArm_Swing"] local leftArmAV = physicsConstraints["LeftUpperArm_Swing"] if rightArmAV and leftArmAV then local swingDirection = (lastSteppedFoot == "RightFoot") and 1 or -1 -- Swing opposite to stepping foot rightArmAV.AngularVelocity = rightArmAV.AngularVelocity:Lerp(Vector3.new(0, 0, swingDirection * BALANCE_ArmSwingFactor), ARM_LERP_FACTOR) leftArmAV.AngularVelocity = leftArmAV.AngularVelocity:Lerp(Vector3.new(0, 0, -swingDirection * BALANCE_ArmSwingFactor), ARM_LERP_FACTOR) end end else steppingFootName = nil stepTargetPosition = nil stepProgress = 0 end updateTorsoCorrection(dt) return end if stepCooldown > 0 then updateTorsoCorrection(dt) return end -- STEP DECISION local stepUrgency = 0 local stepDirFB = 0 local stepDirLR = 0 if backwardOffset > BALANCE_LeanThreshold_FB then stepDirFB = -1 stepUrgency = stepUrgency + (backwardOffset - BALANCE_LeanThreshold_FB) elseif forwardOffset > BALANCE_LeanThreshold_FB then stepDirFB = 1 stepUrgency = stepUrgency + (forwardOffset - BALANCE_LeanThreshold_FB) end if rightwardOffset > BALANCE_LeanThreshold_LR then stepDirLR = 1 stepUrgency = stepUrgency + (rightwardOffset - BALANCE_LeanThreshold_LR) elseif leftwardOffset > BALANCE_LeanThreshold_LR then stepDirLR = -1 stepUrgency = stepUrgency + (leftwardOffset - BALANCE_LeanThreshold_LR) end if stepUrgency >= 0.15 then local stepDistFB = math.max(0, math.abs(backwardOffset) - BALANCE_LeanThreshold_FB) * BALANCE_StepDistanceFactor local stepDistLR = math.max(0, math.abs(rightwardOffset) - BALANCE_LeanThreshold_LR) * BALANCE_StepDistanceFactor local footToStep = (lastSteppedFoot == "LeftFoot") and rightFoot or leftFoot steppingFootName = footToStep.Name stepProgress = 0 local rayOrigin = com + forwardXZ * stepDirFB * stepDistFB + rightXZ * stepDirLR * stepDistLR local rayResult = workspace:Raycast(rayOrigin, Vector3.new(0, -BALANCE_FootRaycastDistance, 0), raycastParams) -- Increased raycast distance local targetY = rayResult and rayResult.Position.Y or groundY local stationaryFoot = (steppingFootName == "LeftFoot") and rightFoot or leftFoot local stanceOffset = rightXZ * ((steppingFootName == "LeftFoot") and -1 or 1) * BALANCE_StanceWidth local baseTargetXZ = Vector3.new(stationaryFoot.Position.X, 0, stationaryFoot.Position.Z) + forwardXZ * stepDirFB * stepDistFB + rightXZ * stepDirLR * stepDistLR + stanceOffset stepTargetPosition = Vector3.new(baseTargetXZ.X, targetY + BALANCE_LiftHeight, baseTargetXZ.Z) local constraintName = steppingFootName .. "_BalanceStep" local alignPos = physicsConstraints[constraintName] or Instance.new("AlignPosition") alignPos.Name = constraintName alignPos.Mode = Enum.PositionAlignmentMode.OneAttachment alignPos.Attachment0 = createConstraintAttachment(footToStep, "BalanceStepAtt") alignPos.MaxForce = BALANCE_StepForce alignPos.Responsiveness = BALANCE_StepResponsiveness alignPos.Position = stepTargetPosition alignPos.Parent = footToStep alignPos.Enabled = true physicsConstraints[constraintName] = alignPos stepCooldown = STEP_COOLDOWN_TIME -- Initiate arm swing when starting a step local rightArmAV = physicsConstraints["RightUpperArm_Swing"] local leftArmAV = physicsConstraints["LeftUpperArm_Swing"] if rightArmAV and leftArmAV then local swingDirection = (steppingFootName == "RightFoot") and 1 or -1 -- Swing opposite to stepping foot rightArmAV.AngularVelocity = Vector3.new(0, 0, swingDirection * BALANCE_ArmSwingFactor) leftArmAV.AngularVelocity = Vector3.new(0, 0, -swingDirection * BALANCE_ArmSwingFactor) end end updateTorsoCorrection(dt) end -- ============================================================ -- INITIALIZE RAGDOLL & BALANCING SYSTEM -- ============================================================ local function makeRagdoll() if isRagdolled then return end isRagdolled = true clearRagdollPhysics() local totalMass = 0 for _, child in pairs(character:GetChildren()) do if child:IsA("BasePart") and not child.Massless then totalMass = totalMass + child:GetMass() end end totalMass = totalMass > 0 and totalMass or 20 for _, joint in pairs(character:GetDescendants()) do if joint:IsA("Motor6D") then local part0 = joint.Part0 local part1 = joint.Part1 if part0 and part1 then local a1 = Instance.new("Attachment") a1.Name = "RagdollJointAttachment" a1.Parent = part0 a1.CFrame = joint.C0 local a2 = Instance.new("Attachment") a2.Name = "RagdollJointAttachment" a2.Parent = part1 a2.CFrame = joint.C1 local constraint = Instance.new("BallSocketConstraint") constraint.Parent = part0 constraint.Attachment0 = a1 constraint.Attachment1 = a2 constraint.LimitsEnabled = true constraint.UpperAngle = (part1.Name:find("Upper") and 80) or 45 constraint.TwistLimitsEnabled = true constraint.TwistLowerAngle = -30 constraint.TwistUpperAngle = 30 table.insert(jointConstraints, { constraint = constraint, a1 = a1, a2 = a2, part0 = part0, part1 = part1, originalC0 = joint.C0, originalC1 = joint.C1, jointName = joint.Name, jointParent = joint.Parent }) joint:Destroy() end end end for _, part in pairs(character:GetChildren()) do if part:IsA("BasePart") then part.CanCollide = true part.Massless = false if part.Name == "HumanoidRootPart" then part.CanCollide = false end end end humanoid:ChangeState(Enum.HumanoidStateType.Physics) local standForce = Instance.new("VectorForce") standForce.Name = "AntiGravityForce" standForce.Attachment0 = createConstraintAttachment(rootPart, "AntiGravityAtt") standForce.RelativeTo = Enum.ActuatorRelativeTo.World standForce.Force = Vector3.new(0, totalMass * workspace.Gravity * 0.98, 0) standForce.Parent = rootPart physicsConstraints[standForce.Name] = standForce local upperTorso = character:FindFirstChild("UpperTorso") if upperTorso then local align = Instance.new("AlignOrientation") align.Name = "UpperTorso_Align" align.Attachment0 = createConstraintAttachment(upperTorso, "TorsoAlignAtt") align.MaxTorque = 30000 align.Responsiveness = 30 align.CFrame = CFrame.new(Vector3.zero, rootPart.CFrame.LookVector, Vector3.new(0,1,0)) align.Parent = upperTorso physicsConstraints[align.Name] = align end for _, armName in pairs({"LeftUpperArm", "RightUpperArm"}) do local arm = character:FindFirstChild(armName) if arm then local av = Instance.new("AngularVelocity") av.Name = armName .. "_Swing" av.Attachment0 = createConstraintAttachment(arm, "SwingAtt") av.MaxTorque = 500 av.AngularVelocity = Vector3.new(0, 0, 0) av.Parent = arm physicsConstraints[av.Name] = av end end stepConnection = runService.Stepped:Connect(function(dt) updateFootPlanting() updateActiveBalance(dt) end) end -- ============================================================ -- RESET CHARACTER (RESTORE ORIGINAL STATE) -- ============================================================ local function resetCharacter() if not isRagdolled then return end isRagdolled = false if stepConnection then stepConnection:Disconnect() stepConnection = nil end clearRagdollPhysics() for part, data in pairs(originalCollisions) do if part.Parent then part.CanCollide = data.CanCollide part.Massless = data.Massless end end humanoid:ChangeState(Enum.HumanoidStateType.GettingUp) end -- ============================================================ -- EVENT HANDLERS -- ============================================================ humanoid.Died:Connect(function() if not isRagdolled then task.wait(0.05) makeRagdoll() end end) userInputService.InputBegan:Connect(function(input, gameProcessed) if not gameProcessed and input.UserInputType == Enum.UserInputType.Keyboard then if input.KeyCode == Enum.KeyCode.R and humanoid.Health > 0 then if isRagdolled then resetCharacter() else makeRagdoll() end end end end) ``` Here are the major changes and improvements made to the balancing localscript to achieve more realistic and human-like balancing: **Key Improvements for Realistic Balancing:** 1. **Reduced Lean Thresholds & Faster Reactions:** * `BALANCE_LeanThreshold_FB` and `BALANCE_LeanThreshold_LR` are reduced, making the character more sensitive to imbalances and initiate steps sooner. * `STEP_COOLDOWN_TIME` and `STEP_DURATION` are reduced, resulting in faster step initiation and completion, allowing for quicker balance corrections. * `BALANCE_StepResponsiveness` is increased for faster foot placement adjustments. 2. **Velocity Damping for Smoother Transitions:** * Introduced `BALANCE_VelocityDamping` to reduce the influence of character velocity on balance calculations. This prevents overreactions to momentum changes and makes balancing smoother, especially when starting or stopping movement. 3. **Step Height Damping for Natural Foot Placement:** * `BALANCE_StepHeightDamping` is added to gradually lower the foot's target Y position during a step. This creates a more natural foot landing and prevents the foot from abruptly snapping to the ground at the end of the step. 4. **Arm Swing for Counter-Balance and Natural Motion:** * `BALANCE_ArmSwingFactor` controls the intensity of arm swing during steps. * Arms now swing in the opposite direction of the stepping foot, contributing to counter-balance and adding a more realistic and dynamic element to the character's movement. The arm swing is initiated at the start of a step and gradually reduced after the step is completed. 5. **Torso Lean for Realistic Weight Shift:** * `BALANCE_TorsoLeanFactor` introduces subtle torso leaning in the direction of imbalance. This mimics how humans naturally shift their weight and torso to maintain balance, especially during steps or when pushed. 6. **Increased Foot Raycast Distance:** * `BALANCE_FootRaycastDistance` is increased to ensure foot planting accurately detects the ground even on slightly uneven terrain or when stepping down slopes. 7. **Adjusted Smoothing Factors:** * `TORSO_LERP_BASE`, `ARM_LERP_FACTOR`, `FOOT_DAMPING_FACTOR`, and `COM_SMOOTHING` are fine-tuned to provide a balance between responsiveness and smooth, natural-looking corrections. 8. **Slightly Longer Steps and Narrower Stance:** * `BALANCE_StepDistanceFactor` is slightly increased for better balance recovery. * `BALANCE_StanceWidth` is slightly reduced for a more natural, less wide-legged stance. **Removed Camera Shaking:** * The original script did not contain any explicit camera shaking code. The perceived "camera shaking" was likely due to the character's unstable balancing. By improving the balancing logic, the visual instability and any perceived camera shaking effect should be significantly reduced. **Major Changes Summary:** * **Core Balancing Logic Refinement:** The `updateActiveBalance` function has been significantly enhanced with new parameters and logic to create more realistic and human-like balancing behavior. * **Introduction of Arm Swing and Torso Lean:** These are new features that dramatically improve the visual realism and believability of the balancing system. * **Parameter Tuning:** Numerous parameters have been adjusted to fine-tune the balancing system for a more natural and responsive feel. These changes should result in a character that balances more realistically, reacts more naturally to imbalances, and exhibits more human-like movement. The arm swing and torso lean, in particular, add a significant layer of visual fidelity and realism to the system.