<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.starfall.wtf/index.php?action=history&amp;feed=atom&amp;title=How_to_Create_a_Black_Hole</id>
	<title>How to Create a Black Hole - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.starfall.wtf/index.php?action=history&amp;feed=atom&amp;title=How_to_Create_a_Black_Hole"/>
	<link rel="alternate" type="text/html" href="https://wiki.starfall.wtf/index.php?title=How_to_Create_a_Black_Hole&amp;action=history"/>
	<updated>2026-07-28T16:15:08Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://wiki.starfall.wtf/index.php?title=How_to_Create_a_Black_Hole&amp;diff=462&amp;oldid=prev</id>
		<title>PRG: Created page with &quot;{{CatUp|Tutorials}} {{ScriptTutorial|Advanced|Lua Script}} __TOC__  ==Introduction== A black hole destroys SonOfSevenLess&#039;s castle This tutorial is designed for advanced scripters and scripters who can be described as medium-level. It will cover several concepts, such as area-of-effect, and will provide the finished code for a black hole at the end.  If you are unable to understand this tutorial, it is suggested that yo...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.starfall.wtf/index.php?title=How_to_Create_a_Black_Hole&amp;diff=462&amp;oldid=prev"/>
		<updated>2024-12-10T21:57:35Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;{{CatUp|Tutorials}} {{ScriptTutorial|Advanced|Lua Script}} __TOC__  ==Introduction== &lt;a href=&quot;/index.php/File:BlackHole_01.jpg&quot; title=&quot;File:BlackHole 01.jpg&quot;&gt;thumb|A black hole destroys SonOfSevenLess&amp;#039;s castle&lt;/a&gt; This tutorial is designed for advanced scripters and scripters who can be described as medium-level. It will cover several concepts, such as area-of-effect, and will provide the &lt;a href=&quot;#Finished_Code&quot;&gt;finished code&lt;/a&gt; for a black hole at the end.  If you are unable to understand this tutorial, it is suggested that yo...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{CatUp|Tutorials}}&lt;br /&gt;
{{ScriptTutorial|Advanced|Lua Script}}&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
[[Image:BlackHole 01.jpg|thumb|A black hole destroys SonOfSevenLess&amp;#039;s castle]]&lt;br /&gt;
This tutorial is designed for advanced scripters and scripters who can be described as medium-level. It will cover several concepts, such as area-of-effect, and will provide the [[#Finished Code|finished code]] for a black hole at the end.&lt;br /&gt;
&lt;br /&gt;
If you are unable to understand this tutorial, it is suggested that you learn from the Novice tutorials first. If you are merely here to get a black hole, you can find in Roblox Studio in Insert / Free Models / typing &amp;quot;Black Hole&amp;quot; / Clicking &amp;quot;Search&amp;quot; / double-clicking the black hole you want.&lt;br /&gt;
&lt;br /&gt;
== Starting off ==&lt;br /&gt;
&lt;br /&gt;
Before creating a black hole, it is prudent to clear an area and [[Anchored|anchor]] anything in the area which you would like to keep.  Beware, as black holes actually increase in power as they gain mass, so the area should probably be at least 128 units in radius.  It is also a good idea to figure out EXACTLY what you want the black hole to do. In this case, I have laid out the desired effects and the concepts that I use.   &lt;br /&gt;
&lt;br /&gt;
===Desired Effects===&lt;br /&gt;
The black hole will do the following:&lt;br /&gt;
* Suck up &amp;#039;&amp;#039;ANYTHING&amp;#039;&amp;#039; that can move within a reasonable radius.&lt;br /&gt;
* &amp;#039;&amp;#039;Destroy&amp;#039;&amp;#039; objects that get close enough. &lt;br /&gt;
===Concepts===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;[[Anchored]]&amp;#039;&amp;#039;&amp;#039; The black hole, to be efficient, should not attempt to suck up any brick that cannot move anyway. This also prevents the floor from being destroyed.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Area of Effect&amp;#039;&amp;#039;&amp;#039; This black hole will suck &amp;#039;&amp;#039;ANYTHING&amp;#039;&amp;#039; that comes within a reasonable distance into itself.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Arrays&amp;#039;&amp;#039;&amp;#039; Arrays are sets of variables.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Children&amp;#039;&amp;#039;&amp;#039; In order to find every brick, functions will need to find them first.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Classes&amp;#039;&amp;#039;&amp;#039; The black hole must only work on certain types of objects, namely &amp;quot;Parts&amp;quot;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Iteration&amp;#039;&amp;#039;&amp;#039; Functions will use loops to cycle through arrays.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Mass&amp;#039;&amp;#039;&amp;#039; Similar to weight, but without taking gravity into account.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Recursion&amp;#039;&amp;#039;&amp;#039; The function for finding objects will call itself.&lt;br /&gt;
&lt;br /&gt;
==Variable Initialization==&lt;br /&gt;
The black hole will need to keep track of a number of things. It will need an array to keep track of objects and a floating-point variable to keep track of its mass (power).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;local hole = script.Parent -- Optional. Added for optimization&lt;br /&gt;
local childList = {}&lt;br /&gt;
local massConstant = 5.8 -- Generally a good value (again, optional)&lt;br /&gt;
local mass = 32000 * massConstant&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Area of Effect==&lt;br /&gt;
Area of effect is one of the most important concepts when creating a black hole, or any script intended to affect a wide range of bricks. The basic idea is to find every brick in the map, add them to an array, and use the array later. A &amp;#039;&amp;#039;&amp;#039;recursive&amp;#039;&amp;#039;&amp;#039; function will work well, allowing both simplicity and elegance.&lt;br /&gt;
&lt;br /&gt;
Create a function, in this case called &amp;#039;&amp;#039;checkObject&amp;#039;&amp;#039;, which accepts an object&amp;#039;s handle as an input. I named this variable &amp;#039;&amp;#039;obj&amp;#039;&amp;#039;. This function will first get the array of children using&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;local list = obj:GetChildren()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the child&amp;#039;s &amp;#039;&amp;#039;className&amp;#039;&amp;#039; variable indicates that it is a &amp;#039;&amp;#039;Part&amp;#039;&amp;#039; (brick), then it is added to the array of bricks using&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;table.insert(childList, 1, list[n])&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is a &amp;#039;&amp;#039;Model&amp;#039;&amp;#039;, &amp;#039;&amp;#039;Workspace&amp;#039;&amp;#039;, &amp;#039;&amp;#039;Tool&amp;#039;&amp;#039;, or &amp;#039;&amp;#039;Hat&amp;#039;&amp;#039;, then it is checked for bricks by calling&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;local list = obj:GetChildren()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(This sets &amp;#039;&amp;#039;list&amp;#039;&amp;#039; to an array containing every child) and using a &amp;#039;&amp;#039;for loop&amp;#039;&amp;#039; to call&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;checkObject(list[n])&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
on every child, and it is made to check for children that are added later by using&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;list[n].ChildAdded:connect(checkObject)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This works because the &amp;#039;&amp;#039;ChildAdded&amp;#039;&amp;#039; event calls function with an argument of the child that was added. This ends the checkObject function. To get all bricks included, the script calls&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;checkObject(workspace)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Put together, the above code makes this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;-- Note: This should only be run once for each object&lt;br /&gt;
function checkObject(obj)&lt;br /&gt;
	if (obj ~= hole) and (obj.className == &amp;quot;Part&amp;quot;) then&lt;br /&gt;
		if (obj.Anchored == false) then&lt;br /&gt;
			table.insert(childList, 1, obj)&lt;br /&gt;
		end&lt;br /&gt;
	elseif (obj.className == &amp;quot;Model&amp;quot;) or (obj.className == &amp;quot;Hat&amp;quot;) or (obj.className == &amp;quot;Tool&amp;quot;) or (obj == workspace) then&lt;br /&gt;
		local child = obj:GetChildren()&lt;br /&gt;
		for x = 1, #child do&lt;br /&gt;
			checkObject(child[x])&lt;br /&gt;
		end&lt;br /&gt;
		obj.ChildAdded:connect(checkObject)&lt;br /&gt;
	end&lt;br /&gt;
end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Finished Code==&lt;br /&gt;
When complete, the code will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;local hole = script.Parent&lt;br /&gt;
local childList = {}&lt;br /&gt;
&lt;br /&gt;
local massConstant = 5.8 -- Generally a good value&lt;br /&gt;
&lt;br /&gt;
local mass = 32000 * massConstant&lt;br /&gt;
&lt;br /&gt;
-- This is basically a function that finds all unanchored parts and adds them to childList.&lt;br /&gt;
-- Note: This should only be run once for each object&lt;br /&gt;
function checkObject(obj)&lt;br /&gt;
	if (obj ~= hole) and (obj.className == &amp;quot;Part&amp;quot;) then&lt;br /&gt;
		if (obj.Anchored == false) then&lt;br /&gt;
			table.insert(childList, 1, obj)&lt;br /&gt;
		end&lt;br /&gt;
	elseif (obj.className == &amp;quot;Model&amp;quot;) or (obj.className == &amp;quot;Hat&amp;quot;) or (obj.className == &amp;quot;Tool&amp;quot;) or (obj == workspace) then&lt;br /&gt;
		local child = obj:GetChildren()&lt;br /&gt;
		for x = 1, #child do&lt;br /&gt;
			checkObject(child[x])&lt;br /&gt;
		end&lt;br /&gt;
		obj.ChildAdded:connect(checkObject)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
checkObject(workspace)&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Black Hole script loaded.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
local n = 0&lt;br /&gt;
while true do&lt;br /&gt;
	if n &amp;lt; #childList then&lt;br /&gt;
		n = n + 1&lt;br /&gt;
		if n % 800 == 0 then&lt;br /&gt;
			wait()&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		n = 1&lt;br /&gt;
		wait()&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local child = childList[n]&lt;br /&gt;
	if (child ~= hole) and (child.className == &amp;quot;Part&amp;quot;) and (child.Anchored == false) then&lt;br /&gt;
		local relPos = hole.Position - child.Position&lt;br /&gt;
		local motivator = child:FindFirstChild(&amp;quot;BlackHole Influence&amp;quot;)&lt;br /&gt;
		if relPos.magnitude * 240 * massConstant &amp;lt; mass then&lt;br /&gt;
			child:BreakJoints()&lt;br /&gt;
			if (relPos.magnitude * 320 * massConstant &amp;lt; mass) and (child.Size.z + hole.Size.x &amp;gt;  relPos.magnitude * 2 - 4) then&lt;br /&gt;
				mass = mass + child:GetMass()&lt;br /&gt;
				child:Remove()&lt;br /&gt;
				table.remove(childList, n)&lt;br /&gt;
				n = n - 1 -- This is the reason I need a counter of my own design&lt;br /&gt;
			else&lt;br /&gt;
				child.CanCollide = false -- I Can assume that things won&amp;#039;t escape the black hole.&lt;br /&gt;
				if motivator == nil then&lt;br /&gt;
					motivator = Instance.new(&amp;quot;BodyPosition&amp;quot;)&lt;br /&gt;
					motivator.Parent = child&lt;br /&gt;
					motivator.Name = &amp;quot;BlackHole Influence&amp;quot;&lt;br /&gt;
				end&lt;br /&gt;
				motivator.position = hole.Position&lt;br /&gt;
				motivator.maxForce = Vector3.new(1, 1, 1) * mass * child:GetMass() / (relPos.magnitude * massConstant)&lt;br /&gt;
			end&lt;br /&gt;
		elseif motivator ~= nil then&lt;br /&gt;
			motivator:Remove()&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting Tutorials]]&lt;/div&gt;</summary>
		<author><name>PRG</name></author>
	</entry>
</feed>