How to spawn multiple parts around another part?

  1. What do you want to achieve? I’m trying to make a part spawn where the player clicks and shortly after, 3 more parts around the part previously spawned.

  2. What is the issue? While i managed to make the parts spawn in a circular path, for some reason the direction is wrong.
    image
    image
    As you can see from the pics the blue parts are around the purple part, however they spawn on the side. I’m trying to make them spawn vertically, facing the bottom of the purple part, like this (i manually changed the position):
    image

  3. What solutions have you tried so far? I tried editing the pivot property, play around with the CFrame but nothing seems to work.

Here is the code:

local Players = game:GetService("Players")
local Shard_Model = game:GetService("ReplicatedStorage"):WaitForChild("Shard")
local Rune_Model = game:GetService("ReplicatedStorage"):WaitForChild("RuneShard")
local Remote = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvent")
local TS = game:GetService("TweenService")
local DS = game:GetService("Debris")

local function renderShard(Shard)
	local InfoTween = TweenInfo.new(0.15,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,false,0)
	local goal = {}
	goal.Size = Shard.Size + Vector3.new(0.15, 0.15, 7)
	local spawnShard = TS:Create(Shard,InfoTween,goal)
	
	return spawnShard
end


local shards = {}
local numberOfShards = 3
local skillRadius = 10

local function getXAndZPositions(angle,radius)
	local x = math.cos(angle) * radius
	local z = math.sin(angle) * radius
	return x, z
end

local function chargedAttack(player,char,mouse)
	
	local HRP = char:FindFirstChild("HumanoidRootPart")
	
	local RuneShard = Rune_Model:Clone()
	local RuneTween = renderShard(RuneShard); RuneShard.Color = Color3.fromRGB(135, 14, 255)
	RuneShard.CFrame = CFrame.new(mouse.Position) * CFrame.new(0,10,0)
	print(RuneShard:GetPivot())
	RuneShard:PivotTo(CFrame.lookAt(RuneShard.Position,mouse.Position))
	RuneShard.Anchored = true
	RuneShard.CanCollide = true
	RuneShard.Parent = workspace
	RuneTween:Play()
	
		local fullCircle = 2 * math.pi

		for i = 1, numberOfShards do
			table.insert(shards, Shard_Model:Clone())
		end

		for i, part in pairs(shards) do
			part.Anchored = true
			part.CanCollide = true
			part.Parent = workspace
		end


		for i, part in pairs(shards) do
			local angle = i * (fullCircle / #shards)
			local x, z = getXAndZPositions(angle,skillRadius)

		local position = (RuneShard.CFrame * CFrame.new(x, 5, z)).p
		local lookAt = RuneShard.Position--HRP.Position


			local newCFrame = CFrame.new(position,lookAt)
			part.CFrame = newCFrame
		
			local tween = renderShard(part)
			tween:Play()
	
		end
end

If something isn’t clear, please let me know and I’ll try to explain better!

1 Like

In short, you wish to rotate them differently?
Maybe a screenshot of what you’re trying to achieve, exept build in studio manually (instead of via a script) will help.

Yep, as I explained in the post, I’m trying to make the blue parts spawn around the purple part
vertically. while also being oriented towards the bottom of the purple part.

Not sure what you mean here? Perhaps like this? image

Multiplying the part’s CFrame by CFrame.Angles(x,y,z) (uses radians, 2pi = 360, pi = 180, .5pi = 90, etc.)
And playing around with those results might solve it.

Also, what i mean was like a crude mockup. Not the end result of what the script gives, but what you want by the end, and that built by hand.

You mean the purple part’s CFrame or the blue ones?
I tried doing as you said on the blue parts by adding this:

local newCFrame = CFrame.new(position,lookAt)
part.CFrame = newCFrame * CFrame.Angles(math.rad(45),math.rad(90),math.rad(45)) -- I tried different values

Unfortunately all it does is rotating each individual part in their place instead of rotating them around the purple part :weary:
image

The screenshot i put in the previous post is exactly what I want by the end indeed? Sorry, English isn’t my first language so I might be missing something. :sweat_smile:

Sorry to bump, but if anyone else has any idea please let me know. :tired_face:

You can move these parts to that blue part, then += their position a lil , and radians may help

i think i see what you’re trying to tell us.
First of all, what is movement in video games?
Movement doesn’t exist in video games. It’s all (just like the rest of a game) smoke and mirrors.
It’s just setting the continually setting the position of something at a high frequency to make something seem smooth to the human eye.

How can you get stuff to move smoothly in roblox then?
Tweening, which doesn’t use physics is usually the go to option.
Using roblox’s physics, it can be unstable, but will make stuff interactable.
Using Runservice:BindToRenderStepped(), This will run on a client every time a new frame gets rendered, thus binding it to 60 fps and giving off the illusion of smooth movement. It also return the DeltaTime. (time between each frame. should be around 1/60th of a second)
Do beware that this function can only be run on the client. You might wish to look at some way to tween it if you need it to be replicated to other clients.

So the question should be: how can i continually position stuff around another object?

First, to get a position around an object, you (usually, i’m sure there’s some unholy way to do something else,) have to use the sine and cosine to get a y and x position between 1 and -1 on a given angle in radians. You’ve already done that in the function “getXAndZPositions”.

Then you need something that runs at 60fps, is easily controllable, but isn’t linear. Well, that excludes roblox’s physics, because it’s too linear and uncontrollable.
It also excludes tweening, because it’s too linear (might be possible to still use tweens though, idk).
That leaves you with Runservice:BindToRenderStep()

Then you’ll have to keep track of time yourselve. just a simple local Time = 0 and Time += DeltaTime within the loop will do.
What can you do with the time?
Well, because you know the angle of each part to the middle part, you can simply take said angle, add time on top of it, move the parts and the parts will have rotated by a DeltaTime angle around the middle.

And that’s how you get stuff to “Move” around a point.

1 Like

It could look something like this:

local Time = 0
Runservice:BindToRenderStep("MoveParts",1,function(DeltaTime)
Time += DeltaTime
local position = getXAndZPositions(angle+Time,radius)
part.CFrame = CFrame.new(position)
end)
1 Like

Which axis is the “long” one? X, Y, or Z?

Oh, I see the issue.

CFrame.lookAt (or CFrame.new(pos, target)) makes the Z axis point towards the target.

So when you do

local position = (RuneShard.CFrame * CFrame.new(x, 5, z)).p

You’re basing that off of a 90-degree rotated RuneShard (who’s front face is pointing down).

The simplest fix is to ignore rotations, e.g. by just using positions directly:

local position = RuneShard.Position + Vector3.new(x, 5, z)
1 Like