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

You should add a parameter to specify the starting alpha (totalDelta) of the shot.

Would it make sense to just keep track of every players Caster instance with the Players.PlayerAdded event?

FastCast v9.1.0 is out, ladies and gents!

+ Added new built-in cast visualization. No more copying code from the example gun. This new visualization is very versatile and shows casts that are cancelled (due to piercing), as well as hits.
* Fixed a bug with piercing casts sometimes skipping embedded solid objects (e.g. a piercable wall with a layer of non-piercable stuff inside of it) (reported by dispeller)
* POTENTIALLY fixed a bug causing physics casts to fall through the floor or walls (reported by lots and lots of people)
- Removed visualization code from the example gun.


(n.b. the red arrows are casts that ran but were cancelled due to piercing.Green spheres represent casts that were allowed to continue after impact, and red spheres represent casts that stopped due to an impact)

9 Likes

I could see to this.

It’d work.

2 Likes

Uhh, I don’t think this looks right?
https://gyazo.com/d103d43733889386e338c419e2a4047b

All I did was make the projectile slow, and add downwards acceleration in the bulletAcceleration parameter to simulate gravity
The shots seem to hit correctly (I tested 20 shots, and all of them hit correctly), so is it a problem with your visualizator?

Also, do you simply ray cast from point in previous frame to point in current frame? If so, then wouldn’t shots with unique acceleration, like not hit detect correctly if there is lag/delay between frames?

Apologies if this has been answered already, I tried to look through most of the thread (over 90%). I’m new to using this module and I’m trying to make a gun system. I want to make the networking behind it as least laggy as possible while not being too exploitable. I found that this reply and this reply seemed to know how to make a non-laggy weapon but I’m having trouble understanding how they work so I can make my own from scratch using those ideas while functioning well. I noticed that using a modified debug gun it gets annoying to try and aim at moving targets as the higher the ping, the later the shots you sent in certain directions hits the target you want.

Any help would be greatly appreciated. :grin:

1 Like

Hey EtiTheSpirit!

I’m not sure if you updated the Module to use the new Raycast API but I think you should put the module on Github since you are busy and we want to help you with maintenance.

1 Like

Probably. I’ll look into it.

Yes, this is one of the caveats of lag. Think of it like this: You have a graphing function, say, x^2. On a real graph, that’s a smooth curve, but in a game we are limited by certain increments of time. The effect is that you get a jagged line instead of a curve. More latency between captures (more lag) = a less precise representation of what’s truly going on under the hood.

Thank you, this module is amazing! It works perfectly.

When looking through the example gun, I noticed this (on line 96 of the server script):

local myMovementSpeed = humanoidRootPart.Velocity		-- To do: It may be better to get this value on the clientside since the server will see this value differently due to ping and such.

Wouldn’t that be exploitable? Exploiters could send any value they want though the RemoteEvent. This could be fixed with clamping it on the server, but exploiters could still send a high value and have the bullets travel slightly faster for them.

Also, is it possible to have bouncing bullets with this module? I’m ok with having to do a little extra math myself, but I don’t exactly know how this module works yet and if it would even be possible.

Is there a way to prevent the bullet delay that occurs when shooting? When shooting initially, the bullet doesn’t appear until it reaches a few studs from the gun. This happens sporadically, and I was wondering if there was a fix for it. Thank you!

Is there a way I can access the velocity of the cast at any time during its trajectory? Trying to manually figure out the velocity with the formula v = d / t by using past positions and their times is very unreliable. LengthChanged seems to fire at such frequent intervals that recording time in the connected function seems to round off a lot of numbers. This results in wild discrepancies in the calculated velocity.

Code:

Caster.LengthChanged:Connect(
	function(_, SegmentOrigin, SegmentDirection, _, Projectile)
		local CurrentTime, CurrentPos = time(), SegmentOrigin
		local DeltaTime, DeltaPos = CurrentTime - Projectile.LastTime.Value, (Projectile.LastPosition.Value - CurrentPos).Magnitude
		Projectile.CurrentSpeed.Value = DeltaPos / DeltaTime
		print(DeltaPos, "|||||", DeltaTime, "|||||", Projectile.CurrentSpeed.Value)
		Projectile.LastTime.Value = CurrentTime
		Projectile.LastPosition.Value = CurrentPos
		Projectile.CFrame = CFrame.new(SegmentOrigin, SegmentOrigin + SegmentDirection)
	end
)

When the Caster is first fired, the LastTime, LastPosition, and CurrentSpeed ValueBases are assigned the initial values that were input into the Caster’s Fire function.


Black cone arrows are just from FastCast’s VisualizeCasts property enabled.

1 Like
Bug

Looks like you made a mistake with the distance traveled. You added displacement.Magnitude. This is fine with non-piercing projectiles, but it reduces the “range” (total distance to be traveled) on piercing projectiles (test this out with the DebugGun by shooting it at bunch of parts together while piercing demo is on, it should not go 1000 studs (the default range), but less because of hitting those parts). I believe you were supposed to add (point-lastPoint).magnitude right before the if hit and hit ~= cosmeticBulletObject then line? Unless you intended to reduce its “range” on hit?

Feature request

could you add a way to change the projectile’s trajectory mid-fire/mid-flight? Maybe store the projectile and check if another FastCast:Fire() sent the same object as projectile, and discard the projectiles’s previous :Fire()?

1 Like

That needs to be done manually for now. When I get around to adding the ability to redirect bullets during flight-time, this will probably be an option.

Not with default behavior, no, but I can see about adding this in.

The underlying issue is actually kind of complicated it seems, or I’m overcomplicating it due to being so tired. The old behavior set lastPoint = at. This worked great, with the exception that sometimes rays got spaced apart and this is why people were reporting issues where bullets with physics fell through the floor.

I’m going to do some work on this issue after I sleep so ideally I should have it fixed in a little while.

Hey I’ve got a weird issue going on with FastCast. I’m replacing my current system with it, but I’ve run into an issue that’s making it impossible currently. I’ve based it off the code from the example blaster you gave. Here’s my code:

EDIT: Bottom two lines are part of the script, but I couldn’t get it to past correctly. self.HitP is equivalent to

(Mouse.Hit.p - FirePointObject.WorldPosition).Unit

local Caster = FastCast.new() --Create a new caster object.
FastCast.VisualizeCasts = true

local directionalCF = CFrame.new(Vector3.new(), self.HitP)
local RNG = Random.new()
local TAU = math.pi * 2	

self.HitP = (directionalCF * CFrame.fromOrientation(0, 0, RNG:NextNumber(0, TAU)) * CFrame.fromOrientation(math.rad(RNG:NextNumber(0, 0.5)), 0, 0)).LookVector
print(self.HitP)

local modifiedBulletSpeed = (self.HitP * 200) + self.Player.Character.HumanoidRootPart.Velocity;

self.Projectile.CFrame = CFrame.new(self.Player.Character.Weapon.Barrel.Attach.WorldPosition, self.Player.Character.Weapon.Barrel.Attach.WorldPosition + self.HitP)
self.Projectile.Parent = workspace.Projectiles;

Caster:Fire(self.Player.Character.Weapon.Barrel.Attach.WorldPosition, self.HitP * 1000, modifiedBulletSpeed, self.Projectile, self.Player.Character, false, Vector3.new(0,0,0));

Caster.LengthChanged:Connect(function(castOrigin, segmentOrigin, segmentDirection, length, cosmeticBulletObject)
	local bulletLength = self.Projectile.Size.Z / 2 -- This is used to move the bullet to the right spot based on a CFrame offset
	local baseCFrame = CFrame.new(segmentOrigin, segmentOrigin + segmentDirection)
	self.Projectile.CFrame = baseCFrame * CFrame.new(0, 0, -(length - bulletLength))
end)
Caster.RayHit:Connect(onHit);

EDIT2: It seems to happen whenever the mouse is pointed at an object. That is, if I point towards a wall, it will go up. If I point towards the sky, it goes normally.

Basically, depending on which way the character’s is pointing, if it’s pointing down towards a baseplate, the rocket instead of shooting straight forward will shoot up at an angle. That’s not a behavior I want - i’d rather it go to the ground, even if that means it makes contact and explodes right away. I’ve attached a video belowrobloxapp-20200626-1302033.wmv (2.0 MB)

1 Like

This seems to be an issue with your method of hit detection. The module itself does not do anything to the input direction value.

You should consider double-checking how you grab the mouse’s position in 3D space. It seems to be hitting some part in front of your character (maybe you’re clicking on the view model?)

Good news folks! FastCast V10.0.0 is out!
https://github.com/XanTheDragon/FastCastAPIDocs/wiki/Changelist#fastcast-1000

This fixes the bugs reported by many others as well as the most recent reported by @problems_0zz where physics based casts were all finnicky. This also implements @GFink’s request of accessing segment velocity. THIS CHANGE WILL NOT WORK WITH OLDER VERSIONS OF THE API. See the LengthChanged event, RayHit event, and CanRayPierce callback on the wiki for more information.
[color=#808080][size=2]The main reason this occurred was because I implemented the wrong math. When calculating the velocity of the given segment, I didn’t calculate it from the initial velocity and acceleration. Instead, I used the initial velocity alone. This resulted in things getting all mixed up, which in turn caused physics casts to be “pulled apart” (which is what allowed them to clip through things at times). Whoops.[/size][/color]

As for the new changes, you code should look a little something like this. Note the implementation of the segmentVelocity values.

function CanRayPierce(hitPart, hitPoint, normal, material, segmentVelocity)
    -- ...
end

function OnRayHit(hitPart, hitPoint, normal, material, segmentVelocity, cosmeticBulletObject)
    -- ...
end

function OnRayUpdated(castOrigin, segmentOrigin, segmentDirection, length, segmentVelocity, cosmeticBulletObject)
    -- ...
end
5 Likes

I was creating a weapon and implementing both FastCast and the PartCache module into it, and it resulted in me discovering an error in the PartCache module. On Line 303, the rayHitEvent variable that is being fired is missing a variable, so the cosmeticBulletObject is one variable too early and is the 5th variable. Maybe I’m wrong, but I found that when rayHitEvent is fired on Line 250, cosmeticBulletObject is the 6th variable.

Line 250
rayHitEvent:Fire(hit, point, normal, material, segmentVelocity, cosmeticBulletObject)

Line 301-304

if distanceTravelled > distance then
   connection:Disconnect()
   rayHitEvent:Fire(nil, lastPoint, nil, nil, cosmeticBulletObject)
end

Since I’m using the provided gun from this thread that uses the module, I’ll paste some code from it. This error in the module results in this line not being correct in the case where the fired projectile goes past its max distance:
function OnRayHit(hitPart, hitPoint, normal, material, segmentVelocity, cosmeticBulletObject)

Basically the cosmeticBulletObject in the line above ends up being nil if the projectile goes too far, since the event in that case isn’t fired correctly. This doesn’t have any negative effects on the module itself, though it might confuse anyone trying to incorporate the PartCache module with this one since they need a reference to their cosmetic bullet so they can re-cache the bullet.

Once again, maybe I’m wrong but adding another nil in the event fire on Line 303 fixed it. Thought I’d just throw this out there so it can be fixed. Besides that, thank you for making this module! It works really great and has saved me a ton of time :happy3:

1 Like

Oh awesome. Thanks for letting me know. Yes, line 303 should have a zero value for segmentVelocity. I’ll release an update to patch that right now.

Edit: Patch is live.

2 Likes

I think the FastCast:FireWithWhitelist and FastCast:FireWithBlacklist functions are not handling the canPierceFunction variable correctly. They are not passing it into the BaseFireMethod function, in which only FastCast:Fire seems to do so. I noticed this as I was adding a playerWhoFired variable to the end of each function, so that I could know who shot a bullet after it hits someone so I could award points accordingly. I’m using FireWithBlackList and the MandateType assert was failing and saying the canPierceFunction was an instance, so that was quite confusing for awhile lol

Hello, first I’d like to say I love the module really helped me out. I’ve been working on a Naval Cannon for some time now and I just recently started making grape shot(shot gun like pellets) able to be fired. To do so I did a i loop for x amount of times I want pellets fired. After I realized my pellets were hitting each other I switched to “FireWithBlacklist”. Problem is I’m still having the same problem with my pellets hitting each other. https://gyazo.com/75781c34f7ab514361d0b612d0b1c7a1 Any help would be appreciated.