Confusion Regarding CFrame (SetPrimaryPartCFrame) Position/Rotation

  1. What do you want to achieve?
    I want a model that is cloned from server storage to be facing the player when a tool is clicked by the player in a position slightly above where the mouse is.
  2. What is the issue?
    I’m very confused as to how to position the model (gargantaModel.Base), based on which direction the player using the tool to spawn it is facing, and how to take the variable for where the mouse is positioned (mousePosition) and add a vector 3 or some other type of value to increase the height of where the model spawns in.
  3. What solutions have you tried so far?
    I’ve tried setting the position with model:MoveTo, however, that does not get the exact position of the mouse if another part is in the way. I’ve tried setting the parts individually to the orientation of the player torso, but that fully ruins the positioning of the model, and I’ve tried setting the model equal to a CFrame value as you would with any other part, but as this is a model, to my knowledge I need to use Model:SetPrimaryPartCFrame. And lastly, as the code below will demonstrate, I’ve tried changing the Vector3 value from the variable torsoOrientation into a radion value, as I have read that radion values are needed for CFrame rotations.

For reference, I am using a Remote Event named “gargantaEvent” in order to deliver information from client to server.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("gargantaEvent")
local Tool = script.Parent
local player = game.Players.LocalPlayer
repeat wait() until player.Character
local character = player.Character
local mouse = player:GetMouse()

Tool.Activated:Connect(function()
	print("Click Detected")
	local mousePosition = mouse.Hit.p
	local torsoOrientation = character.Torso.Orientation
	remoteEvent:FireServer(mousePosition, torsoOrientation)
	print (mousePosition, "mouse position")
	print (character)
	print (torsoOrientation, "torso position")
end)

Local Script Above

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("gargantaEvent")

local function onRemoteEvent(player, mousePosition, torsoOrientation)
	print "remote event detected on server"
	local gargantaModelClone = game.ServerStorage.gargantaModel:Clone()
	gargantaModelClone.Parent = game.Workspace
	local xValue = torsoOrientation.X
	local yValue = torsoOrientation.Y
	local zValue = torsoOrientation.Z
	local radTorsoOrientationX = math.rad(xValue)
	local radTorsoOrientationY = math.rad(yValue)
	local radTorsoOrientationZ = math.rad(zValue)
	gargantaModelClone.base:SetPrimaryPartCFrame(CFrame.new(mousePosition) * CFrame.Angles(radTorsoOrientationX,radTorsoOrientationY,radTorsoOrientationZ))
	gargantaModelClone.Sound.Playing = true
	print (radTorsoOrientationX,radTorsoOrientationY,radTorsoOrientationZ, "rad torso orientation")
end

remoteEvent.OnServerEvent:Connect(onRemoteEvent)

Server Script Above

Currently, as seen above, the model is spawning in at a very strange place due to what I assume to be the wacky CFrame and position values.


Above is a picture of the model in question.

image

In the explorer, the model itself is divided primarily into the box, and the floor below it. The floor is present so as to work with the transparency script also shown above. My goal is to only rotate the model labeled base, and not the part called “floor_lower”, while also positioning the model named “gartanaModel” together in one place.

2 Likes

For cases like this, it can be really helpful to dissect a tool or free model that you know does what you want. Maybe a crossbow that orients the bolt in the direction the crossbow is pointing?
Here’s the solution you are probably looking for though.
CFrame.new is overloaded quite a bit, meaning it functions differently with a different number of parameters. CFrame.new actually has six overloads, more than anything on Roblox AFAIK. Take a look at the page for CFrames, even if you don’t understand it all.
One of the most powerful and beginner-friendly overloads is CFrame.new(V3_Pos, V3_LookAt) where a new CFrame is created at V3_Pos, facing V3_LookAt.

So in this case, re-write your function to work something like this.

local function onRemoteEvent(player, mousePosition, torsoPosition)
    ... clone and stuff ...
    gargantaModelClone.base:SetPrimaryPartCFrame(CFrame.new(mousePosition, torsoPosition))
end

By the way, I love the amount of info you included in your post.

3 Likes