Hey, I am trying to make a system to change the direction of the gravity. I did make the normal force to work properly but the force that simulates gravity to another direction doesn’t work. I need the vector’s direction to be towards a certain angle, which is the angle of the part’s surface.
This is the code I currently have, it is located in game.StarterPlayer.StarterCharacterScripts and it’s a local script.
local g = 196.2
local mass = 0
local NormalVector = Vector3.new(0,0,0)
local FakeGravityVector = Vector3.new(0,0,0)
local BodyForcesVelocity = 0
local NormalForce = script:WaitForChild("NormalForce")
local GravityForce = script:WaitForChild("GravityForce")
local Player = game.Players.LocalPlayer
local WallWalkingOn
local UserInputService = game:GetService("UserInputService")
function refreshMass()
local calcMass = 0
for i,v in pairs(Player.Character:GetDescendants()) do
if v:FindFirstChild("CanCheckForMass") then
if v.CanCheckForMass:IsA("BoolValue") then
if v.CanCheckForMass.Value == true then
calcMass += v:GetMass()
end
end
end
end
mass = calcMass
end
function checkForForces()
if script.Parent.PlayerIsWallWalking.Value == true then
if not script.Parent.HumanoidRootPart:FindFirstChild("newNormal") then
local newNormal = NormalForce:Clone()
newNormal.Name = "newNormal"
newNormal.Parent = script.Parent.HumanoidRootPart
end
if not script.Parent.HumanoidRootPart:FindFirstChild("newGravity") then
local newGravity = GravityForce:Clone()
newGravity.Name = "newGravity"
newGravity.Parent = script.Parent.HumanoidRootPart
end
else
if script.Parent.HumanoidRootPart:FindFirstChild("newNormal") then
script.Parent.HumanoidRootPart.newNormal:Destroy()
end
if script.Parent.HumanoidRootPart:FindFirstChild("newGravity") then
script.Parent.HumanoidRootPart.newGravity:Destroy()
end
end
end
function updateVectors()
BodyForcesVelocity = g*mass
NormalVector = Vector3.new(0,BodyForcesVelocity,0)
FakeGravityVector = Vector3.new(BodyForcesVelocity,BodyForcesVelocity,BodyForcesVelocity)
end
function updateForces()
local Normal = script.Parent.HumanoidRootPart:FindFirstChild("newNormal")
if Normal then
Normal.Force = NormalVector
end
local Gravity = script.Parent.HumanoidRootPart:FindFirstChild("newGravity")
if Gravity then
local a,b,c,alpha,results = findSurface()
if math.cos(alpha) == math.cos(alpha) then
Gravity.Force = Vector3.new(
BodyForcesVelocity * math.cos(alpha),
0,
BodyForcesVelocity *math.cos(alpha)
) * FakeGravityVector
print("Vector3.new( ".. Gravity.Force.X .." , ".. Gravity.Force.Y .." , ".. Gravity.Force.Z .." )")
end
end
end
function findAllWallWalkables()
local walkables = {}
for i,v in pairs(game.Workspace:GetDescendants()) do
if isWalkable(v) then
table.insert(walkables,v)
end
end
return walkables
end
function findSurfaceSurfaceAngle(Results)
local pos0 = Results.LeftFoot.Position
local pos1 = Results.RightFoot.Position
local pos2 = Results.HumanoidRootPart.Position
local a = (-(pos0.Y - pos2.Y + (((pos0.Y - pos1.Y) * (pos2.Z - pos0.Z)) / (pos0.Z - pos1.Z)))) / (pos0.X - pos2.X + (((pos0.X - pos1.X) * (pos2.Z - pos0.Z)) / (pos0.Z - pos1.Z)))
local b = 1
local c = (a * (pos1.X - pos0.X) + (pos1.Y - pos0.Y)) / (pos0.Z - pos1.Z)
local alpha = math.deg(math.acos(b/math.sqrt(a^2+b^2+c^2)))
return a,b,c,alpha
end
function findSurface()
local RayCastParams = RaycastParams.new()
RayCastParams.FilterDescendantsInstances = findAllWallWalkables()
RayCastParams.FilterType = Enum.RaycastFilterType.Whitelist
RayCastParams.IgnoreWater = false
local Results = {
LeftFoot = game.Workspace:Raycast(
game.Players.LocalPlayer.Character.LeftFoot.Position,
WallWalkingOn.Position,
RayCastParams
),
RightFoot = game.Workspace:Raycast(
game.Players.LocalPlayer.Character.RightFoot.Position,
WallWalkingOn.Position,
RayCastParams
),
HumanoidRootPart = game.Workspace:Raycast(
game.Players.LocalPlayer.Character.HumanoidRootPart.Position,
WallWalkingOn.Position,
RayCastParams
),
}
for i,v in pairs(Results) do
local part = Instance.new("Part")
part.Name = "CheckerPart"
part.Shape = "Ball"
part.Size = Vector3.new(0.5,0.5,0.5)
part.Transparency = 0.75
part.Position = v.Position
part.Anchored = true
part.CanCollide = true
part.CanTouch = true
part.Parent = game.Workspace
spawn(function()
wait(0.5)
part:Destroy()
end)
end
local a,b,c,alpha = findSurfaceSurfaceAngle(Results)
return a,b,c,alpha,Results
end
Player.Character:WaitForChild("HumanoidRootPart")
spawn(function()
while wait() do
local function a(su,er)
refreshMass()
checkForForces()
updateVectors()
updateForces()
end
local function b(su,er)
warn(su,er)
end
local su,er = xpcall(a,b)
end
end)
function isWalkable(obj)
if obj:FindFirstChild("WallWalkable") then
if obj.WallWalkable:IsA("BoolValue") then
if obj.WallWalkable.Value == true then
return true
end
end
end
return false
end
function refreshWallWalkingState()
local part = Instance.new("Part")
part.Name = "CheckerPart"
part.Shape = "Ball"
part.Size = Vector3.new(7.5,7.5,7.5)
part.Transparency = 0.75
part.Position = Player.Character.HumanoidRootPart.Position
part.Anchored = true
part.CanCollide = true
part.CanTouch = true
part.Parent = Player.Character.HumanoidRootPart
local TouchingParts = part:GetTouchingParts()
part:Destroy()
local changeTo = false
if #TouchingParts >= 1 then
for i,v in pairs(TouchingParts) do
changeTo = isWalkable(v)
if changeTo then
WallWalkingOn = v
break
end
end
end
script.Parent.PlayerIsWallWalking.Value = changeTo
end
UserInputService.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.Space then
if script.Parent.PlayerIsWallWalking.Value == true then
script.Parent.PlayerIsWallWalking.Value = false
else
spawn(function()
repeat
refreshWallWalkingState()
wait()
until script.Parent.PlayerIsWallWalking.Value == false
end)
end
end
end)