Pardon the noob question, I am new to Roblox LUA.
I am trying to make the humanoid move forwards and backwards, (as when an officer, guards a perimeter by moving to and fro) but there may be something wrong with this script, because it only moves forwards.
local toggle = true
local RunService = game:GetService("RunService")
local humanoid = game.Players.LocalPlayer.Character:WaitForChild("Humanoid")
RunService:BindToRenderStep("Move", Enum.RenderPriority.Character.Value + 1, function()
while toggle do
humanoid:Move(Vector3.new(0, 0, -1), true)
wait(1)
humanoid:Move(Vector3.new(0, 0, 1), true)
wait(1)
end
end)
And then when I toggle = false, it does not stop.
I can't use keypress as it defeats the purpose of what I intend to do.
Thank you for any assistance.
The way this code is structured does not make much sense. You're creating a loop inside a function that is triggered every frame. Every single frame, you create a new loop... After just 10 seconds you might have 300 loops trying to move the humanoid at the same time.
Because the loops constantly overwrite each other, the last one to run takes precedence... Which is likely why it's only towards one direction.
I presume you want to make the character move towards (0,0,-1) for a second, then towards (0,0,1) for another second and then, if toggle is enabled, run again.
What you should be doing instead is not creating a loop inside the BindToRenderStep, but setting the movement every frame according to where the character should be moving to, and running that loop outside, once:
local toggle = true
local RunService = game:GetService("RunService")
local humanoid = game.Players.LocalPlayer.Character:WaitForChild("Humanoid")
movement = nil
RunService:BindToRenderStep("Move", Enum.RenderPriority.Character.Value + 1, function()
if movement then
humanoid:Move(movement, true)
end
end)
while toggle do
movement = Vector3.new(0, 0, -1)
task.wait(1)
movement = Vector3.new(0, 0, 1)
task.wait(1)
end
movement = nil
Mind that this code has some quirks:
Nothing will be able to run after the while, so nothing will realistically set the toggle off if placed after while toggle do. It depends on where you want to switch the toggle how you'd handle this.
Depending on where you've placed this, it might error. If this is in StarterPlayerScripts you should use the CharacterAdded event to wait until the character exists, and then handle setting the humanoid again when respawning (because the humanoid will not be the same one if the character respawns). If this is in StarterCharacterScripts, there is no need to access the LocalPlayer, you can just do script.Parent:WaitForChild("Humanoid") (though it also comes down to personal preference).
You've made the movement relative to the camera with that true argument to :Move() https://create.roblox.com/docs/reference/engine/classes/Humanoid#Move. The player will still be able to move the camera to change how the movement direction.
Related
I've been trying to get a part, to change rotation to point toward a specified point. Can't find anything googling, so I tried to make it myself.
I tried this: but instead of rotating anything, looks like the rotation just has the regular CFrame functions, and just teleports it to the position.
if (pos ~= nil) then
script.Parent.CFrame = script.Parent.CFrame.Rotation:ToWorldSpace(pos)
end
In Roblox's documentation, Understanding CFrames, there's a section on rotating to face a point.
Essentially, one of the CFrame constructors allows you to pass in two Vector3s. The first is the object's position, and the second is the point to look at. So just use the object's current position for the first value, and the target position as the second value.
if (pos ~= nil) then
local object = script.Parent
local position = object.Position
local look = pos
object.CFrame = CFrame.new(position, look)
end
The devforum was no help so I'm asking it here.
Im trying to make a Five Nights At Freddys game and I’m making the custom camera script, but its not facing the correct direction. Why is this happening?
Video:
https://doy2mn9upadnk.cloudfront.net/uploads/default/original/4X/0/2/4/024cca4de534dcfc084a944d3c2a13abf5382e0c.mp4
Code
RunService.RenderStepped:Connect(function()
if PlayerCharacter:WaitForChild("Player"):WaitForChild("isNightGuard").Value and not game.ReplicatedStorage:FindFirstChild("GameData"):FindFirstChild("inCams").Value then
Mouse.TargetFilter = game.Workspace.NightguardPosition
CurrentCamera.CFrame = CFrame.new(game.Workspace.NightguardPosition.CFrame.Position)
CurrentCamera.CFrame = CFrame.new(CurrentCamera.CFrame.Position, Mouse.UnitRay.Direction * 10)
end
end)
The NightguardPosition part is in the correct position and orientation.
I’ve tried many variations of the camera script but they all have the same result, please help?
The issue here is that for the CFrame.new(Vector3: position, Vector3: lookAt) constructor, the second Vector3 is what the CFrame will point at in world-space and is not a direction vector, unless position is (0, 0, 0), the origin. To fix the issue, you must add NightguardPosition.Position to the where the mouse is pointing in the world since that unit ray of the mouse like an offset when having to set lookAt.
Modified code with some comments (changes made to RenderStepped are suggestions and do not need to be built around!):
CurrentCamera.CameraSubject = workspace.NightguardPosition --// The CameraSubject is the LocalPlayer's Humanoid by default, causing some funky movements. Make sure to revert this
--// when cameras are exited.
--// Small performance improvement, unless this is changed elsewhere. Either way, it is best to only set when necessary and not in a looping behavior.
Mouse.TargetFilter = game.Workspace.NightguardPosition
local nightGuardPos = workspace.NightguardPosition.Position
RunService.RenderStepped:Connect(function()
--// CurrentCamera.CFrame = CFrame.new(game.Workspace.NightguardPosition.CFrame.Position)
--// Can be removed as this is the same as getting the Position of NightguardPosition
CurrentCamera.CFrame = CFrame.new(nightGuardPos, nightGuardPos + Mouse.UnitRay.Direction * 10)
end)
I have a player who is navigating in space. Since it is space, there is not gravity therefore no parabolic trajectory. The player is just going in a horizontal line from left to right. The player is not actually moving, but the background is, so it looks like he is. The x value is fixed.
I have 2 buttons that help the player avoid obstacles like asteroids. One button gives the player upward force, the other one downward force. The following are the functions called when those buttons are pressed.
function moveUp( event )
if event.phase == "ended" then
player:applyForce(0, 8, player.x, player.y)
player:setSequence("jump")
jumpChannel = audio.play(jumpSound)
end
return true
end
function moveDown( event )
if event.phase == "ended" then
player:applyForce(0, -8, player.x, player.y)
player:setSequence("jump")
jumpChannel = audio.play(jumpSound)
end
return true
end
The problem with this implementation is that whenever a force is applied the player keeps going in that direction. Then you have to apply force in the opposite direction and he will keep going in that direction forever. That is not what I want. What I want is :
when UP is pressed, player goes up for certain value (say 50 px) in Y. Then the player keeps going in the horizontal direction from left to right in the new altitude.
When DOWN is pressed, player goes down certain value. Then the player keeps going in the horizontal direction from left to right in the new altitude.
What is the best way to accomplish this? Can I do this using the applyForce function or is there another method? Thanks in advance for your time!
You have to remember that F=ma: if force applied is 0, a is 0, which means velocity does not change. You have two choices:
apply an opposite force that will decrease the speed, and stop when speed is 0. Every Body has myBody.linearDamping factor which you could set to non-zero. If that doesn't work, you can apply your own damping: you make it proportional to Body velocity, so you need an enterFrame event handler that updates the force based on current velocity:
function enterFrame(e)
local v = player:getLinearVelocity()
player:applyForce(- a * v)
end
Here the "a" is damping, some arbitrary number (0 is what you have now; the larger it is, the faster the player will return to 0 velocity). I haven't checked whether the applyForce() is additive (adds to existing forces) or absolute (replaces existing). But you get the idea.
directly move the player:
function moveUp( event )
if event.phase == "ended" then
player:setLinearVelocity(0, 8) -- pixels/sec
You will still need an enterFrame handler to monitor position and setLinearVelocity(0,0) when desired position reached.
You will get smoother, more "realistic" motion with option 1.
I'm new to Corona and looking for a little help manipulating moving objects:
Basically I want a set up where when I can click on a moving object, a dialog box will pop up giving me the option to change the speed of the object and the vector of travel. I'm pretty sure I can figure out the event handling and the dialog but I'm stuck on simply changing the direction of travel to the new vector
in a simple example, I have a rect moving up the screen as follows:
obj1 = display.newRect(500, 800, 10, 40)
transition.to(obj1,{x=500, y = 100, time = 40000})
I know I can change the speed by adjusting the time, but if I use
obj1:rotate(30)
to turn the object 30 degrees, how do I make it travel in the new direction?
Should I be using physics - linear impulse for example, instead of transitions?
Apologies if this is a stupid question but I have searched without success for a solution.
This sounds like what you are trying to do. You would have to modify bits to fit your code but this is a working example. So if you copy it to a new main.lua file and run it you can see how it works. (Click to rotate obj).
local obj = display.newRect(50,50, 10, 40)
local SPEED = 1
local function move(event)
obj.x = obj.x + math.cos(math.rad(obj.rotation)) * SPEED
obj.y = obj.y + math.sin(math.rad(obj.rotation)) * SPEED
end
local function rotate(event)
obj.rotation = obj.rotation + 45
end
Runtime:addEventListener("enterFrame", move)
Runtime:addEventListener("tap", rotate)
Basically I used the "enterFrame" event to 'move' the rectangle, by recalculating the x and y of the objects location using its rotation (which is easy enough to modify) every frame.
For posting reasons here's a simple version of what I'm trying to do.
On the screen I have a simple circle object that is static and doesn't move. The user can then drag and drop a straight line. If the line passes through that circle I'm hoping for the collision event to be triggered.
It appears that unless one of the objects are moving the collision is never detected. Can I detect the collision when the line is drawn?
Collision Event
function onHit(e)
print("hit");
end
Runtime:addEventListener("collision", onHit)
Touch Event
local startX = 0;
local startY = 0;
local endX = 0;
local endY = 0;
function onTouch(e)
if(e.phase == "began") then
startX = e.x
startY = e.y
elseif(e.phase == "moved") then
endX = e.x
endY = e.y
elseif(e.phase == "ended") then
local line = display.newLine(startX, startY, endX, endY)
line:setColor(100, 100, 100)
line.width = 2
physics.addBody(line, "static", { })
end
end
Runtime:addEventListener("touch", onTouch)
Create circle
local c = display.newCircle(50, 50, 24)
physics.addBody(c, "static", { radius = 24 })
This page from the Corona SDK docs describes the bodyType property about halfway down the page. When describing "static" bodies, it says (my emphasis):
static bodies don't move, and don't interact with each other;
examples of static objects would include the ground, or the walls of a
pinball machine.
That means that one of the objects has to be something other than static.
Here's an idea, although I haven't tried it myself: (See update below.) Make the line dynamic when you first create it. Set it to static a few milliseconds later using a timer.performWithDelay function. If a collision event occurs in the meantime, you will know that you've got an overlap, and can set the bodyType back to static immediately. If you don't get a collision event, the bodyType will still be dynamic in the delayed routine, and you'll know you didn't have an overlap. In this case, you'll still need to set the line to static in the delayed routine.
UPDATE: Tested this, using your code as the starting point
I changed the collision event to always set both objects' bodyType to static:
function onHit(e)
print("hit")
e.object1.bodyType = "static"
e.object2.bodyType = "static"
end
Then I changed the addBody call for the line to add it as a dynamic body, with new code to setup a timer.PerformWithDelay function to check after a short time:
physics.addBody(line, "dynamic", { })
timer.performWithDelay(10,
function()
if line.bodyType == "dynamic" then
print ("NO OVERLAP")
line.bodyType = "static"
end
end)
The results were, unfortunately, mixed. It works most of the time, perhaps 95%, but fails occasionally when drawing a line that starts outside the circle and ends inside, which should be an overlap, but is sometimes reported as no overlap. I wasn't able to figure out why this was happening. I'm posting this anyway, hoping that it gets you going, and also thinking that someone may be able to figure out the inconsistent behavior and educate us both.
Failing that, you could add an additional check for the "no overlap" case to check if either endpoint of the line is closer than the radius of the circle away from the center. That would be make things work, but I suppose it misses the whole point of letting the physics engine to the work.
Anyway, good luck!
Perform a raycast when you release your mouse press. This way you can keep both objects static, and know that they intersect via the raycast callback.
(I know that this is an old post, but it was the first hit on my Google search and is incorrect afaic)
Set the body type as kinematic, set it as a sensor, and update its position to the entity it's tied to every frame. Unlike static, kinematic can interact with static.