Making a combat game with ranged weapons? FastCast may be the module for you!

It’s spelled behavior, you wrote behaviour.

4 Likes

I can’t figure out why are there performance issues for the life of me
Okay so this might be a longer read but I’ll try to write down any info I can.

Obviously it’s called FastCast and everyone is saying that they have great performance. However I’m having major issues with performance. My target is to have 8 players on the server, who can be firing at the same time causing minimal lag to none. However already when just two players are shooting the script gets so demanding that the server ping goes up and everything starts to lag.

I’ve tried disabling every part of my script to find out where the performance issues lie:

  1. Validity checking if enough time has passed since last shot and many many more validity checks cause barely any lag on the server
  2. Ammo counting, no impact it’s just a couple of variables and a intvalue instance
  3. Effects also cause little to no impact(this includes muzzle flash, reload effects, cosmetic bullets)
  4. So the only thing left is the FastCast module itself and it’s causing quite the lag from what I can see in the Script Performance window.

I wanted to quickly check how does the example model blaster peform and it’s very costly on the server even for one person firing the weapon(the activity goes up to even 30%, damn)

So I’m wondering, am I doing something wrong or is the module not that optimized(no offence tho it’s an amazing module).

Another piece of information I can provide is that I’ve had quite the struggle to get fast cast implemented with my tool script which handles all the tools from one script instead of many scripts inside the tools.
My method was to create a multi dimensional table containing the player and everything needed to fire their caster. A new caster is created and put into the table instead of the old one whenever the weapon needs to change. To fire, the caster is simply requested from that table.

Hey! So, I’ve been messing around with this module for a while, and I’ve been trying to get the gun to fire ONLY when the mousebutton is up or just fully clicked, do you have any idea of how I could go about doing this? I’m using this version of the module. I am aware that this might be quite a dumb question, but I’m still not that experienced with scripting. Thanks!

Edit: I’ve found the solution, apparently I didn’t write my code correctly. At around line 150, I wrote down this code.

Tool.Activated:Connect(function()
   CanFire = true
end)

Quite a simple solution, but I didn’t really pay attention earlier.

I think there have indeed been unwanted performance regressions. I am working on fixing them. They came around after the addition of ActiveCast which makes sense considering it has changed from a simple event connection to an entire object to keep track of.

You’re interested in Tool.Deactivated, which fires when the mouse is released.

1 Like

Version 13.2.0 has been released!

This update has a number of good changes that you can read about here.

Most notably, cast resolution enforcement has been added! This means that it’s now possible to always cast with say, 1 stud long increments. This is great for physics simulation as it promises more accurate - and more importantly consistent - results regardless of latency or lag.

I’ve also fixed a mistake involving how I import types. I was unaware that you required a reference to the module that instantiated the type – that is, Module.MyType rather than just MyType. Whether or not this has performance or behavioral implications is something I haven’t really noticed.

3 Likes

You broke it :sweat_smile:studio now stops responding if I try to add the model in. Only crashes with fastcast, can insert any other model from the toolbox, but not fastcast

2 Likes

^^^
Same problem as above, inserting the model causes my studio to crash.
Only for the FastCast models

Interesting! This seems to be a side effect of the Lua script analysis beta @NinjoOnline @20amir02 – disable this beta feature and then insert the model. It works fine there.

I’ll get this information to the right people as soon as I can. For now, you’ll need to disable the feature, I’m afraid.

5 Likes

Thank you for the solution, now i can use this module.

One roadblock I ran into is that I’ve been getting errors when I try to terminate the ActiveCast in the Casters LengthChanged event.
image
I seemed to stop the errors by adding a check in between the lines in the module.

	SendLengthChanged(cast, lastPoint, rayDir.Unit, rayDisplacement, segmentVelocity, cast.RayInfo.CosmeticBulletObject)
	if not cast.StateInfo then return end
	cast.StateInfo.DistanceCovered += rayDisplacement

Though I do feel like there could’ve been a better method. Just letting you know.

You aren’t supposed to be terminating casts in LengthChanged anyway, let alone any event handler. Termination is more for if an outside source needs to come in and stop a cast, such as a network replication script.

2 Likes

I am looking for advice on how to set this up, because in my use case, I am not using a tool like the example gun. I have a single module that will be accessed by any player in the game, and the documentation for this FastCast states we should never be creating a new Caster each time we want to fire a bullet (in my case they are knives).

I notice that there is no :Destroy method in the FastCast constructors? Why is this? Where are the casters stored and how are they garbage collected if at all?

In my case, given that I have a single module for all players in the game, where would I be storing these casters for use when a player returns to the module after the initial time there? Should I create a table and when I create the new caster, put it in the table with the players UserId or something like that? I fi do that, then I have to track PlayerRemoving and cleanup after the player, which feels a little overly complicated.

My knife throwing ability has a longish cooldown, something like 10 seconds between throws, would it be OK to just create a new caster each time?

Thanks!

They are stored in your script when you instantiate them, and they are GC’d through stock Lua GC – Drop all references to the caster and it will be disposed of.

local myCaster = FastCast.new()
-- some use code here ...
myCaster = nil
-- caster instance will now be GC'd because there's no more references to it

Modules cache when require()'d. Alongside this, I recommend a LocalScript in StarterPlayerScripts that instantiates the caster - scripts in that location will run once and never reload until the player flat out leaves the game and rejoins. All other client scripts can reference it via events or whatever it may be. If the player leaves, the script is destroyed, and by extension, the caster managed by that script will be GC’d. No need to track players leaving and joining on the clientside.

For the server, you should have one caster for all players – Presumably, the players will all be using the same knife. Think of a caster like a “factory” for projectiles - you only need one thing making the projectiles if there’s only one type of projectile. Each individual person does not need their own factory to create something for them on the server. A client should simply go to the server and say “Hey, I’m throwing a knife, can you make one for me?” and the server will do just that.

The client differs because if you plan to do rendering on the client, then the client needs to be independent of the server. It should still be one module, just each client should call FastCast.new() once.

No, time does not change anything. A single unified caster is the way to go.

this is helpful, thank you!

I was doing some setup and simply requiring the latest version of the module yields all code in my game, I looked and on line 127 of the main script, Roblox studio is giving an error.

FastCastRedux - Roblox Studio (gyazo.com)

so all I am doing is just requiring the FastCastRedux module in a script, if I do that, it yields completely and the game wont run past that point. If I simply comment out that require, everything works fine.

Ah it’s just a warning, if you go to TypeDefinitions, you will see that FastCastBehavior defines CanPierceFunction: PierceFunction (or whatever I put it as). It should have a ? after it making PierceFunction? which means that it’s able to be nil. You can make this edit yourself for now

will this stop the module from yielding? as it is now, i cant use the module at all.

The yielding might be due to something with Luau. It used to completely crash studio if you inserted it, now it just locks it up for about a second or two. Is this what’s happening in your script too?

Just yields indefinitely, no errors and no crash

Is there an older version of this module available, something more stable?

I can’t get this issue to occur, it may likely be in your script. Please check everything and make sure you haven’t made any mistakes (Did you try modifying the module to tinker with it and forget you did it? Try inserting a fresh copy.)

I did not modify anything, just required it from my script.

I had to literally copy and paste the entire code though because I use Rojo. Is there any way to download a file system version of the project?

EDIT: I went ahead and re-copy/pasted all the code into my file system and this time, I am not getting any yields. I was fairly sure I did a clean job, but I guess it was my own error. I am grateful for all of your work here but I have one request! Could you please upload this to GitHub so we can have a file system version of this code? That would be so helpful I think :slight_smile:

1 Like