Dodge script
Key RequiredUniversal

Dodge script

Universal ScriptEducationalistEducationalist 2.9K views 528 executesUpdated Jan 31, 2026
Unrated
00
Lua Script•260 lines (8628 chars)
-- Name: UltraInstinct_Dodge_AI_V3
-- Parent: StarterPlayer -> StarterCharacterScripts

local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")
local Debris = game:GetService("Debris")
local TweenService = game:GetService("TweenService")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local rootPart = character:WaitForChild("HumanoidRootPart")
local humanoid = character:WaitForChild("Humanoid")

-- // CONFIGURATION //
local CONFIG = {
	-- Detection
	ScanRadius = 18,           -- Area to check for threats
	ProjectileSpeedMin = 25,   -- Minimum speed to consider a part a "projectile"
	
	-- Movement
	DodgeDist = 14,            -- How far to teleport
	WallBuffer = 2.5,          -- Distance to keep from walls
	
	-- Cooldowns & Stress
	BaseCooldown = 1.3,
	OverdriveCooldown = 0.2,   -- Spam dodge speed
	StressThreshold = 3,       
	StressDecay = 0.6,
}

-- // STATE VARIABLES //
local stressLevel = 0
local lastDodgeTime = 0
local isDodging = false

-- Raycast params for environment (Walls/Floors)
local envParams = RaycastParams.new()
envParams.FilterType = Enum.RaycastFilterType.Exclude

-- Raycast params for incoming threats (Projectiles)
local threatParams = RaycastParams.new()
threatParams.FilterType = Enum.RaycastFilterType.Exclude

-- // INITIALIZATION //
local function updateFilters()
	local ignoreList = {character, Workspace.CurrentCamera}
	envParams.FilterDescendantsInstances = ignoreList
	
	-- For projectile prediction, we want to see if it hits US
	threatParams.FilterDescendantsInstances = {Workspace.CurrentCamera} -- Don't ignore character, we need to know if we get hit
end

character.DescendantAdded:Connect(updateFilters)
updateFilters()

-- // VISUAL FX //
local function playEffects(mode, pos)
	local isPanic = mode == "Panic"
	local color = isPanic and Color3.fromRGB(255, 40, 40) or Color3.fromRGB(80, 255, 200) -- Red vs Cyan
	
	-- 1. Sound
	local sound = Instance.new("Sound", rootPart)
	sound.SoundId = "rbxassetid://130768133" 
	sound.PlaybackSpeed = isPanic and 1.4 or 1.0
	sound.Volume = 0.6
	sound:Play()
	Debris:AddItem(sound, 1)

	-- 2. Afterimage (Ghost)
	coroutine.wrap(function()
		for _, v in pairs(character:GetChildren()) do
			if v:IsA("BasePart") and v.Transparency < 1 then
				local g = v:Clone()
				g.Parent = Workspace
				g.Anchored = true
				g.CanCollide = false
				g.CFrame = v.CFrame
				g.Material = Enum.Material.ForceField
				g.Color = color
				g.Transparency = 0.2
				
				-- Remove scripts/joints
				for _, c in pairs(g:GetChildren()) do c:Destroy() end
				
				Debris:AddItem(g, 0.4)
				
				-- Quick fade
				local tween = TweenService:Create(g, TweenInfo.new(0.4), {Transparency = 1})
				tween:Play()
			end
		end
	end)()
end

-- // PHYSICS CALCULATIONS //

-- Checks if a position is valid (Not inside a wall, not over a void)
local function getSafePosition(origin, direction, distance)
	-- 1. Wall Check
	local ray = Workspace:Raycast(origin, direction * distance, envParams)
	local targetPos
	
	if ray then
		-- Wall detected: Slide logic
		local hitNormal = ray.Normal
		-- Calculate sliding vector: remove the component of movement going INTO the wall
		local slideDir = direction - (direction:Dot(hitNormal) * hitNormal)
		
		-- If slide vector is too small (cornered), just stop before wall
		if slideDir.Magnitude < 0.1 then
			targetPos = origin + (direction * (ray.Distance - CONFIG.WallBuffer))
		else
			-- Slide along the wall
			targetPos = origin + (slideDir.Unit * (distance * 0.8))
		end
	else
		targetPos = origin + (direction * distance)
	end
	
	-- 2. Void Check (Floor Check)
	-- Raycast down from the proposed target position
	local floorRay = Workspace:Raycast(targetPos + Vector3.new(0, 4, 0), Vector3.new(0, -20, 0), envParams)
	
	if not floorRay then
		-- If dodging leads to death (void), cancel movement or reduce distance drastically
		return origin -- Stay put if the alternative is falling
	end

	return targetPos
end

-- // SCANNER SYSTEM //
local function scanForThreats()
	local scanParams = OverlapParams.new()
	scanParams.FilterDescendantsInstances = {character}
	scanParams.FilterType = Enum.RaycastFilterType.Exclude

	-- Get everything nearby
	local parts = Workspace:GetPartBoundsInRadius(rootPart.Position, CONFIG.ScanRadius, scanParams)
	
	local chosenThreat = nil
	local threatType = "None" -- "Melee" or "Projectile"
	local threatVector = Vector3.new(0,0,0) -- Direction available to dodge away from

	for _, part in pairs(parts) do
		-- >> CHECK 1: FAST MOVING PARTS (Projectiles/Flying Objects) <<
		if not part.Anchored and part.AssemblyLinearVelocity.Magnitude > CONFIG.ProjectileSpeedMin then
			local vel = part.AssemblyLinearVelocity
			local toMe = (rootPart.Position - part.Position)
			
			-- Is it moving towards me?
			if vel.Unit:Dot(toMe.Unit) > 0.5 then
				-- PREDICTION: Raycast forward from the part to see if it will actually hit us within 0.2s
				local predictRay = Workspace:Raycast(part.Position, vel * 0.2, threatParams)
				
				if predictRay and predictRay.Instance:IsDescendantOf(character) then
					chosenThreat = part
					threatType = "Projectile"
					threatVector = vel.Unit -- Movement direction of projectile
					break -- Priority: Dodge bullet immediately
				end
			end
		end

		-- >> CHECK 2: HUMANOIDS (Melee/Players) <<
		-- Works on invisible players because we check HumanoidRootPart existence, not transparency
		local model = part.Parent
		if model and model:FindFirstChild("Humanoid") and model ~= character then
			local enemyRoot = model:FindFirstChild("HumanoidRootPart")
			if enemyRoot then
				local eHum = model.Humanoid
				if eHum.Health > 0 then
					local toPlayer = (rootPart.Position - enemyRoot.Position)
					local dist = toPlayer.Magnitude
					
					-- Are they looking at me?
					local facing = enemyRoot.CFrame.LookVector:Dot(-toPlayer.Unit) -- -1 to 1
					local speed = enemyRoot.AssemblyLinearVelocity.Magnitude
					
					-- Logic: Close & Facing me OR Close & Moving Fast
					if dist < 10 and (facing > 0.6 or speed > 10) then
						chosenThreat = enemyRoot
						threatType = "Melee"
						threatVector = (rootPart.Position - enemyRoot.Position).Unit -- Direction away from enemy
					end
				end
			end
		end
	end
	
	return chosenThreat, threatType, threatVector
end

-- // MAIN BRAIN //
RunService.Heartbeat:Connect(function(dt)
	local now = tick()
	
	-- Stress Decay
	if stressLevel > 0 then stressLevel = math.max(0, stressLevel - (CONFIG.StressDecay * dt)) end

	-- Determine Cooldown based on Stress
	local currentCooldown = (stressLevel > CONFIG.StressThreshold) and CONFIG.OverdriveCooldown or CONFIG.BaseCooldown
	
	if isDodging or (now - lastDodgeTime < currentCooldown) then return end
	
	-- -> RUN SCAN
	local threat, type, dirVec = scanForThreats()
	
	if threat then
		isDodging = true
		local mode = (stressLevel > CONFIG.StressThreshold) and "Panic" or "Normal"
		
		-- // DODGE IRECTION LOGIC //
		local dodgeDir = Vector3.new(0,0,0)
		
		if type == "Projectile" then
			-- If bullet coming, dodge PERPENDICULAR (Sideways usually)
			local left = dirVec:Cross(Vector3.new(0, 1, 0))
			dodgeDir = (math.random() > 0.5) and left or -left
			stressLevel = stressLevel + 2 -- Projectiles are scary, high stress gain
			
		elseif type == "Melee" then
			-- If Melee, calculate strategy
			if mode == "Panic" then
				-- Panic behavior: Teleport BEHIND enemy (dirVec is currently Away, so reverse it)
				dodgeDir = -dirVec + (Vector3.new(math.random()-0.5, 0, math.random()-0.5)) -- Behind + Jitter
			else
				-- Normal behavior: Back up or Circle
				local left = dirVec:Cross(Vector3.new(0, 1, 0))
				dodgeDir = dirVec + (left * 0.5) -- Angle backwards
			end
			stressLevel = stressLevel + 1
		end
		
		-- Normalize
		dodgeDir = Vector3.new(dodgeDir.X, 0, dodgeDir.Z).Unit
		
		-- // EXECUTE MOVEMENT //
		local finalPos = getSafePosition(rootPart.Position, dodgeDir, CONFIG.DodgeDist)
		
		-- Only move if significant distance
		if (finalPos - rootPart.Position).Magnitude > 2 then
			
			-- 1. Reset Velocity (Stop momentum so we don't slide)
			rootPart.AssemblyLinearVelocity = Vector3.zero
			rootPart.AssemblyAngularVelocity = Vector3.zero
			
			-- 2. Teleport
			local lookTarget = (type == "Projectile") and (rootPart.Position + dodgeDir) or (threat.Position)
			rootPart.CFrame = CFrame.new(finalPos, Vector3.new(lookTarget.X, finalPos.Y, lookTarget.Z))
			
			lastDodgeTime = now
			playEffects(mode, finalPos)
		end
		
		task.wait(0.05)
		isDodging = false
	end
end)

Features & Information

An autonomous Dodge script dodges most attacks
#Made by Educationalist

Community Comments (3)

myloveforyouisNAmyloveforyouisNAJun 7, 2026

bro which game tho

Replying to @myloveforyouisNA
idontcarelolz_281idontcarelolz_281Jun 16, 2026

@myloveforyouisNA pretty sure its universal

Replying to @idontcarelolz_281
noobbbynoobhahanoobbbynoobhahaAug 26, 2026

@idontcarelolz_281 hey any game?

More Scripts for Universal Scripts