Player Auto-Rotate Speed

Hey guys, I’m currently making a game and I was just curious about how I could change the speed of how fast a player turns for example, I don’t want to be able to do this: https://gyazo.com/83ba3945dc06555cebf0bd114955e88b

You’re able to do this my spamming WASD, is there anyway to change how fast your character changes the way it’s facing? This is a player character as extra info.

This is a pivotal gameplay mechanic and any info would help. :smile:

4 Likes

Are you still using the default player controller and humanoid? You can replace the MasterControl script with your own custom one. In there you will find on line 83 a variable called ‘moveFunc’. By default it is set to LocalPlayer.Move(), but using your own function you could first make it turn the desired direction before moving, or just have the character move forward while turning. You can make it turn anyway you like, but beware if you are using a humanoid! It likes to mess with physics and forces, so you will have a hard time manipulating it. I’d recommend removing the humanoid.

I really like how all the player control and Roblox GUI were done in Lua, and even more so that the player control scripts are easily editable. I would like to see more of Roblox’s functionality switched over to Lua or is some way editable/extendable by developers.

The only problem with removing the Humanoid is for animations. But, I’ll check for this and get back to you.

Yeah, when I remove the Humanoid I use an AnimationController for animations instead.

Does that still allow animation instances to be loaded and played as if off a humanoid?

Yup, as seen here.

Another good way to fix this is to use linear or limited linear interpolation from the current angle to the intended angle.
linear interpolation:

local lerp = function(a,b,c) return a+(b-a)*c end
--lerp current angle to target move angle

limited linear interpolation:

local llerp = function(a,b,c,l) return a+clamp((b-a)*c,-l,l) end
--lerp current angle to target move angle, has a maximum rotational speed per call

Angles are based off of atan2(moveDir.Z,moveDir.X)
Move direction would be based on the cosine and sine of the directional angle.
You would call these every frame with the specified rate changing how quick and how smooth the transition is and the limit changing the fastest it can move.

2 Likes

So, I wrote my own script for this but it isn’t working 100%, more like 85%. I don’t think there is access to whatever controls Auto-rotate in humanoid, I don’t know if you’d be interested in helping me further, but this is a core part of gameplay, I can show you the script I’ve made as well, if you’d be willing.

I finally was able to make it. I don’t mind leaking my own code. You can see it here and try it out here.

https://pastebin.com/kcqMxrkb

2 Likes

Would you mind explaining where exactly player.CamRot.Value is coming from, and what the value of Char.DeltaGradient.Value is?

Sure. Replicating turret movement between clients was the best way to ensure smooth traverse viewing for everyone. Basically, player.CamRot.Value is the rotation in degrees of the player’s camera on the Y Axis, it then uses that value to show turret rotation of all players including yourself to the client. Char.DeltaGradient.Value is something I’m using for WalkSpeed. Since I wanted realistic turning speeds, I subtract delta multiplied by the delta gradient from the base WalkSpeed, so if you walk in the direction you’re facing, your WalkSpeed will be at 100% but as you turn and walk, your WalkSpeed will get slower until you face your target direction.

3 Likes

You’re a saint for sharing. Do you mind if I post a pastebin here with your turning code adapted to be more generic?

1 Like

Feel free. Glad I could help. Attached is the full script for everything related to the rotation.
https://pastebin.com/PQPE8VFU

Another thing you can do if you want to fine tune your animation to the turning WalkSpeed is add this to the RenderStepped.

AnimTrack:AdjustSpeed(Char.Humanoid.WalkSpeed) --play with this number 'til it looks good.

This will adjust the animation speed to whatever the WalkSpeed currently is, if you want to fine tune but it looks good.

Adjust weight should also be used to make the character transition between different animations and as well as to increase or reduce stepping distance.

Fair. For this instance however the main concern was WalkSpeed as your character turns.

This is a standalone LocalScript to be placed inside the character.
While creating a tween on RenderStepped doesn’t sit very well with me, I don’t have any more time right now to fiddle with this. Lots to optimize here.

@Trioxide helped me compress that giant block of angle logic. This is much nicer and will work with controller input, because iirc you won’t get whole numbers in the ControlScript when you’re using an analog stick (because analog).

Edit: Turns out I can cut out a lot of unnecessary tweens. Also there was an issue with the character continuing to turn after you’ve already released input.

local TS = game:GetService("TweenService")
local Players = game:GetService("Players")
local UIS = game:GetService("UserInputService")
local player = Players.LocalPlayer
local control = require(player.PlayerScripts.ControlScript.MasterControl)

local char = player.Character
local root = char:WaitForChild("HumanoidRootPart")
local humanoid = player.Character:WaitForChild("Humanoid")
local camera = workspace.CurrentCamera

local tweenTime
local traverseTime
local goalRad
local calc
local rotTween

local DELTA_GRADIENT = 4
local BASE_TWEEN_TIME = .2
local movementSpeed = humanoid.WalkSpeed

-- AutoRotate must be disabled on the humanoid
humanoid.AutoRotate = false

local function adjustCharRotation()
	local moveVector = control:GetMoveVector()
    local rotGoal = {}
	local _,camRotX,_  = camera.CFrame:ToOrientation()

	-- Find goal rotation CFrame and goal angle
	local angle = (math.atan2(moveVector.X, moveVector.Z) + (math.pi)) % (math.pi * 2)
	
	if not(moveVector.Z == 0 and moveVector.X == 0) then
		rotGoal.CFrame = CFrame.new(root.Position) * CFrame.Angles(0, angle + camRotX, 0)
		goalRad = angle + camRotX
		
			-- Calculate walkspeed and tween time
	    local calcRad = math.abs(goalRad - math.rad(root.Orientation.Y))
	    if calcRad > math.pi or calcRad < -math.pi then
	        local correctRad = math.abs(math.pi*2 - calcRad)
	        tweenTime = BASE_TWEEN_TIME * correctRad
	        char.Humanoid.WalkSpeed = movementSpeed - (correctRad*DELTA_GRADIENT)
	    else
	        tweenTime = BASE_TWEEN_TIME * calcRad
	        char.Humanoid.WalkSpeed = movementSpeed - (calcRad*DELTA_GRADIENT)
	    end
	
		-- Do rotation tween
	    local rotInfo = TweenInfo.new(tweenTime, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0)
	    rotTween = TS:Create(player.Character.HumanoidRootPart, rotInfo, rotGoal)
	    rotTween:Play()
	elseif rotTween then
		rotTween:Pause()
	end
end

game:GetService("RunService").RenderStepped:Connect(adjustCharRotation)
8 Likes

The continuous tween after releasing input was intentional for the game I’m making. But very well done, I’ll have to review the math for more simply getting directions from MoveVectors.

1 Like