https://www.roblox.com/games/652948132/Kingdom-Chaos-Grand-Opening In this game there's a mechanic allowing for a ring to appear directly below where ever the player stands, floating on the surface of the part beneath said player. How has he done it?
The X and Z are easy considering it follows the character, but what about the Y? A use of raycasting can get what ever is below but how did he get the surface? For instance, a part may be rotated causing so that the "top surface" isn't what you would expect anymore, infact the "top surface" may be pointing downwards depending on how it's rotated.
(TL;DR How would you make get the Y axis of the part's surface, despite it's rotation?)<<
I actually need something like this for a health bar, doing the bar is easy but the placement confuses me as it is flat upon the ground, and my mind is boggled on how it still runs so quickly in the Kingdom Chaos game.
Help is extremely appreciated.
Gyazo #1: https://gyazo.com/1775b21f95329791a2d4a51e01ce9e48
Gyazo #2: https://gyazo.com/9261434b10f27b3faf20797ad90f59f3
local Player = game.Players.LocalPlayer repeat wait() until Player.Character~=nil local Character = Player.Character local Ring = game.ReplicatedStorage.ItsTheTag:clone() Ring.Parent = Character Ring.Anchored = true
local IGHM = {} local Back = Platform.CFrame * CFrame.new(0, 0, (Platform.Size.Z/2)) * CFrame.Angles(3.14, 0, 0).p IGHM[1] = Back local Front = Platform.CFrame * CFrame.new(0, 0, -(Platform.Size.Z/2)) * CFrame.Angles(3.14, 0, 0).p IGHM[2] = Front local Side1 = Platform.CFrame * CFrame.new(-(Platform.Size.X/2), 0, 0) * CFrame.Angles(3.14, 0, 0).p IGaveHerSheGotMad[3] = Side1 local Side2 = Platform.CFrame * CFrame.new(-(Platform.Size.X/2), 0, 0) * CFrame.Angles(3.14, 0, 0).p IGHM[4] = Side2 local Top = Platform.CFrame * CFrame.new(0, (Platform.Size.Y/2), 0) * CFrame.Angles(3.14, 0, 0).p IGHM[5] = Top local Bottom = Platform.CFrame * CFrame.new(0, -(Platform.Size.Y/2), 0) * CFrame.Angles(3.14, 0, 0).p
for i = 1, 6 do --[[Here I would try to see which surface is closest to the player and choose that to sort out what the Y axis would be with several if statements, for instance: "if Back.Y>IGaveHerSheGotMad[i].Y then" "elseif Front.Y>IGaveHerSheGotMad[i].Y then" etc, but then I realized something, if it's a very small part then that would mess it up if you're standing somewhat to the side, plus the game im drawing the inspiration from doesen't have that type of issue, so surely i'm going about this wrong ]] end
game:GetService('RunService').RenderStepped:connect(function() Update()
The main goal was to basically fill in the Y, but then I thought to myself, there has to be a quicker, less laggier way to do this right? What is it they did that i'm not doing?<<
Ring.CFrame = CFrame.new(Character.HumanoidRootPart.Position.X, ???, Character.HumanoidRootPart.Position.Z)
You can use Raycasting and FindPartOnRayWithIgnoreList to be able to get the position easily.
There are many ways to do this, one way is to cast a ray from the HumanoidRootPart of the character in the negative Y direction.
We are going to use the first two parameters of the FindPartOnRayWithIgnoreList, which return the part that has intersected the ray, and the position it intersects it at, respectively.
So it would look something like this:
repeat wait() until game.Players.LocalPlayer.Character local player = game.Players.LocalPlayer local character = player.Character local runService = game:GetService("RunService") local ignoreList = {} function fillIgnoreList(character) for i, v in pairs(character:GetChildren()) do if v.Parent:FindFirstChild("Humanoid") then table.insert(ignoreList, v) -- ignore all parts that are under a model with a humanoid end end end local trackingPart = Instance.new("Part") -- the tracking part that will be under the character trackingPart.CanCollide = false trackingPart.Anchored = true trackingPart.Parent = character fillIgnoreList(character) -- fill the ignore list with all the parts that have to be ignored if they intersect the ray runService.RenderStepped:connect(function() -- update every 1/60 of a second local ray = Ray.new(character.HumanoidRootPart.Position, Vector3.new(0, -1, 0) * 100) local hit, position = workspace:FindPartOnRayWithIgnoreList(ray, ignoreList) trackingPart.CFrame = CFrame.new(position) end)
Hope it helped!