I’m trying to make AI that will move around a players ‘tycoon base’ just at random. Almost all videos/wiki pages, etc. On AI focus on pathfinding, but none of them show you how to make the AI actually just move to random spots within a squared area. I’ve thought about maybe using BodyGyro or BodyPosition but not entirely sure what I am doing.
given that you know how to pick the position/vector3 values so that they are within the desired place, you could use a Humanoid’s MoveTo method to tell it to go towards a certain point, or Move method which makes them go in a direction rather than at a target
local character = script.Parent
local humanoidRootPart = character:WaitForChild('HumanoidRootPart')
local humanoid = character:WaitForChild('Humanoid')
local base = character.Parent.Parent.Base
local step = 2
while wait(step) do
humanoid:Move(Vector3.new(math.random(base.Position.X), 0, math.random(base.Position.Z)))
end
This is what I wrote up. AI moves, but just picks a direction and runs until they fall of the map. Base is the players Tycoon area btw (So I only want the AI to stay within that area)
given that you have the base part, I’d use MoveTo with given points like this
while wait(step) do
humanoid:MoveTo(
(base.CFrame *
CFrame.new(
math.random(-base.Size.x,base.Size.x),
humanoid.HipHeight,
math.random(-base.Size.z,base.Size.z),
)).p
)
end
the code has been split in lines so that it is easier to see, but it should be doable in one line
one issue I can see with this is if the “base” part has an unusual rotation, let us say, 90 degrees in either x or z axis
Small problem, is on the odd occasion, some of them drift off onto the brown part. The base part is the green (light green, there are darker green spots on top of the base, which I’ll eventually have it so the AI can only walk on the light green grass, instead off all of the grass) But yeah, I don’t know why they drift into the brown area. It’s not common, but still a noticeable amount do it
EDIT Is there also a way of making them stand still for a period? Atm they just run around constantly. Would just setting their walkspeed to 0 be the best way of accomplishing this?
NVM I tried, and they just don’t walk (guessing it’s setting their walkspeed to 0 before they reach the set spot)
local character = script.Parent
local humanoidRootPart = character:WaitForChild('HumanoidRootPart')
local humanoid = character:WaitForChild('Humanoid')
local base = character.Parent.Parent.Base
local walkTime = math.random(3, 5)
local waitTime = math.random(1, 3)
while true do
humanoid:MoveTo((base.CFrame * CFrame.new(math.random(-base.Size.x,base.Size.x), humanoid.HipHeight, math.random(-base.Size.z,base.Size.z)).p))
wait(walkTime)
humanoid.WalkSpeed = 0
wait(waitTime)
humanoid.WalkSpeed = 10
end
Edited code to have them stop walking and walk for random periods of time each. Noticed that they seem to still fall off the base as well, as well as walking on the brown part
Yeah it is rotated. What coordinates would I use to make it work on the rotation (each base has different rotations, so needs to work for all of those)
I used position based on a CFrame value so that it accounts for the base’s rotation, and only downside to that is if it’s rotated and resized in a way that I didn’t expect, which I suppose is not
if you use MoveTo method, and not Move, then it should move strictly to that position and then stop when the humanoid reached that position
if I overlooked something in my example above, is that an npc might sometimes decide to move on the edge of the base and might fall from that, so I’d change it into something like
local dis = 5 – minimum distance from edges of base
humanoid:MoveTo((base.CFrame * CFrame.new(math.random(-base.Size.x+dis,base.Size.x-dis), humanoid.HipHeight, math.random(-base.Size.z+dis,base.Size.z-dis)).p))
Forgive me if my solution is not the most elegant. I’ve not messed around with CFrames for a while and I moved away from vectors in my further maths module so it might be awful
From everything I’ve seen, you understand the problem. The rotation of the part doesn’t affect the translation of the random size, and that’s the issue.
local sizeX, sizeZ = base.Size.X/2, base.Size.Z/2
local randomDisplacement = Vector3.new(math.random(-sizeX, sizeX), 0, math.random(-sizeZ, sizeZ))
humanoid:MoveTo(base.CFrame:vectorToWorldSpace(randomDisplacement) + base.Position)
If you’ve a basic understanding of scripts, I hope these lines of code help you to achieve your aim
another thing I noticed is that I didn’t divide the base.Size.x or base.Size.z by 2, since it will count from the center of the base
local dis = 5 – minimum distance from edges of base
humanoid:MoveTo((base.CFrame * CFrame.new(math.random(-base.Size.x/2+dis,base.Size.x/2-dis), humanoid.HipHeight, math.random(-base.Size.z/2+dis,base.Size.z/2-dis)).p))
thanks to @Zarkonan_Zenheart since that example does so
I’m glad to have done something useful haha. I forgot that mutliplying a CFrame with another CFrame is the same as a translation in object space. Thanks for the reminder