Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Changing the velocity of a part according to its impacted surface (like light)?

Right now I have the stock Hyperlaser; I'm trying to make the shot, on impact with a surface, change its velocity according to the angle of the shot relative to the surface impact, without changing its velocity.

The simplest example would be how light reflects off a completely reflective surface; that' the effect I'm trying to get here. I've tried tons of different code snippets that reflect in strange and bizarre ways.

How could I do this?

1 answer

✓ Accepted answer

This would be a good use of the Dot Product The dot product, also commonly known as the scalar product, is an operation preformed on vectors and returns a single number.

Example pulled from article:

local tool = script.Parent; -- the Tool
local handle = tool:WaitForChild("Handle"); -- does not continue without a Handle!
 
function reflect(input, normal) -- this vector reflector will reflect the laser 
	-- using dot method b/c vector3
	return -2 * input:Dot(normal) * normal + input; 
end;
 
function drawray(ray, parent) -- draws the ray of the laser
	local part = Instance.new("Part", parent or game.Workspace.CurrentCamera); -- do only you can see the lasers
	part.FormFactor = Enum.FormFactor.Custom;
	part.Material = Enum.Material.Neon; -- glowy effect c:
	part.Size = Vector3.new(.2, ray.Direction.magnitude, .2);
	part.CFrame = CFrame.new(ray.Origin + ray.Direction/2, ray.Origin + ray.Direction) * CFrame.Angles(math.pi/2,0,0);
	part.Anchored = true;
	part.CanCollide = false;
	part.BrickColor = BrickColor.new("Bright red");
	return part;
end;
 
function fire(from, to, bounce) -- function that fires the laser
	local bounce = bounce or 0;
	if bounce <= 5 then -- how many times can it reflect
		-- first ray is to calculate distance and normal
		local ray = Ray.new(from, (to - from).unit * 500);
		local hit, pos, normal = game.Workspace:FindPartOnRay(ray, tool.Parent);
 
		-- this is the actual ray we use and draw
		local ray2 = Ray.new(from, (pos - from));
		local part = drawray(ray2, tool);
 
		-- throw out the laser beam later
		game:GetService("Debris"):AddItem(part, 2);
 
		-- calculate the reflected ray
		local ref = reflect((pos - from), normal);
		if hit then
			local hum = hit.Parent:FindFirstChild("Humanoid");
			if hum then
				hum:TakeDamage(math.random(10, 15));
			end;
			-- shoot a ray in the reflected position
			fire(pos, pos + ref, bounce + 1);
		end;
	end
end;
 
script.Parent.Equipped:connect(function(mouse) -- connect the function to when the tool is equipped
	mouse.TargetFilter = game.Workspace;
	script.Parent.Activated:connect(function() -- whenever the player clicks with the tool out
		fire(handle.CFrame.p, mouse.Hit.p); -- call the function
	end);
end);

This discussion is preserved as it was. New answers, comments, and votes are closed.