In this video, you can see an example of two different spells being fired. I was wondering how you can achieve an effect like that while not compromising insane amounts of accuracy (the spell landing far off target). Is it truly random or is there an algorithm?
The method I’m using rn is a simple straight projectile that uses rays to check a hit
If it’s a physical projectile, you can give it different forces at different points, based on whatever you want. If you’re strictly using data, you can use a node system for a pre-calculated path (it will still have to calculate live with the projectile in case something moves in the way).
There are many ways to do the second option, but you basically have control over time and offset, and can use that in your algorithm. A spiral, for example, would simply be having a straight line of nodes that get rotated by time and offset outward by some amount, either static or also multiplied by time (if you want the spiral to grow the longer it lasts). These nodes don’t have to be generated all at once, you can generate them throughout the lifetime of the projectile, to maximize how dynamic it is.
the x and y offset (relative to lookvector of the projectile) is x=cos(theta) and y=sin(theta), and then for randomness you just add some noise so x += math.noise(t) and y += math.noise(t+offset)
i think both use the same formula, but the first one moves slower because you just make the angle and time change slower
i think precalculating points is worse than just calculating a dynamic offset but you would do something like
local function generateNodes(distance : number, start : Vector3, velocity : Vector3) : {Vector3}
local NODE_DISTANCE = 2 -- one node every two studs
local ROTATION_SPEED = 2 -- how fast the spiral rotates
local SPIRAL_MAGNITUDE = 5 -- how big the spiral is
local NOISE_VOLATILITY = 0.1 -- how volatile the noise (random movement) Is
local NOISE_MAGNITUDE = 1 -- how strong the noise is
local nodes : {Vector3} = {}
local nodeCount = distance / NODE_DISTANCE
for i = 1, nodeCount do
local currentPosition = start + (velocity * i)
local angle = i * ROTATION_SPEED
local offsetX = math.cos(angle) * SPIRAL_MAGNITUDE
local offsetY = math.sin(angle) * SPIRAL_MAGNITUDE
local noiseX = math.noise(i*NOISE_VOLATILITY) * NOISE_MAGNITUDE
local noiseY = math.noise(i*NOISE_VOLATILITY) * NOISE_MAGNITUDE
nodes[i] = currentPosition + Vector3.new(offsetX, offsetY, 0) + Vector3.new(noiseX, noiseY, 0)
end
return nodes
end
and then the position of the projectile at any given point is the linear interpolated vector3 of nodes[i+1] and nodes[i]
edit: lerp would be like a zigzag line, so you could use something like bezier curve or just dynamic offset would be the best