InteractionService - Create interaction prompts with ease!

Note: once proximityprompt is out of beta, I won’t be supporting this really anymore. I made this as an interaction prompt system but as it’s being worked in as an official feature there’s really not much use for this. Ill still throw the patch every now and then, but no crazy new features.

Last update: 12/03/2020

Hello everyone!

Ive decided to publish my InteractionService here on the dev forum for everyone to use. What exactly is it?

We have all probably played games with those ‘E circles’ or ‘E prompts’. This provides a simple way to create those. I created this to hopefully make the creation of these prompts quick, easy, and effective for any use.

This uses CollectionService to handle the interactable objects, so I recommend you use the Tag Editor by sweetheartichoke for the easiest experience.


Documentation
--[[
InteractionService by grif_0

	 - You dont have to give me credit, but you can if you want :)
	 - Feel free to use, edit, and modify it how you please.
	 - Just dont claim you created it / sell it.
	
	InteractionService was created to provide an easy way to create interaction prompts in games for any kinds of in game events or functions.
	
	Please let me know if anything is unclear. I think i've done a good job documenting everything, but I also already know how to use this.
	
	Enjoy! 
	
	Created 10/1/2020
	Last Updated: 10/28/2020

	Update Notes: 
		- All input types now measure distance from the player
		- Billboard changes
		- All Billboard tweens are together to make changing the billboard easier
		- Cuztomizeable RenderDistance
	
		- Fix for LocalInteractPrompt using wrong tags to find functions and data
		- Output will warn you if any properties or the event is missing
	
		- Custom tag interaction distance didnt actually work
		- Property to determine how many frames in between each update.
		- Instead of looping through every single object that can be interacted with, it will search through all objects
		  within 100 studs of the user.
		  
	
		- The position must be on screen in order to register
	
	
		- Yield function to yield the interaction
		- Documentation
		- LocalHandler now uses table.sort() to sort through all the parts

	-----================================================================================----

	Each module and folder should be placed in its designated places:
		ServerInteractPrompts - ServerScriptService
		InteractHandler - ReplicatedStorage
		InteractData - ReplicatedStorage
		LocalInteractPrompt - StarterPlayerScripts/Client
		InteractionsHandler - ServerScriptService

	You may need to change where its defined, depending where you put it.


	For the scripts to determine if the event can fire, each object and tag must fit a few requirements:

		Replication - Each object must be visible on both the server and client.
		Tag - Each object should be tagged with 'Object-Interact' and 'Object-[YourTagName]'. 
		ClassType - Objects must be an Attachment or BasePart.
		Documentation - Each tag should be specified in this module and the server Authorize module.
		Function - Inside the server InteractEvents module, the original function must create a coroutine 
				   for the function and return true or false whether the function can happen, so you can 
				   create your own rules for each function. It must return true if it executed, and false 
				   if it didnt.
				   
		Then, all you have to do is tag the object and you should be set.

	-----================================================================================----


	Properties

	UpdateAmount: The amount of times a second the LocalInteractPrompt will update.
	selectedPart: The currently selected object.
	selectedInteraction: The currently selected interaction.
	isPressing: Determines whether the user is holding down the selected interact key.
	canClose: Determines whether the prompt can be closed.
	YieldScript: Determines if the script is Yielding. This should not be changed to yield the script.
	SelectedParts: A table of parts the LocalInteractPrompt uses. You can manually add parts to this, but be aware it
				   updates every 15ish seconds or if the user moves a great distance from the last position it was updated.
				   its important you DO NOT make the interact distance of any tag greater than the RenderDistance, or it will not register.
	RenderDistance: All objects outside of this distance wont be rendered.
	
	ObjectInteractDistance - The default interaction distance used if one is not specified in the tag's table. do NOT make it greater than the RenderDistance.
	InteractData - TagDescriptions: A module containing all of the tag and the properties determoning how it works. A new table should be made for each tag, and copied into the server Authorize module.
		Text - The text the billboard should show.
		Keybinds = {
			Controller = the controller key that needs to be activated.
			Keyboard = the keyboard key that needs to be actiated.
			Mobile gets a ContextActionService prompt.
		};
		Tag - The tag name again.
		Time - The time required for the prompt to activate. 0 makes it instant.
		Distance - The minimum distance the user needs to be from the object. If nil, it will use ObjectInteractDistance. Do NOT make it greater than the RenderDistance, or it will not register.


	Functions

	Yield(bool shouldYield): When the script is yielded, the function will not update and cannot be called.
		shouldYield - a bool determining whether to yield the functions or not.

	CancelSessioin(): Cancels the current prompt session, but does not close it.

	CloseSession(): Cancels the current prompt, but also closes the billboard and resets completely.

	CreateSession(): Creates a new interact session which will run if it has not been yielded or updated.

	UpdateSession(instance SelectedPart, string SelectedInteraction): Updates the billboard to the selected 
																	  part and cancels the current session.
		SelectedPart - the object which should prompt the new event on. Supports Attachments and BaseParts.
		SelectedInteraction - the string name of the selected interaction. If the part is not tagged with the SelectedInteraction on the server, it will error.

	UpdateSelectedParts(vector3 PlayerPos): Updates the table of objects which the LocalInteractPrompt uses when finding objects, to prevent looping through every single object.
											Automatically updates after 10 seconds, or when the player moves away from the last position a decent amount.
		PlayerPos - a position in which it checks all parts by. I reccomend you use the HumanoidRootPart's position.
		
		
	==================================================
	
	
	Thanks for using InteractionService! Heres a quick guide to get started:
	
	This uses CollectionService in order to function, so i reccomend you use the Tag Editor by sweetheartichoke. Make sure you download the correct plugin! 
	The server must have the tags, meaning you cannot create the tags on an object on the client, or it will not work. Same with the objects, they must be created on the server.
	Objects must have a unique name / descendant train, meaning you cannot have two parts named 'Part' with one tagged. Each part must have a unique name and unique path to find the part.
	
	All interactable tags must be tagged with 'Object-Interact', aswell as the tag for your function: 'Object-YOURTAGNAME'. In order to hide an object from players, tagging it with 'Object-HideObject' will hide the object from all other players.
	
	Now that you have added the tags to the object, you must define the tag. Inside of the 'InteractData' module, there is a table 'TagDescriptions. Create a new table just like the following:
	
	["Object-YOURTAGNAME"] = {
		Text = "Tween Part"; --// Text you want the billboardgui to say.
		Keybinds = { --// Keybinds to be pressed. Mobile gets a contextactionservice button.
			Controller = Enum.KeyCode.ButtonY;
			Keyboard = Enum.KeyCode.E;
			MOBILE - A ContextInteractionService button is created Please let me know what i can do to improve it.
		};
		Tag = "Object-YOURTAGNAME"; --// The tag again
		Time = 1; --// Time it takes to fire 
		Distance = 10; --// custom interact distance per-tag. If nil, it will use the default.
	};
	
	This defines how far you must be, how long it takes, the keybinds, and the text shown. 
	
	Object Requirements:
	 - Must be within your designated distance
	 - Must be on screen
	 - Must have line of sight with your cameras focus
	 - Must have a unique path to find locate the object within the game
	 - Must be a BasePart / Attachment
	 - Must  be within the RenderDistance of the user
	 - Object + Tag must be created on the server / seen by the server
	 - Must have the respected tag + 'Object-Interact' and cannot be hidden with 'Object-HideObject'
	 
	 Now, to create the event that will be fired. Inside of the 'InteractEvents' module, you can define the function like the following:
	 
		module["Object-YOURTAGNAME"] = function(object, Player) --// Function name must be the tag name. The function also gets the object and player.
			local function Thread()
				table.insert(module.IsInAction, #module.IsInAction + 1,object) --// Add it to IsInAction, so it cant be fired when working.
			
				table.remove(module.IsInAction, table.find(module.IsInAction, object)) --// Make sure to remove it from it.
			end
			
			local Coroutine = coroutine.create(Thread)
			coroutine.resume(Coroutine) --// Coroutine it so the event can play and return true for fast feedback
			return true --// Return true to give the user feedback that the event happened, return false/nil if the event wont occur.
		end
	 
	 If you want to put custom rules per function, you can do so. Make sure to return true if the function was executed, and nil/false if it wasnt, or it will tell the client that it failed to execute.
	 
	 There are 4 different kinds of input types supported:
	 
		0 - Lerped position between Camera from 2 and 1 at .8
		1 - Mouse.Hit.Position
		2 - Wherever the camera is looking at or if its looking at nothing, then its focus point - (cameraRay = workspace:Raycast(camera.CFrame.Position, camera.CFrame.LookVector * RenderDistance, rayParams).Position or Camera.Focus.Position)
		3 - HumanoidRootPart.Position
	 
	 By default, this is 3. You can change it by changing the NumberValue inside of LocalInteractPrompt
	 
	 I have created an example 'Tween Part' event as a guide if you are unclear.
	 
	 
	 PLEASE let me know if anything is unclear! Feel free to message me.
]]
Updates

Update Notes:

	- Fixed issue with players dying
	- Object names no longer need to be unique

	- All input types now measure distance from the player
	- Billboard changes
	- All Billboard tweens are together to make changing the billboard easier
	- Cuztomizeable RenderDistance

	- Fixed an error with trying to retrieve data with the Object-Interact tag, and Object-HideObject tag.
	- Feedback if any events, or properties are missing.

	- Custom tag interaction distance didnt actually work
	- Property to determine how many frames in between each update.
	- Instead of looping through every single object that can be interacted with, it will search through all objects
	  within 100 studs of the user.

	- The position must be on screen in order to register

	- Yield function to yield the interaction
	- Documentation
	- LocalHandler now uses table.sort() to sort through all the parts

This creates a Mobile ContextInteractionService button which may be a bit glitchy, so please let me know what i can do to improve it.

Im hoping this can allow users to easily make more interactable functions in their games without having to go out and create their own system, so they can just add a few tags, define the tag, and create the function and be on their day.

Please let me know if the documentation is unclear! Ill happily answer any questions you have here and update the documentation accordingly.

Heres a link to the model:

Enjoy!

23 Likes

The system works wonderfully, very well documented. Keep up the good work!

1 Like

Works wonderfully, thanks! I know that this is very hard to make and making it open source is amazingly helpful to people who can’t quite put the time in to make it themselves or can not figure it out for themselves.

EDIT: When you walk away from a part that has the GUI on it, the GUI does not close until you have walked far enough away for it to not render anymore.

Thanks for you feedback. Does this happen every time, or is it every now and then? I’ve never seen this happen before. Do any errors show in the output, and do you mind sharing the table values in the InteractData module with me so i can see if its a per value thing?

1 Like

I probably won’t update this anymore due to roblox releasing ProximityPrompt, I reccomend you check that out.

2 Likes

This happens every time.

No, no errors show in the output.

Sure thing, I have only set up one tag so far. The other one is the TweenPart example you have provided.

["Object-PDUniforms"] = {
		Text = "Get uniform"; --// Text you want the billboardgui to say.
		Keybinds = { --// Keybinds to be pressed. Mobile gets a contextactionservice button.
			Controller = Enum.KeyCode.ButtonY;
			Keyboard = Enum.KeyCode.E;
		};
		Tag = "Object-PDUniforms"; --// The tag again
		Time = 4; --// Time it takes to fire 
		Distance = 5; --// custom interact distance per-tag. If nil, it will use the default.
	};

Another small detail that may be important is that my InputType is 1, due to having problems where the others will not let it fire the event properly.

1 Like

Thanks for also telling me which input type, Because the first type only uses your mouse hit and doesn’t take your player position into account at all. I think ill have a fix for this out tonight along with a few others things. Thanks for getting me the info and telling me about it.

This shouldn’t matter as even if I move my mouse far out of the distance for the Interaction, it still persists.

I have created another and the same error is occurring.

I pushed a few fixes, can you tell me if the issue still happens for you? I wasnt able to replicate it after fixing what I found.

Ill have to give this a try!

yesineed30chars

Aw, a new feature for prompt just arrived in Roblox Studio Beta. I think you should update it for Proximity Prompt, to help newbies to deal with that new feature.
However, this is a good resource, thank you!

Yeah, its great Proximity Prompt released as its probably easier to use, just bad timing and i guess a big coincidence that it released almost right after I posted this. Im not sure how i would modify this to use Proximity Prompt since there’s already events you can directly fire from for Proximity Prompt, so this whole system isn’t really important if you use that.

I guess itll just serve as an alternative.

2 Likes

This is an excellent resource that does what it says once you understand the scripts that need to be edited in order to create your own interaction prompts. I have been able to create a press E to sit with real ease.

However, yeah I have been receiving the same game-breaking bugs as @purn8r and I noticed a problem after some further inspecting in the below screenshot:

Screenshot 2020-11-14 at 12.05.39 AM

Yeah every time the character resets the default InteractBillboard isn’t destroyed and is locally cloned on the clients workspace which can cause the following glitch:

And more like how the prompt won’t disappear once you press E to sit down which is how it worked previously. Moreover, perhaps this is a memory leak in itself as well which the Instances not being destroyed client-sided.

Anyhow, the project has been really insightful and should serve as a suitable alternative until Proximity Prompt comes out of Beta.

For now I guess I’ll focus on other aspects of my project and see which one needs to be worked on first then reevaluate the usage of Proximity Prompt based on the release, customizability, and other stuff


What I’m doing wrong? Wanted to test the example, but even it doesn’t work…

Since you took the scripts and remote out of the folders, make sure you updated the locations of them in the scripts or it could error. Was any output coming from that?

It was a bit unclear what should I do with these folders. The thing is, at firsts I didn’t touch them, but they still didn’t work, so I removed them, but this did not help too. Sorry for disturbing you, now I got it, thanks! This is so useful right now, because proximity prompt will release only in 2021… I’m really grateful to you for making this. Surely will credit you!

I have been receiving the same game-breaking bugs… every time the character resets the default InteractBillboard isn’t destroyed and is locally cloned on the clients workspace.

Any way to fix this? Got same problem, already made all my functional on this service, and now it’s breaks like this…

Hmm, the prompts break when the users die, like do the reset or freeze?

That’s instererting the billboards duplicate, I think I’ll release one more patch to hopefully fix these issues soon.

It just doesn’t check if billboard was are already created, and creates new one. You just need to add if statement, so it doesn’t creates new one.

Will this be visible to everyone in the game, or can it only be used in the studio? :slight_smile: