Moving a part relative to sphere

It’s stuck facing one direction and not actually rotating relative to *its current location on the sphere.

1 Like

Can you try this script? I got some help from AI to correct it.

local sphere = workspace.Sphere
local part = workspace.Part

local currentPosition = part.Position
local destination = getDestination()

local sub = destination - currentPosition
local sphereRay = sphere.Size.X / 2

local totalFramesCount = 100

for i=1, totalFramesCount do
    local relativePos = (currentPosition - sphere.Position)
    local newCFrame = CFrame.lookAt((((i / totalFramesCount) * sub + currentPosition) - sphere.Position).Unit * sphereRay + relativePos, sphere.Position)
    part.CFrame = newCFrame * sphere.CFrame
    task.wait(0.015)
end

Troop is floating far away from the sphere into the night sky

1 Like

I tested this script on my PC now and it works:

local sphere = workspace.Sphere
local part = workspace.Part

local currentPosition = part.Position
local destination = getDestination()

local sub = destination - currentPosition
local sphereRay = sphere.Size.X / 2

local totalFramesCount = 100

for i=1, totalFramesCount do
    local newCFrame = CFrame.lookAt((((i / totalFramesCount) * sub + currentPosition) - sphere.Position).Unit * sphereRay + sphere.Position, sphere.Position)
    part.CFrame = newCFrame
    task.wait(0.015)
end

AI failed again

image
Getting this result still. Trying to make a RON-type game but in space

I would fire a raycast at the sphere from the cursor (using ScreenPointToRay) and use the RaycastResult CFrame+Normal properties, similar to how Bullet Holes function.

View below post for place file demonstrating method

But then it looks directly up at the cursor, no?

It is meant to just stay flat on the sphere at all times.

The normal of a hit surface is perpendicular to the surface hit. (If there were a person standing at that position, the normal would be their “up” direction)

I tried this approach earlier and it would just look side-to-side or up-and-down. Only flat when it moves within a 5 stud radius of origin of creation

Attached is a place file of the described method functioning.
SpherePlacement.rbxl (42.0 KB)

That is placing units, not moving them.

Swap out the brick cloning for a static brick.

Then that teleports it. >> chars

(READ DES) Roblox Rise Of Nations Basic Tutorial - YouTube just to be clear, unit movement is meant to look like this

What’s the result supposed to be?

Sorry, use to “move” referring to just setting the positions, phrases like “move smoothly” might convey that idea better.

Tween from PointA to PointB (using a separate vector3 variable, not the actual position), and run the interpolated results through the following:
Point_on_surface = MIDPOINT_VECTOR.Unit*SPHERE_RADIUS
In the example place provided, I used FromAxisAngle with the rotation but that seems to be buggy when crossing the Z-axis so you can mess with the rotation elements as you will. I also did not add conditions for moving 180deg (messes with rotation I believe) or a (0,0,0)/nan exemption for the .Unit

All of this is assuming a perfect sphere positioned at the origin point (0,0,0). I’m sure you’re able to figure out workarounds if these cases can’t be met.
SpherePlacement.rbxl (42.7 KB)

Here’s the changed code if you don’t want to open it:

local activeLoop = nil

function GetTweenedValue(endResult,startResult,midPoint)
	return(endResult - startResult)*midPoint + startResult
end

function MoveBrick(brick:BasePart,result:RaycastResult)
	local TWEEN_DURATION = 1.0
	local SPHERE_RADIUS = workspace.Part.Size.X/2
	local START_POS,START_ROT,START_ANGLE = brick.Position,brick.CFrame.Rotation:ToAxisAngle()
	local END_CFRAME = CFrame.new( result.Position, result.Position+result.Normal )
	local END_POS,END_ROT,END_ANGLE = END_CFRAME.Position,END_CFRAME.Rotation:ToAxisAngle()
	local EASING_STYLE,EASING_DIRECTION = Enum.EasingStyle.Sine,Enum.EasingDirection.InOut
	
	local interpolatedPosition = START_POS
	local interpolatedRotation = brick.CFrame.Rotation
	local timePassed = 0
	
	if activeLoop then -- Stops any previous tweens
		activeLoop:Disconnect()
	end
	
	activeLoop = RunService.Stepped:Connect(function(_,delta)
		timePassed += delta
		if timePassed > TWEEN_DURATION then -- Checks if goal was reached
			activeLoop:Disconnect()
			brick.CFrame = END_CFRAME
			return
		end
		local MIDPOINT = TweenService:GetValue(timePassed/TWEEN_DURATION,EASING_STYLE,EASING_DIRECTION) -- Gets 0-1 tween value
		local currentPosition = GetTweenedValue(END_POS,START_POS,MIDPOINT) -- Applys tween to position
		interpolatedPosition = currentPosition.Unit*SPHERE_RADIUS -- Gets the unit of the current position, then multiplies it by the radius to get a position on the surface of the sphere.
		
		local currentRotation,currentAngle = GetTweenedValue(END_ROT,START_ROT,MIDPOINT),GetTweenedValue(END_ANGLE,START_ANGLE,MIDPOINT)		
		local interpolatedRotation = CFrame.fromAxisAngle(currentRotation,currentAngle)
		
		brick.CFrame = CFrame.new(interpolatedPosition)*interpolatedRotation
	end)
end

I sent a youtube video with the result, did that get blocked?

Tweening will cause it to very often clip thrugh the earth.

No, this script is working for me:


gBall.rbxl (34.2 KB)

1 Like

Any way I can use tweenservice with this?

1 Like