Help with ball physics

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 :slightly_smiling_face: :slightly_smiling_face: :slightly_smiling_face:

1 Like

not readin allat

kidding

however, I would recommend instead of creating an entirely new ball, just changing their humanoidrootpart to a ball and unanchoring it; also you’ll need to make all the other parts on their character not able to collide.

This way, you can set the charactervelocity locally with userinput and not have to update it from the server; since it’s from the client and it will automatically update the character’s cframe.

I would change anything cosmetic and physical from the server though, only handle the input from the player. You wont need to have the server update the character’s movement though as it’ll be updated automatically.

1 Like

Sorry for not explaining well, I want you to forget about the player character in my prototype it does not exist, the only thing that is there is a cylinder that is controlled by the player’s mouse and a ball that bounces off some walls, thank you for helping me and take your time with long text

Bouncing off the walls is easy with Roblox’s default physics.
However, You can probably make it follow the mouse by making it go towards a location with a function to get the mouse’s position in the 3d space. If you need help with that I can do that tomorrow morning but not rn.

1 Like

If someone is willing to help me, then: what this consists of is a cylinder which will always follow the direction of the mouse, that is, mouse.Hit.Position, and the movement will be noticed on the server, each physics response, that is, each hearthbearth. In the collision function called updateball which detects collisions between the ball with the walls and the cylinder taking into account the restitution value

The physics of Roblox do not make a ball bounce exactly the way I want, much less being a cylinder, as you will see I am making my own physics and I want to find the solution to the problems I currently have.