so before i get yelled at yes I did use ai, but I’m hoping to learn how it all works and eventually rewrite it myself, but for now I’ve ran into an issue, where the player doesn’t face left or right in the 2d plane, but instead front and back. How can I fix this? I tried a bunch of like repositioning but its eosnt work.
PlayerInputScript:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local rootPart = character:WaitForChild("HumanoidRootPart")
character.PrimaryPart = rootPart
local fightEvent = ReplicatedStorage:WaitForChild("FightState")
local playerStart = ReplicatedStorage:WaitForChild("PlayerStart") -- Vector3Value
-- Load animations
local animator = humanoid:WaitForChild("Animator")
local function loadAnimation(id)
local anim = Instance.new("Animation")
anim.AnimationId = "rbxassetid://" .. id
return animator:LoadAnimation(anim)
end
local walkFrontTrack = loadAnimation("111437686490686") -- Replace with correct ID
local walkBackTrack = loadAnimation("71507897049072") -- Replace with correct ID
local idleTrack = loadAnimation("134052246679083") -- Replace with correct ID
-- Movement config
local moveSpeed = 8
local moveVelocity = 0
local direction = 0
local keysPressed = { A = false, D = false }
local enabled = false
-- Animation control
local function updateAnimation()
if math.abs(moveVelocity) < 0.05 then
if not idleTrack.IsPlaying then
walkFrontTrack:Stop()
walkBackTrack:Stop()
idleTrack:Play()
end
elseif moveVelocity > 0 then
if not walkFrontTrack.IsPlaying then
idleTrack:Stop()
walkBackTrack:Stop()
walkFrontTrack:Play()
end
elseif moveVelocity < 0 then
if not walkBackTrack.IsPlaying then
idleTrack:Stop()
walkFrontTrack:Stop()
walkBackTrack:Play()
end
end
end
-- Facing logic
local function updateFacing()
if direction ~= 0 then
local facingAngle = direction == -1 and math.rad(180) or 0
local pos = rootPart.Position
character:SetPrimaryPartCFrame(CFrame.new(pos.X, pos.Y, playerStart.Value.Z) * CFrame.Angles(0, facingAngle, 0))
end
end
UserInputService.InputBegan:Connect(function(input, gpe)
if gpe or not enabled then return end
if input.KeyCode == Enum.KeyCode.A then
keysPressed.A = true
elseif input.KeyCode == Enum.KeyCode.D then
keysPressed.D = true
end
end)
UserInputService.InputEnded:Connect(function(input)
if not enabled then return end
if input.KeyCode == Enum.KeyCode.A then
keysPressed.A = false
elseif input.KeyCode == Enum.KeyCode.D then
keysPressed.D = false
end
end)
RunService.RenderStepped:Connect(function(dt)
if not enabled then return end
if keysPressed.A and not keysPressed.D then
direction = -1
elseif keysPressed.D and not keysPressed.A then
direction = 1
else
direction = 0
end
moveVelocity = direction * moveSpeed
humanoid:Move(Vector3.new(moveVelocity, 0, 0), true)
updateFacing()
updateAnimation()
end)
fightEvent.OnClientEvent:Connect(function(state)
enabled = state
if not state then
moveVelocity = 0
keysPressed = { A = false, D = false }
walkFrontTrack:Stop()
walkBackTrack:Stop()
idleTrack:Play()
end
end)
CameraController:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local workspace = game:GetService("Workspace")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local rootPart = character:WaitForChild("HumanoidRootPart")
local camera = workspace.CurrentCamera
local fightEvent = ReplicatedStorage:WaitForChild("FightState")
local opponentDummy = nil
local CAMERA_HEIGHT = 8
local CAMERA_MIN_ZOOM = 20
local CAMERA_MAX_ZOOM = 50
local enabled = false
local function getDummyRoot(dummy)
if not dummy then return nil end
return dummy:FindFirstChild("HumanoidRootPart") or dummy.PrimaryPart
end
fightEvent.OnClientEvent:Connect(function(state)
enabled = state
if not state then
camera.CameraType = Enum.CameraType.Custom
opponentDummy = nil
else
for _, obj in pairs(workspace:GetChildren()) do
if obj.Name == "Dummy" then
opponentDummy = obj
break
end
end
end
end)
RunService.RenderStepped:Connect(function()
if not enabled or not opponentDummy or not rootPart then return end
local dummyRoot = getDummyRoot(opponentDummy)
if not dummyRoot then return end
local playerPos = rootPart.Position
local dummyPos = dummyRoot.Position
local midpoint = (playerPos + dummyPos) / 2
local distance = (playerPos - dummyPos).Magnitude
local zoom = math.clamp(distance * 1.2, CAMERA_MIN_ZOOM, CAMERA_MAX_ZOOM)
local camPos = Vector3.new(midpoint.X, midpoint.Y + CAMERA_HEIGHT, midpoint.Z + zoom)
local camFocus = Vector3.new(midpoint.X, midpoint.Y, midpoint.Z)
camera.CameraType = Enum.CameraType.Scriptable
camera.CFrame = CFrame.new(camPos, camFocus)
end)
FightStateSwitcher:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local workspace = game:GetService("Workspace")
local fightEvent = ReplicatedStorage:WaitForChild("FightState")
local playerStart = ReplicatedStorage:WaitForChild("PlayerStart")
local opponentStart = ReplicatedStorage:WaitForChild("OpponentStart")
local dummyTemplate = ReplicatedFirst:WaitForChild("Dummies"):FindFirstChild("Dummy")
local triggerPart = workspace:WaitForChild("FightTriggerPart")
local function setupPrompt(part)
local prompt = part:FindFirstChildWhichIsA("ProximityPrompt")
if not prompt then warn("Missing ProximityPrompt!"); return end
prompt.Triggered:Connect(function(player)
local char = player.Character
local hrp = char and char:FindFirstChild("HumanoidRootPart")
if not hrp then return end
hrp.CFrame = CFrame.new(playerStart.Value)
if dummyTemplate then
local newDummy = dummyTemplate:Clone()
newDummy:PivotTo(CFrame.new(opponentStart.Value))
newDummy.Parent = workspace
else
warn("Dummy missing")
end
task.delay(0.2, function()
fightEvent:FireClient(player, true)
end)
end)
end
setupPrompt(triggerPart)