Need help with ghost AI

Hello there!
I’m currently working on game that needs to have like ghost killing NPCS
But it is working the problem is I want the ghost is looking to a NPC that is he killing or the ghost looks where is he randomly going
This is my script:

local AttackableNPCS = workspace.AttackableNPCS
local GhostOwner = script.Parent.OWNER.Value
local IsAttacking = false

function GetNearestNPC()
	local SelectedNPC = nil
	for i,v in pairs(AttackableNPCS:GetChildren()) do
		if (v.HumanoidRootPart.Position - script.Parent.Ghost_BODY.Position).Magnitude <= 30 then
			SelectedNPC = v
			break
		end
	end	
	return SelectedNPC
end

while wait() do
	if GhostOwner == "NONE" then
		script.Disabled = true
	else
		local SelectedNPC = GetNearestNPC()
		if SelectedNPC == nil then
			local RandomPos = script.Parent.Ghost_BODY.Position + Vector3.new(math.random(-10,10),0,math.random(-10,10))
			script.Parent.Ghost_BODY.BodyPosition.Position = RandomPos
			wait(5)
		elseif SelectedNPC ~= nil and IsAttacking == false then
			IsAttacking = true
			script.Parent.Ghost_BODY.BodyPosition.Position = SelectedNPC.HumanoidRootPart.Position - Vector3.new(math.random(-5,5),0,math.random(-5,5))
			script.Parent.Ghost_BODY.BodyGyro.CFrame = CFrame.new(script.Parent.Ghost_BODY.BodyPosition.Position,SelectedNPC.HumanoidRootPart.Position)
			repeat
				wait()
			until (SelectedNPC.HumanoidRootPart.Position - script.Parent.Ghost_BODY.Position).Magnitude <= 10
			script.Parent.Ghost_BODY.BodyGyro.CFrame = CFrame.new(script.Parent.Ghost_BODY.BodyPosition.Position,SelectedNPC.HumanoidRootPart.Position)
			local BeamEffect = game.ReplicatedStorage.AttackBeam:Clone()
			BeamEffect.Parent = script.Parent.Ghost_BODY
			BeamEffect.Attachment0 = script.Parent.Ghost_BODY.EffectAttachment
			BeamEffect.Attachment1 = SelectedNPC.HumanoidRootPart.SoulEffect
			SelectedNPC.HumanoidRootPart.SoulEmiterHandler.SoulEmmtier.Enabled = true
			repeat 
				SelectedNPC.Humanoid.Health -= 5
				wait(0.3)
			until SelectedNPC.Humanoid.Health <= 0
			BeamEffect:Destroy()
			--game.Players[GhostOwner].leaderstats.Souls.Value += 1
			wait(3)
			IsAttacking = false
		end
		if SelectedNPC ~= nil then
			if SelectedNPC:FindFirstChild("HumanoidRootPart") then
				script.Parent.Ghost_BODY.BodyGyro.CFrame = CFrame.new(script.Parent.Ghost_BODY.BodyPosition.Position,SelectedNPC.HumanoidRootPart.Position)
			end
		end
	end
end

Results:
https://streamable.com/8km931

NOTE: This script will be reporgrammed once I know the solution for this!
Thanks for any help!

1 Like

so whats the problem exactly with it i dont really understand. also it you should use more variables in your code.

Problem is that that the ghost isn’t look at right place

you dont want it to be spinning around you want it to be looking at the character hes attacking?

Yeah and when it lurks it will look at the position that is ghost going to

So exaplain I never used :ToWorldSpace()

actually ive changed my mind ToWorld Positoin will not work effectively for your game INSTEAD we are going to just use CFrame:

so as my example code it will make the Red Part (which you can compare to as your ghost to the blue part which you can treat asa your character

local redBlock = game.Workspace.RedBlock
local BlueBlock = game.Workspace.BlueBlock

local RedBlockPosition = redBlock.Position
local BlueBlockPosition = BlueBlock.Position

--parameter1: where the block is 
--parameter2: where the block is looking
--so the block that will be looking is the "redBlock" it will be looking from the 
--RedBlockPosition and it will be looking towards the BlueBlockPosition
redBlock.CFrame = CFrame.new(RedBlockPosition, BlueBlockPosition)

and what it does is makes this:
image
do this:
image

so in short you need to:
get the HumanoidRootPart.Position
get your Ghost.RootPart.Position

and then do

Ghost.RootPart.CFrame = CFrame.new(Ghost.RootPart.Position, HumanoidRootPart.Position)

make sure to use variables in your code though becaue it will make them run more efficiently!

What you did not help me at all

you need to put that in your loop and it will make it face the player. i thought thats what you wanted?

treat the BluePart as the character and the RedPart as the ghost

do you need me to tell you how to incorporate this into your script or something? if you want i can type it into your code for you.

Im already doing this you know

oh well if its the spinning thats annoying you then its probably your BodyGyro movements because they are really easy to get wrong, try instead use a service to move the Ghost to the Selected NPC

like:
–Tween Service
–Lerp Service
–MoveTo Service

because at the momment you are using pyshics that are messing up the movement

if your set on using pyschics though your options are:

–vector force
–allign position
–rocket propulsion (definitely worth looking into)

Uhmmm, So what? I don’t know what to do

Hmm can you explain clearly what’re you trying to do. Honestly, I barely understand what’re you saying. Not to be mean but please consider to use Grammarly before posting as it will confuse most of us. I suggest using Magnitude for the “BodyPosition.Position” part where u set the ghost’s distance before trying to such player’s life ← as what I’m understand what are u trying to do, this is my solution.

after the player dies, just set it to destroy the BodyGyro or stop it when it faces the player’s previous CFrame. Using lookVector3 Raycast(Use this before the player dies so that it stores the previous CFrame in order to set it later)

rocket propulsion is more of a thing for projectiles, for example: Homing Missiles, Heat tracking projectiles,…

The simplest way by doing it with bodygyro will be using CFrame. Here how it will work.

function GetNear()
	local sel 
	for i,v in pairs(workspace.AttackableNPCS:GetChildren()) do
		if (v.PrimaryPart.Position - script.Parent.Position).Magnitude <= 30 then
			sel = v.PrimaryPart
			break
		else
			sel = "NONE"
		end
	end
	return sel
end
local Gyro = script.Parent.BodyGyro
local BPos = script.Parent.BodyPosition
BPos = script.Parent.Position
while wait() do
	local The_NPC = GetNear()
	if The_NPC ~="NONE" then
		Gyro.CFrame = CFrame.new(script.Parent.CFrame.p, The_NPC.CFrame.p)
	end
end

This will make the ghost look at the character but this is one problem left using bodygyro and changing rotation while the object is anchored will not work. so instead you will add bodyvelcity and set it velocity to 0,0,0 to keep the object at it place and for bodygyro if you want the front to look at object change it MaxTorque to 400000, 400000, 400000.
Note: It will only working with front face and not any other side.