hi! Im trying to make a horror game right now, and I’m trying to do work on some enemyAI right now, but I’m having a little bit of trouble. Right now I have a movement function in a module script, and I’m trying to add in raycast detection, though I am a little stuck.
local RS = game:GetService("RunService")
local enemy = require(game.ReplicatedStorage:WaitForChild("EnemyAI"))
function raycast()
local hum = script.Parent:WaitForChild("Humanoid")
local hrp = script.Parent:WaitForChild("HumanoidRootPart")
if hum then
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {script.Parent}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
local raycastResult = workspace:Raycast(
script.Parent.HumanoidRootPart.Position,
Vector3.new(10, 10, 10) * hrp.CFrame.LookVector,
raycastParams)
print(Vector3.new(10, 10, 10) * hrp.CFrame.LookVector)
if raycastResult then
print(";hit")
end
end
end
RS.Stepped:Connect(function()
--walk, if sees player print hit with raycast function
end)
since the movement is using moveto(pos).movedtofinished:wait(), it will wait until the thing finishes moving, then it will play the raycast function, but I want the raycast function to be playing at all times, even while its moving. Im pretty sure it has to do with coroutines, though I’m completely stuck with it. I tried reading the documentation and stuff like that but its all too complicated for my tiny brain to comprehend any help would be greatly appreciated!
if you need access to the module script, feel free to let me know!
You can use a function like task.spawn() to spawn a function in a new coroutine. You could have two loops running simultaneously, one that does the logic for the AI’s movement, and another loop that checks for targets using raycasting.
Coroutines allow you to introduce multi-tasking into your code, so when one coroutine yields, the next coroutine that needs to be executed gets resumed. So, for example, you could have your loop moving the enemy to waypoints in one coroutine, then once it hits the yield for MoveToFinished:Wait(), if your second loop needs to be resumed, it’ll do so and perform your raycasts.
Also, with your raycast, I assume you want to have the AI do a check 10 studs in the LookVector direction of the HRP? The math for that would be:
local direction = hrp.CFrame.LookVector * 10
local raycastResult = workspace:Raycast(hrp.Position, direction, raycastParams)
Where 10 is how far you want the raycast to check in studs.
sorry for another question, but is it ok if you dumb the beginning down for me for the task.spawn part and coroutines? Sorry I’m still really new to corouotines and the task functions
Sure! In the most basic sense, you can think of a coroutine as a separate function that does not stop or halt your code.
For example:
print("a")
task.wait(1)
print("b")
task.wait(1) will halt the code and "b" won’t be printed until 1 second later. However, if we want to print both at the same time but keep the yield for a different thing in our code, we can create a new coroutine:
"a" will print first, and then the yield statement will be hit, pausing that coroutine we just spawned. However, we have some more code that needs to be executed outside of the paused coroutine, so it’ll immediately print "b" as well. Then 1 second later, it will print "c".
Notice how the yield statement won’t stop "b" from printing right away!
Using this coroutines, we are now able to run multiple while loops in our code, like below. Both infinite while loops exist in separate coroutines so we are able to multi-task and hop back and forth between them!
task.spawn(function()
while true do
-- does whatever
task.wait(1)
end
end)
while true do
-- also does whatever
task.wait(1)
end