Ayuda con el Ray

Antes de hablar sobre mi problema, si no sabes que es un Ray, lo explico. Un Ray, es una línea invisible generada desde un punto 3D, desde el cual puede ir hacia alguna dirección, con una función llamada FindPartOnRay, podemos detectar la colisión de un Ray con un objeto.

Ahora sí, resulta que estoy programando a los enemigos de mi juego los cuales funcionan de la siguiente forma:

  • Ellos generan un Ray entre el enemigo y un jugador
  • Si ellos detectan la colisión del ray con un jugador, a continuación, inician una función que detecta su distancia, una vez ya se sabe la distancia entre el jugador con el enemigo, se procede a la última función
  • Dependiendo de la distancia, analizan la distancia con la distancia de cada acción tal que así
if Distance < ActionDistance then
  distances.Action(objetivo)

El problema es el siguiente, digamos que… el enemigo, solo hace funciones cuando existe una conexión de Ray, esto es un grave problema para la animación Idle… me explico mejor.

Este enemigo, solo se moverá y atacará, cuando el Ray del enemigo esté conectado con el jugador. El problema es que, el enemigo, cuando no tiene a ningún jugador dentro de su “Área de Acción o Ataque”, este supuestamente se tendría que quedar “Idle” o parado, haciendo una animación hasta que el jugador se acerque a él y… realmente la hace, pero no como yo tenía previsto. Como ya he dicho, las acciones solo se hacen cuando hay una conexión del Ray del enemigo con el jugador, por lo tanto, aunque estés alejado de él, si no le “miras” o si hay un obstáculo entre ti y él, este no hará la animación aunque esté parado.

Alguna solución?

1 Like

Supongo que será algún problema de bucle o condiciones. Podría ver tu código actual?

local RobotController = {}
 
local TiempoDeAccion = .1
 
local function DistanciaPaE(enemy, character)
	if not character or character.Humanoid.Health <= 0 then return nil end
	local toPlayer = character.HumanoidRootPart.Position - enemy.HumanoidRootPart.Position
	local toPlayerRay = Ray.new(enemy.HumanoidRootPart.Position, toPlayer)
	local part = game.Workspace:FindPartOnRay(toPlayerRay, enemy, false, false)
	if part and part:IsDescendantOf(character) then
		return toPlayer.magnitude
	end
	return nil
end
 
local function recibirPlayerCercano(enemy)
	local menorDistancia = math.huge
	local playerCercano = nil
	for _, player in pairs(game.Players:GetPlayers()) do
		local distancia = DistanciaPaE()(enemy, player.Character)
		if distancia and distancia < playerCercano then
			menorDistancia = distancia
			playerCercano = player.Character
		end
	end
	return playerCercano, menorDistancia
end
 
function RobotController:RunAI(enemy, configurations)
	while wait(TiempoDeAccion) and enemy.Humanoid.Health > 0 do
		local target, targetDistance = recibirPlayerCercano(enemy)
		if target then	
			if targetDistance < configurations.ActionDistance then
				configurations.Action(target)
			elseif targetDistance < configurations.DetectingDistance then
				configurations.Aggro(target)
			elseif targetDistance > configurations.DetectingDistance or targetDistance > configurations.ActionDistance then
				configurations.NotMoving(target)
			elseif not target then
				configurations.NotMoving(target)
			end
		end
	end
end

return RobotController

Ese es el código que uso para controlar al Enemigo, como se puede ver, primero se genera el ray y s e clasifica como una función, luego se genera otra función donde, a base de la primera función y de las distancias recibidas, se identifica la magnitud del player y el enemy. Por último cada 0.1 Segundos se actualizan las acciones, si la distancia es esa y el Ray está alineados se hace la acción.

PD: La respuesta atrasada ha sido porque he estado ocupado con unas cosas del aprendizaje de Roblox Studio :c

En la consola no sale ningún error de eso? Porqué siento que haz invocado mal la función ahí, debería ser DistanciaPaE(enemy, player.Character)

He hecho un repaso entero del scripts, el DistanciaPaE(enemy, character) no causa ningún problema, al ser un ModuleScript el Script se “junta” con el otro scripts que hace alusión al personaje.

No sale ningún error no, de hecho cuando intenté hacer un cambio en el script de detección de distancia, me daba error, así que así como está es la única forma que he encontrado de que no tenga errores.

local RobotController = {}
 
local TiempoDeAccion = .1

--Detector de Distancia
local function DistanciaPaE(enemy, character)
	if not character or character.Humanoid.Health <= 0 then return nil end
	local toPlayer = character.HumanoidRootPart.Position - enemy.HumanoidRootPart.Position
	local toPlayerRay = Ray.new(enemy.HumanoidRootPart.Position, toPlayer)
	local part = game.Workspace:FindPartOnRay(toPlayerRay, enemy, false, false)
	if part and part:IsDescendantOf(character) then
		return toPlayer.magnitude
	end
	return nil
end

--Detector de Distancia (Sin Ray)
local function DistanciaAlejada(enemy, character)
	if not character or character.Humanoid.Health <= 0 then return nil end
	local toPlayerAlejado = character.HumanoidRootPart.Position - enemy.HumanoidRootPart.Position
end

--Detector para Ataque/Seguimiento
local function recibirPlayerCercano(enemy)
	local menorDistancia = math.huge
	local playerCercano = math.huge
	for _, player in pairs(game.Players:GetPlayers()) do
		local distancia = DistanciaPaE(enemy, player.Character)
		if distancia and distancia < playerCercano then
			menorDistancia = distancia
			playerCercano = player.Character
		end
	end
	return playerCercano, menorDistancia
end

--Detector para Inactividad
local function recibirPlayerAlejado(enemy)
	local mayorDistancia = math.huge
	local playerAlejado = math.huge
	for _, player in pairs(game.Players:GetPlayers()) do
		local distanciaAlejada = DistanciaAlejada(enemy, player.Character)
		if distanciaAlejada and distanciaAlejada < playerAlejado then
			mayorDistancia = distanciaAlejada
			playerAlejado = player.Character
		end
	end
	return playerAlejado, mayorDistancia
end
 
--Funciones
function RobotController:RunAI(enemy, configurations)
	while wait(TiempoDeAccion) and enemy.Humanoid.Health > 0 do
		local target, targetDistance = recibirPlayerCercano(enemy)
		local nilTarget, targetAlejadaDistance = recibirPlayerAlejado(enemy)
		if target then	
			if targetDistance < configurations.ActionDistance then
				configurations.Action(target)
			elseif targetDistance < configurations.DetectingDistance then
				configurations.Aggro(target)
			elseif targetAlejadaDistance > configurations.DetectingDistance or targetAlejadaDistance > configurations.ActionDistance then
				configurations.NotMoving(target)
			elseif not target then
				configurations.NotMoving(target)
			end
		end
	end
end

return RobotController

No se como no lo pensé la primera vez :joy:

Simplemente he hecho (dentro del mismo scripts) una copia de los “Detectores de Personajes” y los he modificado para que no haya un Ray. Bueno, gracias por el intento de ayudar @Ince_FS :slight_smile:.