So I have just started dipping my toe into the Roblox Studio this week, I have only 7-8 months experience coding custom content for games in LUA and it was quite some time ago. This is however my first attempt virtually from scratch also (obviously) my first with Roblox, forgive me if I overlook something stupid.
I have been attempting to get familiar with Roblox’s base code and studio features and I was shocked at how much limitation there is honestly and with how few basic features 90% of devs would use are not plug-and-play ready… but I understand it was meant to be ‘close’ to plug-and-play for the younger gen and 99% of the games are so simplistic it doesn’t matter.
Advanced help/examples/references etc are far and few between other than the massive and unwieldy roblox wiki for studio which covers many things but I still had some questions.
To the topic point! Before I dive head in spend a month coding and regret later not asking the newbie questions before I would like some development related advice on which direction to go for scripting the full setup.
Issue/Question #1:
I have seen several mentions of “Script Heavy Games are laggy”, “Too many enemies is laggy” etc however there are no actual guidelines on just how lite a game needs to be to run well.
Does anyone have a rough estimate of how many Scripted/Animated Enemies in an area, or view range, or single server that can be active before this occurs? or what limit in the studio performance I should aim to remain under? Partially answered by Katrist
Question #2: Answered by Katrist - Glad it works this way!
Issue/Question 3: NPC Follow, Face, Stop when Close issue resolved with help from Katrist
Still wondering if there is a way to shave the performance down any without sacrificing the animation but glad it’s working the way I desired without conflicting commands :D.
Thanks for sticking around this long, I am excited to get started on a little RPG here which I realize is far more involved than most themes, hell you could throw together a horror chase game in a day, but if I wasn’t in over my head learning as I go it wouldn’t be as much fun!
@Katrist the bringer of good news! Just what I wanted to hear except now I have to figure out how to setup the main script to control multiple npcs .
Appreciate the link it is a useful plug but I am doing ok with that part, moving them from point to point or thru a maze isn’t too bad once you setup the material weights. It’s the custom needs of one script for moving only in X range of a player to commence it’s combat function that is getting me and the modules I tried only did the basics. (Ill recheck that one just in case I overlooked something important)
What I am stuck on is specifically the handling of after searching for & finding a qualifying nearest player RootBodyPart having it MoveTo() but only within X studs of the final POS of a moving target.
I just can’t quite put my hand on the verbiage for it to use a single function/calculation of playerPos vs npcPos and both choose to chase when > 3 studs away and also maintain/move away when =< 3.
Only way I have done it so far is to run 2 functions each finding the Character:FindFirstChild(“Humanoid”) each running a separate calculation with .Magitude and outputting a local which then tells it to basically Run towards or Step back. One variation I had worked but then the NPC after 15 minutes or so playing would run too close to the player and then run back to the 3 stud limit resulting in it facing away.
The variation I have now works it just constantly has conflicting information… and I haven’t found a good way to turn one command off while the other runs without breaking what I wanted it to do.
Working isn’t the same as optimized I guess is what I am getting at.
I’m still playing with it maybe i’ll figure it out if not ill just post the script at some point for some assist.
Until then if anyone knows a good way to aim the MoveTo target X studs away while maintaining it facing the player I am alll ears!
local Players = game:GetService("Players")
local NPC = script.Parent
local HumanoidRootPart = NPC.HumanoidRootPart
local Humanoid = NPC.Humanoid
local function FindNearestCharacter(position: Vector3)
local nearestCharacter = nil
local nearestDistance = math.huge
for i, player in Players:GetPlayers() do
local character = player.Character
local humanoidRootPart = character and character:FindFirstChild("HumanoidRootPart")
local distance = humanoidRootPart and (humanoidRootPart.Position - position).Magnitude
if distance and distance < nearestDistance then
nearestCharacter = character
nearestDistance = distance
end
end
return nearestDistance, nearestCharacter
end
while task.wait() do
local nearestDistance, nearestCharacter = FindNearestCharacter(HumanoidRootPart.Position)
if nearestCharacter then
local position = nearestCharacter.HumanoidRootPart.Position
if nearestDistance < 3 then
HumanoidRootPart.CFrame = CFrame.lookAt(HumanoidRootPart.Position, Vector3.new(position.X, HumanoidRootPart.Position.Y, position.Z))
Humanoid:MoveTo(HumanoidRootPart.Position - HumanoidRootPart.CFrame.LookVector * 3)
else
Humanoid:MoveTo(position)
end
end
end
No idea what happened there but I disabled my script, updated the Humanoid local to my workspace.UniqueNPCname and it made the NPC teleport on top of my head and fly up and down in the sky! Amusing to watch buuuut I had not even thought about using the LookVector to aim away from the target.
I popped that into my other chase script and I am much closer, will just have to add in a line to make it face the player at all times. Had another version that had the same issue but it would completely turn around at times, with the CFrame it’s only slightly off.
The humanoid is supposed to be the humanoid, not the character. The NPC is the character. Sorry for not clarifying that, thought the variable names were enough.
If you want me to show a video, I can. It works for me atleast.
Ah my fault, I have changed my NPCs body to “Monster” which avoids the need for extra measures to prevent attacking or damaging each other. -Certainly adds some extra work but worth it… I think. I’ll try the edit.
Phew ok that one threw me a bit, you did exactly the same thing as one of my older attempts that tells it to moveto (exact pos of players inner torso) elseif move away 3 studs but with very different verbiage. It resulted in the npc running close smoothly then glitch-porting directly to my side and attempting to run thru me. Basically attempting to do both things at once. [This is actually what most people want because they just use touch-damage, i’ve been trying to position it for an attack animation instead.]
If you remove the elseif variable at the end to the moveto exact position of the rootbody part it makes the character walk away when close (useful) and not chase at all. Also the Lookat line where you placed it only works if shes in the “stay away” distance but it will still turn around to walk away and stop facing once its in that < 3 range.
I ended up moving the - Vector * to pos in my script and the .lookat you put in, it works perfectly without the extra needed “else” at the end.
I updated the one you sent as well to show my desired outcome, certainly helped me figure that one out thank you!
Mostly looking for tips and advice to maximize performance as I write up scripts for various things. Had a minor NPC issue we resolved still curious if theres a way to limit how often it loops without causing the walk animation to glitch but that part is minor.
Right now looking at the options for handling multipleNPCs functions with minimal impact, i’ve seen Controller functions suggested as well as building a basic table for all NPCs in a folder or workspace, my favorite at the moment might be a Module Script just curious if theres a “best” way as far as end performance goes.
Worried ill end up laggy and having to cut features if I begin the setup wrong from the start.
Will be doing DataStore, Custom Inventory, Random Loot, Currency, Animated NPC Combat (lots of them), Player Classes - usual RPG stuff. Atleast as much as I can get away with on the platform.
Any ways I can find to improve performance vs my current trains of thought is a bonus!
In developing your project, it’s advisable to handle NPC physics and state updates on the server side to maintain consistency across clients and prevent cheating. Utilizing a RenderStepped or Heartbeat event on the server for updating NPC states can be effective. For animations, consider rendering them on the client side to reduce server load. Keep track of NPC positions on the server and send the necessary information to clients for rendering, ensuring a balance between server and client responsibilities.
Implementing Dependency Injection is a good practice for managing dependencies and improving code organization. Exploring design patterns like the Singleton pattern for managing global state or the Observer pattern for handling events can contribute to a more structured codebase. Learning from other languages such as C#, and frameworks like .NET, can provide valuable insights into best practices and efficient coding techniques. Adapt project structures from languages like Golang, Python, and JavaScript for better organization and scalability.
When dealing with NPC update loops, consider implementing a time-based or delta-time approach to update NPCs at a consistent rate without overloading the system. Using a Module Script for NPC management can be beneficial, allowing you to encapsulate NPC-related functionalities in a modular way, making your code more maintainable. Additionally, leverage Roblox Studio’s built-in performance profiler to identify bottlenecks in your code and prioritize optimizations based on the profiler’s results.
Threading or asynchronous operations can be explored to prevent blocking the main thread and improve overall responsiveness. Optimize your usage of DataStore to minimize unnecessary data transfers and reduce latency. Consider caching frequently accessed data locally to minimize the number of DataStore requests. Lastly, adopt an incremental development approach, starting with a minimal viable product and incrementally adding features. This allows you to test and optimize each component individually, making performance improvements more manageable over time.