Trying to make a system that you can turn into a "gas"

I’m making a game where you can turn into different types of matter.
I’ve been trying to make it so you can turn into a gas.
The gas matter can go through parts that are named “GasPart”.
This system isn’t working well though.
Can somebody give me a better solution?

local UserInput = game:GetService("UserInputService")
UserInput.InputBegan:Connect(function(button)
	if button.KeyCode == Enum.KeyCode.F then
		if game.Players.LocalPlayer.Character.HumanoidRootPart.Gas.Value == false then
			local gas = Instance.new("Smoke")
			gas.Parent = game.Players.LocalPlayer.Character.HumanoidRootPart
			for i,v in pairs(game.Players.LocalPlayer.Character:GetChildren()) do
				if v:IsA("BasePart") then
					v.Transparency = 1
					if v.Name == "Head" then
						v:FindFirstChildWhichIsA("Decal").Transparency = 1
					end
				end
				if v:IsA("Accessory") then
					v.Handle.Transparency = 1
				end
				if v:IsA("BasePart") then
				v.Touched:Connect(function(brick)		
						local ray = Ray.new(brick.Position, Vector3.new(0,0,1111111111111150))

						local hit, position = workspace:FindPartOnRayWithIgnoreList(ray, {v})
						if hit.Name == "GasPart" then
							print("this jumble of a code actually works, congrats")
							v.CanCollide = false

						else
							v.CanCollide = true
							
						end
						
					end)
					end
		end
		end
		if game.Players.LocalPlayer.Character.HumanoidRootPart.Gas.Value == true then
			for i,v in pairs(game.Players.LocalPlayer.Character:GetChildren()) do
				if v:IsA("BasePart") then
					v.Transparency = 0
					if v.Name == "Head" then
						v:FindFirstChildWhichIsA("Decal").Transparency = 0
					end
					if v.Name == "HumanoidRootPart" then
						v:FindFirstChild("Smoke"):Destroy()
						v.Transparency = 1
						game.Players.LocalPlayer.Character.HumanoidRootPart.Gas.Value = false
					end
				end
				if v:IsA("Accessory") then
					v.Handle.Transparency = 0
				end
			end
		end
	end
end)
game:GetService("RunService").RenderStepped:Connect(function()
if game.Players.LocalPlayer.Character:WaitForChild("HumanoidRootPart"):FindFirstChild("Smoke") then
	game.Players.LocalPlayer.Character.HumanoidRootPart.Gas.Value = true
	end
	end)

Main code you should probably focus on:

if v:IsA("BasePart") then
				v.Touched:Connect(function(brick)		
						local ray = Ray.new(brick.Position, Vector3.new(0,0,1111111111111150))

						local hit, position = workspace:FindPartOnRayWithIgnoreList(ray, {v})
						if hit.Name == "GasPart" then
							print("this jumble of a code actually works, congrats")
							v.CanCollide = false

						else
							v.CanCollide = true
							
						end
						
					end)

Is this script in a local script? Where is it located?

Yes, this is a local script, it is in the StarterGui because I didn’t know where else to put it.

I’d use collision groups. Collision groups let you change which groups of parts can hit other groups of parts:

StarterPlayerScripts or StarterCharacterScripts are some other options.

1 Like

One thing I should note: this print("this jumble of a code actually works, congrats") doesn’t actually print, so can somebody help me with that?

You’re not doing directions right, my friend.

And I’m referring to the Ray.new(Origin, Direction) calls.

Neither are you doing your Origin right if I recall correctly.

You need to use the Player’s Character’s LookVector (where they’re facing)
And their Character’s Position for Origin.
Example:

local Player = ...
local Character = Player.Character
local HRTP = Character.HumanoidRootPart

-- This would be in your touched connection, or something.. I'm somewhat confused by your code honestly.
local HR_CF = HRTP.CFrame
local Direction = HR_CF.LookVector
local Distance = 20 -- This is how far ahead we should be casting.
Direction *= Distance

local OurRay = Ray.new(HR_CF.Position, Direction)
local Hit, HitPos = ... -- you get the idea.

Try this out if you will.

Can somebody tell me why the collision group isn’t working?

game:GetService("RunService").RenderStepped:Connect(function()
					if v:IsA("BasePart") then
				
						
							local Player = game.Players.LocalPlayer
				
							local Character = Player.Character
							local HRTP = Character.HumanoidRootPart

							-- This would be in your touched connection, or something.. I'm somewhat confused by your code honestly.
							local HR_CF = HRTP.CFrame
							local Direction = HR_CF.LookVector
							local Distance = 20 -- This is how far ahead we should be casting.
							Direction *= Distance

							local OurRay = Ray.new(HR_CF.Position, Direction)
						local Hit, HitPos = workspace:FindPartOnRayWithIgnoreList(OurRay, {v}) -- you get the idea.
						if game.ReplicatedStorage.Collision.Value == false then
							game.ReplicatedStorage.Collision.Value = true
							for i, thing in pairs(Character:GetChildren()) do
								if thing:IsA("BasePart") then
									game.ReplicatedStorage.CollisionGroup:FireServer(thing, Hit)
									end
								end
						end
						game.ReplicatedStorage.Collision.Value = true
							if Hit == nil then
							
							else
							if Hit.Name == "GasPart" then
								print("ello")
								game.ReplicatedStorage.CollisionFilter:FireServer(false)
								else
								game.ReplicatedStorage.CollisionFilter:FireServer(true)
								end
							end
			

					end
				end)
1 Like

I’d set all the gas parts to their own gas collision group in studio, then just switch the parts of the character to the gas collision group when they turn into a gas. Changing the collision group of the parts of the character can be done on the client (since the client has network ownership of the character), so that makes it a bit easier.

The reason the code above probably doesn’t work is because it is still getting parts on the ray then sending a true false value to the server, not the part too. It depends on how the server script handles that though.

Can you explain in more simpler terms? I don’t understand what you’re saying.

Create a collision group (Model tab)

Go to the collision group editor that opened when you pressed “Collision Groups”

Enter the name into the add group text box

Set the GasParts collision group to not collide with other parts in the GasParts collision group.

Set the collision groups of the GasParts to the GasPart group:

(the number is the number on the list, Default is zero and the next is one)

Then once you do that, you can change all the parts in the character to the GasParts collision group when they turn into gas. (This means those parts can’t collide with other gas parts.)

Which command do you use to transfer collision groups?

You can set the BasePart.CollisionGroupId or you can use SetPartCollisionGroup.


Screen Shot 2022-03-08 at 8.19.46 PM
Okay, so these are my scripts, but it shows up with the error “Parameter 1 must be BasePart.” or something.

You can change the collision groups of the character’s parts on the client. The collision groups of the GasParts should probably be changed in studio.

The error is because thing2 isn’t a base part. If you were to do it that way you’d need to do something like FireServer(“do”, Hit)

I’d recommend just setting the GasParts’ collision groups before hand and changing the collision groups of the character model’s parts.

oh shoot just realized i didnt fill in the thing2 thingy

1 Like