How do I make a part parallel to the surface it touches?

I am making like blood splatters in my game and each one is simply a flat cylinder . They go in different directions meaning that they touch walls, floors , rooves ect . The problem is they will be at the wrong angle to the surface they touch like this:

How do I make it so that when it touches a wall or something it instead looks like this :

1 Like

I recently wrote a section about this in my CFrame tutorial.

1 Like

Thank you so much , nobody else was replying to me , I assumed it was because it is a difficult topic.

1 Like

Yep, CFrames are usually a difficult topic that gets little responses.

But also keep in mind that this topic has been solved before. I would google align part to surface.

This is my favorite one which I used to learn CFrames from:

3 Likes

I am still completely lost after looking at everything sent to me for over an hour .I still can’t understand how I can make this work

figure out what your plate’s surface normal is, it is probably the up vector (cframe.UpVector) just get the normal of the wall it is touching by seeing which dot product of the unit vectors (You can paste them to a table by just creating a new part and reading off the basis vectors and then getting those and reflecting them so you have 6 vectors). after that go through each vector and calculate the dot product of it to the upVector of your plate’s surface normal. after sorting through the dot products, get the highest one and call it targetVector. Now, set the cframe of the plate to be CFrame.lookAt(self.Position, self.Position + (targetVector * epsilon))

1 Like

How do you get the normal and what is a dot product?

You can set it’s Orientation to be the same Orientation of the surface that it touches.

All a CFrame is, is just Roblox lingo for an “affine matrix”. To dumb it down though it is just a way to represent a coordinate system. In an affine matrix, you represent the vector spaces orientation based on the “basis vectors”. Some parts of this matrix are those basis vectors, the ones which tell us what is positive on the y, what is positive on the x, what is positive on the z if the coordinate space was that CFrame. The normal for the plate can be calculated by just reading off the basis vectors of it, its CFrame.UpVector. The dot product is just one of the many ways to find the angle between two vectors. Moreover, the geometric definition is |a||b|cos(angleBetweenAandB). It is very cheap to calculate cause Roblox has dot product done on their backend with their vector library. Since the normal of the wall will always be a unit vector and so will the upvector we can just dumb it down to just be the dot product, no need to do inverse cosine because having it be sorted from least to greatest and getting the highest one will let it account for small precision errors. Remember that when the angle is 0 the x will be 1 on the unit circle.

2 Likes

I think I am just going to give up , none of that made any sence to me at all.

something like this

--[[
wall is a part and bloodCircle is a flattened cylinder
bloodCircle.UpPart is a tiny part that is invisible which is directly above
 the blood circle and is parented to bloodCircle.
 it is assumed that bloodCircle is already touching alignBlood like shown in your image
]]
function alignBlood(wall, bloodCircle)
 local wallNormals = {wall.CFrame.LookVector, -wall.CFrame.LookVector, 
 wall.CFrame.UpVector, -wall.CFrame.Up,
 wall.CFrame.RightVector, -wall.CFrame.RightVector}
 local alignerVector = bloodCircle.UpPart.Position - bloodCircle.Position
 local biggest = {0, Vector3.new()}
 for i=1,#wallNormals do
    local dot = wallNormals[i]:Dot(alignerVector)
    if dot > biggest[1] then
        biggest[1] = dot 
        biggest[2] = wallNormals[i]
    end
  end
  local transformedUpPart = bloodCircle.Position + biggest[2].Unit
  bloodCircle.CFrame = CFrame.lookAt(bloodCircle.Position, transformedUpPart)
end

What type of loop is that “i=1,#wallNormals do” I have only worked with for i,v in pairs loops and for 0,1,0.1 do loops

for Identifier = Start, Stop, (Step = 1) do
    -- Code
end

This, by Lua’s definition, is a numerical for loop (see first example). The one you’ve questioned is no different from the latter loop you mentioned.

FYI, Lua labels for A, B in C loops as “generic for loops”.