I want to make a physics system that consists of a cylinder that will be controlled by the player’s mouse (it should be noted that the server will move it with each physics response, that is, each “HearthBearht”).
There will be the ball which will be another cylinder that will move and bounce inside a room with 4 walls with no exit and will bounce with the cylinder.
here is the script
local RunService = game:GetService("RunService")
-- Crear una referencia a la pelota, los cilindros y las paredes
local ball = game.Workspace.PN2:WaitForChild("Ball")
local cylinder1 = workspace.PN2:WaitForChild("Cilindro")
local cylinder2 = workspace.PN2:WaitForChild("Cilindro2")
local RemoteEvent = game.ReplicatedStorage.RemoteEvent
local Parametros = RaycastParams.new()
Parametros.RespectCanCollide = true
local walls = game.Workspace.PN2.Walls
task.wait(2)
-- Definir algunas constantes para el radio de la pelota, los cilindros y el coeficiente de restitución
local ballRadius = 2.2
local cylinderRadius = 5.5
local restitution = 10
local ballVelocity = Vector3.new(0, 0, 0)
-- Definir una variable para la velocidad de la
----Definir una función para calcular la distancia entre dos puntos
local function distance(p1, p2)
return (p1 - p2).Magnitude
end
--Definir una función para calcular el vector normal entre dos puntos
local function normal(p1, p2)
return (p2 - p1).Unit
end
-- Definir una función para calcular el ángulo entre dos vectores
local function angle(angle)
--[[print(v1,v2)
print(v1:Dot(v2))
print(v1.Magnitude * v2.Magnitude)
print(v1:Dot(v2) / (v1.Magnitude * v2.Magnitude))
if v1:Dot(v2) / (v1.Magnitude * v2.Magnitude) == math.huge then
end]]
return math.acos(angle)
end
-- Definir una función para calcular el vector reflejado de un vector incidente sobre una superficie normal
local function reflect(incident, normal)
return incident - 2 * normal * incident:Dot(normal)
end
-- Definir una función para actualizar la posición y la velocidad de la pelota cada fotograma
local function AtributoChange(Part)
if Part:GetAttribute("Primero") then
return (Part:GetAttribute("Valor") * Part.CFrame.RightVector)
else
return (Part:GetAttribute("Valor") * Part.CFrame.LookVector)
end
end
local function updateBall(step)
local T = tick()
local newPosition = ball.Position + ballVelocity * step
for i, wall in pairs(walls:GetChildren()) do
local WS = wall.Size
local WC = wall.CFrame
local LowerLeft = WC:PointToWorldSpace(Vector3.new(-WS.X/2,-WS.Y/2,-WS.Z/2))
local CP = ball.Position
local CS = ball.Size
local CLowerLeft = Vector3.new(CP.X - CS.X/2,CP.Y - CS.Y/2,CP.Z - CS.Z/2)
local CUpperRight = Vector3.new(CP.X + CS.X/2,CP.Y + CS.Y/2,CP.Z + CS.Z/2)
local UpperRight = WC:PointToWorldSpace(Vector3.new(WS.X/2,WS.Y/2,WS.Z/2))
if CUpperRight.X > LowerLeft.X and CLowerLeft.X < UpperRight.X and CUpperRight.Y > LowerLeft.Y and CLowerLeft.Y < UpperRight.Y and CUpperRight.Z > LowerLeft.Z and CLowerLeft.Z < UpperRight.Z then
local Dot = ballVelocity:Dot(AtributoChange(wall))
local Direccion = ballVelocity - 2 * Dot * AtributoChange(wall)
ballVelocity = Direccion
newPosition = ball.Position + ballVelocity * step
end
end
for _, cylinder in pairs({cylinder1}) do
--Calcular la distancia entre el centro de la pelota y el centro del cilindro
local d = distance(newPosition, cylinder.Position)
-- Si la distancia es menor que la suma de los radios de la pelota y el cilindro, hay colisión
if d < ballRadius + cylinderRadius then
-- Calcular el vector normal entre el centro de la pelota y el centro del cilindro
local n = normal(newPosition, cylinder.Position)
-- Calcular el punto de contacto entre la pelota y el cilindro
local contactPoint = newPosition - n * ballRadius
--Calcular el ángulo entre la velocidad de la pelota y el vector normal
local Angle = newPosition:Dot(cylinder1.Position) / (newPosition.Magnitude * cylinder1.Position.Magnitude)
local theta = angle(Angle)
-- Si el ángulo es menor que 90 grados, la pelota se está acercando al cilindro
if theta < math.pi / 2 then
-- Calcular el vector reflejado de la velocidad de la pelota sobre el vector normal
local ReflejarVelocidad = (cylinder1.Position - ball.Position) * -1
local reflectedVelocity = reflect(ballVelocity, n)--INCORRECTO
-- Multiplicar el vector reflejado por el coeficiente de restitución para reducir la velocidad
local newVelocity = ReflejarVelocidad * restitution
-- Calcular la distancia que se ha sobrepasado la pelota al colisionar con el cilindro
local overlap = ballRadius + cylinderRadius - d
-- Calcular la nueva posición de la pelota restando el vector normal multiplicado por la distancia sobrepasada
local correctedPosition = newPosition - n * overlap
-- Actualizar la posición y la velocidad de la pelota con los nuevos valores
newPosition = correctedPosition
ballVelocity = newVelocity
else
end
else
end
end
-- Comprobar si la pelota colisiona con alguna de las paredes
-- Asignar la nueva posición de la pelota al atributo Position de la parte
ball.Position = Vector3.new(newPosition.X,ball.Position.Y,newPosition.Z)
if tick() - T > step then
print(tick() - T)
end
end
-- Conectar la función updateBall al evento Heartbeat del servicio RunService
RunService.Heartbeat:Connect(updateBall)
RemoteEvent.OnServerEvent:Connect(function(plr,Pos:Ray)
cylinder1.Position = Vector3.new(Pos.X , cylinder1.Position.Y, Pos.Z)
cylinder1.Orientation = Vector3.new(0, 0, 90)
end)
then I find myself with several problems and needs:
-I want the last lines where the OnServerEvent is located…
change the Restitution Variable to a logical bounce value that takes into account the Delta, the distance between the two points, and the last restitution you had when you bounced.
THE REST IS IN ADDITION, IF YOU WANT HELP, EVERYONE GIVES THEIR PART IF THEY WANT. THESE ARE PROBLEMS I HAVE.
- When the ball goes in one direction and the player’s cylinder goes in the opposite direction with the intention of bouncing the ball, the cylinder passes the ball and hits it from behind when the cylinder and the ball are going at high speed. This is because the HearthBearth skips a small space due to the high speed. I don’t know what solution I should look for.
-Another problem that I do see important to solve is that the ball bounces off a wall from one side (when it bounces from the side)
It stays stuck to the wall and sometimes goes out of bounds.
I need a solution that anyone can give me, I would appreciate it very much, thank you