Hi! So I'm working on overhauling the battle-gameplay of something I've been working on, and to put it short, the player will, from time to time, have free movement of 3 pre-defined "zones." An "A-Zone," "B-Zone," and you can guess what the third zone is called.
I've chalked up a couple ideas, one that uses Humanoid:MoveToPart, others that use BodyVelocity, others that use an invisible part pushing them / stopping them... and I've tried using the BodyVelocity, because it allows for me to easily adjust the speed, direction, and also doesn't include these invisible parts all over. It's simple and efficient.
Anywho, I've been working on a segment of script that is activated via function when the command-key for moving from zones is activated. It's using a simple unanchored part with the same dimensions as the players legs (minus height) so I can figure out how to center it perfectly in that zone. Zones will be visible, so that does need to be a thing. The script activates the body velocity, and then stops it at the perfect time.
My first idea of stopping the body velocity at the right time was a simple wait(). I'd activate it, and then trial-and-error through all the wait times until I got the one that provided me with the perfect centered position.
Keep in mind, the BodyVelocity is set to (0, 0, 70) when they move from zones. This way it's quick and fast-paced, necessary for some fights and the enemy's attacks.
So, the code is simple for this:
script.Parent.BodyVelocity.Velocity = Vector3.new(0, 0, 70) wait(n) script.Parent.BodyVelocity.Velocity = Vector3.new(0, 0, 0)
Then I tested this script. After some testing, I realized that even if I had the wait times the same between both runs (runs so I could just see it in action without having to load my player in first to save time), the part would stop at different points. I looked it up and read that it's possible that wait() commands have small variations in their delays when ran multiple times. Since it was a high speed part and I needed precision, this was not ideal. The delay variation was not the best since it moved fast, so any small variation = very noticeable change in end position.
My next idea was stopping it just as it touched the part.
script.Parent.BodyVelocity.Velocity = Vector3.new(0, 0, 70) script.Parent.Touched:Connect(function(touch) if touch == game.Workspace.ZoneATarget then script.Parent.BodyVelocity.Velocity = Vector3.new(0, 0, 0) end end)
Also didn't work. The part was stopping after the initial touch (roughly 0.75 studs.) I tried adjusting the part size but it still stopped at the same point somehow.
So, what do I do?
Roblox has a great service built in to do just this! It's called the TweenService
Tweenservice can be used to smoothly transition between any part state like color, opacity, position or anything else.
To use it, you need to create a Tween, tell it what to do, and finally play it. For example:
local tweenService = game:GetService("TweenService") local partToTween = script.Parent local finalCframe = CFrame.new(Vector3.new(0,0,0)) --Change to the CFrame of your final position local tweenInfo = TweenInfo.new(3, Enum.EasingStyle.Sine) --Create the tween. The last argument is a list of final values, which can be basically anything. --For example, to tween color it would be {Color = Color3.new(1,0,0)} local tween = tweenService:Create(partToTween, tweenInfo, {CFrame = finalCframe}) tween:Play() --Finally, Play it!
This will smoothly move the parent part to the new position. Here is where you can find more information on Tweens and TweenInfo:
https://developer.roblox.com/en-us/api-reference/datatype/TweenInfo
https://developer.roblox.com/en-us/api-reference/class/TweenService
https://developer.roblox.com/en-us/api-reference/class/Tween
~~~~~~~~~~~~EDIT:~~~~~~~~~~~~~~~~~~~
It came to my attention that the above doesn't work properly (Thanks for the update post!). After testing this myself, I realized that it's necessary to anchor the character's PrimaryPart before playing the tween! Here's an example of how to move the default Roblox character:
local ts = game:GetService("TweenService") local plrs = game:GetService("Players") wait(2) local player = plrs.<YOUR PLR HERE> local tweenInfo = TweenInfo.new(2) --2 sec local t = ts:Create(player.Character.PrimaryPart, tweenInfo, {CFrame = CFrame.new(0,50,50)}) player.Character.PrimaryPart.Anchored = true --Anchor the player's rootpart so physics doesn't mess things up. t:Play() t.Completed:Connect(function() player.Character.PrimaryPart.Anchored = false end) --After the movement is completed, unanchor the player to resume normal play
I have verified this to work.
update here
tweening the player is not something you can or should do. with attempts to weld and weldconstraint the player, nothing worked and obviously the game did not like me doing that. either the player would become disfigured from the weldconstraints with body parts oddly rotated and / or disconnected completely, you would die without welding, and with welding, only the camera (aka humanoid root part) managed to freely move.
body velocity still didn't work. my last ditch effort is to teleport the player and then at the same time load an animation (which starts at the players prev position) onto the player that smoothly moves them over instead. testing that in my debug centre atm, will keep posted if this solves the issue.
but yea tl;dr don't tween the player
edit!:
nice to know that the animations weren't working out either. the player would transition to the animations start position before it ever played the animation. when I tried to make it so the animation tweened to the end position and then stop the animation and teleport the player to the end position right after it stopped, not only did the player still transition back to the previous starting point, but the camera stayed still in the previous position, and didn't move with the player. big no no.
I've checked whenallthepigsfly's updated answer. anchored the humanoidrootpart and then tweened the player. the only noticeable thing is that the player moves up just slightly when the tween happens, presumably from the hrp anchoring. however, that actually works in my favour because the player will have an air-dodge style animation loaded (aka the player flying through the air whilst still facing forward. if that doesn't describe it, the animation will be in the same vain as what would happen if you jumped and press "e" in https://www.roblox.com/games/147848991/Be-A-Parkour-Ninja.)
no issues have risen from this final tweening solution. if any do, I'll search 4 pages of google before posting here again. after 2 days, I can finally push my game back on the tracks and keep the progress going!