Projectile movement?

I’m currently working on a Wand system - It’s essentially 100% operational to the needs I require.
However I’m struggling to create any sort of /decent/ movement effect?
By this I mean as opposed to moving in a linear line - It has a somewhat erratic movement to it similar to the projectiles in YouTube video posted below.

Below is the code I use for projectile movement.
Does anyone have any suggestions on how I can achieve the desired effects? Somewhat spinning etc.

local LastPos = Part.Position
				Part.CFrame *= CFrame.new(-Vector3.zAxis * 5)
				
				local Distance = (Part.Position - LastPos).Magnitude
				local Direction = (Part.Position - LastPos).Unit * Distance
				
				local RaycastParam = RaycastParams.new()
				RaycastParam.FilterType = Enum.RaycastFilterType.Exclude
				
				RaycastParam.FilterDescendantsInstances = {Part.Parent.Parent}
				
				local Result = Server:GetService('Workspace'):Raycast(LastPos, Direction, RaycastParam)
				if not Result then
					--
				else
					Part.Position = Result.Position
					Part:RemoveTag('Projectile')
				end

If you want the movement to be completely erratic, moving randomly (but still getting to its target),
you could just add a random amount to its position, keeping track of the actual intended position, like so:

if not Result then
	--
else
	IntendedPos = Result.Position
	Part.Position = Result.Position + Vector3.new(math.random(), math.random(), math.random())
	Part:RemoveTag('Projectile')
end

Then when changing the part’s position afterwards you can do it based off IntendedPos instead of the part’s actual position, so that the part wont stray away from where it’s meant to go.

I think your best bet is to use various particle effects like lightning and such.

Though @mynameisjeb2018’s response is valid, I would like to add that it may make it too random, especially if the update rate is high. Ideally, it would be for hit-detetion purposes, and so would be client-sided and update with RenderStepped.

The first spell appears to use a sine wave to create an oscilating effect (in other words, going up and then down). All you need is a constantly increasing or decreasing number as ‘x’ in math.sin(x) to create this effect. In this case, you could just use the elapsed time since the projectile began.

To make the waves shorter, multipy x by a value greater than one, and the opposite for making them longer. Similarly, to make the waves taller, multiple the result of “math.sin(x)” by a value greater than 1 or the opposite to make them shorter.

Then you can use the final result to offset the spell’s visuals by a certain amount in a wave-like pattern. Though remember that it’s only the visual here being effect; the real hitbox is still in the center of the oscilation, so gameplay isn’t effected.

2 Likes

Thank you, I’ll have a go with Sins & Cos this evening.

Do you happen to have a formula stripped down to basics that I could potentially build off?

Thank youu

Would probably look something like this

totalTime

runservice.RenderStepped:Connect(function(delta)
	totalTime += delta
	--//Regular movement
	projectileCore.CFrame *= CFrame.new(0,0,-speed * delta)

	doHitDetectionStuff()

	--// Use sine to offset projectile
	local SinOffset = math.sin(totalTime)
	
	--// Also a slight spin could be put on the projectile like this. I think, idk.
	local Spin = (20 * totalTime)%360

	visualOffset = projectileCore.CFrame * (CFrame.new(0,SinOffset,0) * CFrame.Angles(0,0,math.rad(Spin)))
end)

I’m still struggling to an extent to get desired results :confused:
I’ve attached a video of it done in ROBLOX in another game to give another example?

What do you have currently? You may want to try the script without the spin effect to see where it lands you.

1 Like

I’m making this same thing at the moment, I’ll post my code once I wrap it up here later today, but to keep it short:

  1. Get the Start and Finish positions

  2. Get the Vector3 between those two positions

  3. Create a loop which:
    a) breaks that single long Vector3 into a series of positions (still techniclaly Vector3’s). Set the distance between each position to be the length you want each ‘erractic arc’ to be.
    b) add the X and Y offset to each position
    c) Insert that position into a table

  4. Loop through that table and tween your projectile from its current position to the current indexed position that your loop is at.

Disclaimer that this likely isnt the most efficient way to do it, as I have a line count to meet, but it does accomplish the desired projectile motion pattern that you’re describing.

I’ll edit this post with the the code once I’m done :+1:

1 Like

When it comes to projectiles I’ve never really worked with Start & Finish points.

I’ve always used motion in a sense that once the Projectile is fired it’ll move along the Parts LookVector until either it times out or a collision is detected, I’ve found this to be my best way of detecting accurate collisions.

Where as moving along a linear Path from A to B, especially using a tween, doesn’t use a desired response if you get me?

Got sidetracked – didn’t forget about you.

I made it to follow this type of logic, and therefore it ignores my previous post’s outline. You can play around with it to tweak it however you like.

-- Demo chaotic projectile movement; you can run this in your studio console

local c0:CFrame = CFrame.new(0,10,0)		-- Starter position
local distanceInterval:number = 5			-- Distance per interval
local xOffset:number, yOffset:number = 1,1	-- Offset intervals for the 'chaotic' effect

-- Create projectile
local p:BasePart = Instance.new("Part",workspace) p.Name = "Projectile"
p.Size = Vector3.new(0.5,0.5,1)
p.Color = Color3.new(1,1,1)
p.CFrame = c0

-- Bonus: A trail to help visualize the path
local att0 = Instance.new("Attachment", p) att0.Position = Vector3.zAxis*2.5
local att1 = att0:Clone() att1.Parent = p att1.Position = Vector3.zAxis*-2.5
local trail = Instance.new("Trail", p) trail.Attachment0 = att0 trail.Attachment1 = att1 
trail.TextureMode = Enum.TextureMode.Stretch
trail.MaxLength = 30
trail.TextureLength = 5
trail.WidthScale = NumberSequence.new(0.5) trail.Transparency = NumberSequence.new(0,1)
trail.Color = ColorSequence.new(p.Color)

-- I used a for loop that will cause it travel 150 studs for simplicity
local rayParams:RaycastParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.FilterDescendantsInstances = {p}
for iterator:number = 0, 150, distanceInterval do task.wait(0.05)
	-- Raycast for part detection. Uses c0 as a reference to keep the projectile path linear
	local rayResult:RaycastResult = workspace:Raycast(c0.Position, c0.LookVector.Unit*distanceInterval,rayParams)
	if rayResult then
		-- Whatever happens on hit
		break
	else
		c0 *= CFrame.new(0,0,-distanceInterval) -- Update our reference point
		p.PivotOffset = CFrame.new(math.random(-xOffset,xOffset),math.random(-yOffset,yOffset),0) -- Apply the offset to make it 'erratic'
		p:PivotTo(c0) -- Use PivotTo to apply the PivotOffset. Setting CFrame wont create the effect
	end
end
p:Destroy() -- Cleanup
2 Likes

This looks promising!
I’ve been looking into Bezier Curves & was wondering about utilising this to create a zigzag flow also.
I’ll look into this soon, thank you!

Can help with Bezier curves

Hi,

When I run this in the command bar , it errors out…

and way to get it in a .rbxl or a model etc.?? that works…

 18:15:48.836  require(79851394307177).GetReleases()-- Demo chaotic projectile movement; you can run this in your studio console

local c0:CFrame = CFrame.new(0,10,0)		-- Starter position
local distanceInterval:number = 5			-- Distance per interval
local xOffset:number,:1: attempt to call a nil value  -  Edit
  18:15:48.836  Stack Begin  -  Studio
  18:15:48.836  Script 'require(79851394307177).GetReleases()-- Demo chaotic projectile movement; you can run this in your studio console

local c0:CFrame = CFrame.new(0,10,0)		-- Starter position
local distanceInterval:number = 5			-- Distance per interval
local xOffset:number,', Line 1  -  Studio
  18:15:48.836  Stack End  -  Studio

You’re output shows the error is on line 1 - aka the line you added to require a module. Cant help ya there