moving a rigidbody left and right - c#

I can't seem to get my rigidbody to move left and right. The code looks fine and very similar to what everyone else has posted!
The debug statement is getting called but my character is not moving left and right.
Thanks for the help.
public float speed = 4.0f;
void Update()
{
float moveDirection = Input.GetAxis("Horizontal");
if (Input.GetKeyDown("d"))
{
Debug.Log("pressed d");
rb.AddForce(new Vector2(Time.deltaTime * speed * moveDirection, 0), ForceMode2D.Force);
}

I just tested it using an 3D environment, but that shouldn't matter. So after all I'm pretty sure you've got way to less force applied to AddForce.
So try increasing speed to about 40000, then you should be able to notice the AddForce being applied.
If you want to keep the speed value low, you could of course just add a multiplier here:
rb.AddForce(new Vector2(Time.deltaTime * speed * moveDirection * 10000f, 0), ForceMode2D.Force);

A nice one line option would be to use transform translate.
void Update ()
{
transform.Translate(Vector3.right * speed * Input.GetAxis("Horizontal") * Time.deltaTime);
}

AddForce will not work on a Rigidbody which is kinematic. Verify and set isKinematic to false in your Rigidbody component.
If this is already false, trying increasing the force value as suggested by d4Rk.

Related

why is this Unity 3D jump script doesn't work?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
public Rigidbody rb;
public float MouseSensitivity;
public float MoveSpeed;
public float jumpForce;
void Start ()
{
}
void Update()
{
//Look around
rb.MoveRotation(rb.rotation * Quaternion.Euler(new Vector3(0, Input.GetAxis("Mouse X") * MouseSensitivity, 0)));
//Move
rb.MovePosition(transform.position + (transform.forward * Input.GetAxis("Vertical") * MoveSpeed) + (transform.right * Input.GetAxis("Horizontal") * MoveSpeed));
//Jump
if (Input.GetKeyDown("space"))
{
print("clicked");
rb.AddForce(Vector3.up * jumpForce);
}
}
}
this is my code and a picture of the player object when I'm trying to jump it doesn't work but it does print clicked I tried to do many things but nothing worked so if you know how to solve the issue please tell me
RigidBody.AddForce has a second parameter of type ForceMode that defaults to ForceMode.Force. That particular ForceMode is only good for continual application of force (like a rocket's thruster). For a feature like jumping, you'll either want to use ForceMode.Impulse or ForceMode.VelocityChange.
// Pick one or the other
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
rb.AddForce(Vector3.up * jumpForce, ForceMode.VelocityChange);
Also, make sure your jumpForce value isn't tiny or it'll be an unnoticeably small "jump."
Firstly, physics calculations should generally be calculated inside of FixedUpdate(). This is described in the unity documentation here.
Edit: To make it more clear for the comment on my post. Input should be located inside of the Update() method whilst physics calculations should generally be calculated inside of the FixedUpdate() method.
If it is decided that you want to register input inside of Update() and physics calculations, based on that input, inside of FixedUpdate() then you would use a boolean switch.
Looking at your code I would say that either:
The mass of your Rigidbody is high and your jumpForce variable is too low, trying increasing the value of the jumpForce variable to see if the GameObject moves.
Your Rigidbody has the Is Kinematic checkbox selected.
AddForce is defaulting the ForceMode to ForceMode.Force, try using a different force mode like ForceMode.Impulse to deliver a quick force to the GameObject. In your case this would look like rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
Hope this helps.

How can I add a sprinting function to this script?

I should say that I have very very little C# and Unity experience. I got most of this code from a Brackeys tutorial.
So, this code originally just made the player move at a set speed. So, I added a new public float set to a higher speed and set an if statement to change the value of the float that controls the speed (the float is literally named speed). I added a Debug.Log to display if the if statement is triggered/what the value of the speed float is. This log entry always displays once the Lshift key is pressed (default control axes have Fire3 set to Lshift inside of the unity project settings). I think my issue is that my speed is somehow decreasing before the player even moves. Additionally, this is probably the worst way to implement a sprint function, so if anyone has any better ideas, please let me know!
Clarification: The player can move. My intended effect is for the sprint key (Lshift) to be held down to achieve the sprinting effect. I did intend for the speed to reset every frame, so that as soon as the Lshift key is let go, the speed of the player will drop down to the normal state (12f). Currently I have a Debug.Log in place that displays the value of the "speed" float whenever the Lshift key is pressed. This always returns 18 in the console, which is the intended effect. However, even though this number is displayed in the console, there is no actual movement speed change in the player.
public CharacterController controller;
public float speed = 16f;
public float gravity = -9.81f;
public float jumpHeight = 3f;
public float sprintspeed = 18f;
public Transform groundCheck; //this is where the groundcheck empty object goes
public float groundDistance = 0.4f;
public LayerMask groundMask; //make sure to add a layer into the unity project called "ground"
Vector3 velocity;
bool isGrounded;
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask); //this just creates a sphere and checks it's collision state with any other objects
if(isGrounded && velocity.y < 0)
{
velocity.y = -2f; //sets velocity to a low static number.
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
speed = 12f;
if(Input.GetButtonDown("Fire3")) //theoretically increases the speed float only when left control is pressed down
{
speed = sprintspeed;
Debug.Log(speed);
}
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
if(Input.GetButtonDown("Jump") && isGrounded)//jump function below
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
Thanks in advance!
I would look to see what values are in the inspector since both speed and sprintspeed are public. There is a chance that sprintspeed might be set to 12f and therefore not change the speed. Also, keep in mind that with your implementation you can't change the speed variable from the inspector since you're updating it back to 12f every frame.
If that doesn't help with anything, perhaps some clarification is needed. Is your player moving at all? Is it just the sprinting that isn't working? What value does your Debug.Log give you? What are the values in the inspector?

How to use .MoveRotation, .rotation, .MovePosition and .position properly on Rigidbody2D?

I'm trying to make a 'space shooter'-type game for learning purposes. I have trouble with moving the spaceship with Rigidbody2D.
I have already tried running the commands in Update(), FixedUpdate() and using exclusively the Rigidbody2D component (omitting the use of Transform entirely). I also tried marking the Rigidbody2D as both Dynamic and Kinematic, and changed the Simulated property. Nothing worked.
This is my current (not working) code:
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void FixedUpdate()
{
if (Input.GetKey(KeyCode.Q))
rb.MoveRotation(angularSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.E))
rb.MoveRotation(-angularSpeed * Time.deltaTime);
rb.MovePosition(Vector2.up * speed * Time.deltaTime);
}
I expected this code to make the spaceship turn left when I press the 'Q' key, turn right, when I press the 'E' key and always move forward. The actual result is that the spaceship doesn't move and instead of rotating only jitters when either the key 'Q' or 'E' is pressed (it rotates a single step right or left and then no longer responds to input). The code doesn't generate any error messages nor any warnings and doesn't throw any exceptions.
Rigidbody2D.MovePosition and Rigidbody2D.MoveRotation both expect absolute parameters of the final rotation/position you expect them to move to.
For MovePosition you did it correct but for the MoveRotation you are passing in only the relative rotation change but forgot to add it to the current rotation.
It should rather be
void FixedUpdate(
{
if (Input.GetKey(KeyCode.Q))
rb.MoveRotation(rb.rotation + angularSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.E))
rb.MoveRotation(rb.rotation + -angularSpeed * Time.deltaTime);
rb.MovePosition(transform.position + Vector3.up * speed * Time.deltaTime);
}

Unity: player moves up without any such code

I'm creating a movement function for my character(which I've done many times but this time it's not working correctly) and here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(Animator))]
public class Movement : MonoBehaviour {
public CharacterController controller;
public float moveSpeed;
public float jumpForce;
public float gravityScale;
public Animator animator;
private bool shiftPressed = false;
private void Update()
{
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
shiftPressed = true;
else
shiftPressed = false;
if(shiftPressed)
{
moveSpeed = 20f;
} else
{
moveSpeed = 10f;
}
Vector3 moveDirection = new Vector3(Input.GetAxisRaw("Horizontal") * moveSpeed, 0.0f, Input.GetAxis("Vertical") * moveSpeed);
if(Input.GetKey(KeyCode.Space) && controller.isGrounded)
{
moveDirection.y = jumpForce;
}
if (moveDirection != Vector3.zero)
animator.SetFloat("Speed", moveSpeed);
else if (moveDirection == Vector3.zero)
animator.SetFloat("Speed", 0f);
else if (moveDirection != Vector3.zero)
animator.SetFloat("Speed", moveSpeed);
if(moveDirection != Vector3.zero)
transform.rotation = Quaternion.LookRotation(moveDirection);
moveDirection = Camera.main.transform.TransformDirection(moveDirection);
moveDirection.y = moveDirection.y + (Physics.gravity.y * Time.deltaTime * gravityScale);
controller.Move(moveDirection * Time.deltaTime);
}
}
As you can see that there is no function to go up in the y axis except the jump function. Mysteriously, when I press the 'S' key or 'downArrow' the player moves -z as he should but ironically he moves in +y axis as well. To ensure there is no y axis function I tried making jump function a comment but did the same way still. I thought it might be some character specific problem so I tried adding the code to a cube(thinking it to be my animation mistake) but it didn't helped at any point. I ensured the character controller is set nicely(collider and stuff); I've attached screenshots.
Please help!
Thanks in advance.
The problem has already been stated by several here, but it seems you still do not understand the issue, concluding from your reactions.
This line will always make your character move up.
moveDirection.y = moveDirection.y + (Physics.gravity.y * Time.deltaTime * gravityScale);
You are trying to use gravity (which is a force) in conjunction with manipulating transform. In Unity, you either do one of the two, not both. This will lead to undesired and hard to fix results.
If you want to use forces in your code, then i suggest the follow:
Add a RigidBody to your character. Check the "use gravity" checkbox.
Get the RigidBody in your controller script by calling and add force to it to move it.
var rb = getComponent<RigidBody>();
rb.AddForce(10f);
Do note that if you add force, you can add it continuosly in the Update method, or just once by passing a second paramater "forcemode".
rb.AddForce(10, ForceMode.Impulse); // add instant force, using mass
// Or
rb.AddForce(10, ForceMode.VelocityChange); // add instant force, ignoring mass
// Or
rb.AddForce(10, ForceMode.Force); // add continuous force, using mass
// Or
rb.AddForce(10, ForceMode.Acceleration); // add continous force, ignoring mass
Let me guess.. your character keeps moving up by about the current downwards slope of the camera?
As your code stands, as an example, if your Camera's is Vector3(10,0,0) and if you're trying to move Vector3(5, 0, 5), you've asked the movement vector to be transformed to world space, based off of the camera transform. So, your new movement vector will be something like Vector3(5,1,5). This should do the trick:
var worldDirection = Camera.main.transform.TransformDirection(moveDirection);
moveDirection = new Vector3(
worldDirection.x,
moveDirection.y + (Physics.gravity.y * Time.deltaTime * gravityScale),
worldDirection.z );
moveDirection.y = moveDirection.y + (Physics.gravity.y * Time.deltaTime * gravityScale);
This line always sets "y", and is modified/set as the last function prior to the ultimate statement. It is here, you should validate and verify all factors that has influence the final calculation of "y".
You must validate that each of the variables are calculated to your expected values:
moveDirection.y
Physics.gravity.y
Time.deltaTime
gravityScale
Each will influence the final value of moveDirection.y. Once you have verified each individual value, the final y value will make sense to you. If any of these values are not what you expect, you have a bug in the calculation of that variable.
Happy hunting!

Player object changes position while rotating

First of all: Sorry for my bad English, I'm Dutch.
I'm trying to create a player object that can walk forward and backwards (with the up and down keys), and rotate the player with the right and left keys. But when I press the left or right key, the position of the player changes, it looks like it rotates around a certain point. But it should rotate and stay on the same place, like I do when I turn around.
I have some other small programs, with the same 'move script' and the same inputmanager settings. There it works fine, so I have no idea why it doesn't work this time.
This is my move script, but this script works fine with other programs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveScript : MonoBehaviour
{
public float speed = 3f;
public float rotate = 50f;
private Rigidbody rb;
// Update is called once per frame
private void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetButton("Up"))
transform.Translate(Vector3.forward * speed * Time.deltaTime);
if (Input.GetButton("Down"))
transform.Translate(-Vector3.forward * speed * Time.deltaTime);
if (Input.GetButton("Right"))
transform.Rotate(Vector3.up, rotate * Time.deltaTime);
if (Input.GetButton("Left"))
transform.Rotate(-Vector3.up, rotate * Time.deltaTime);
if (gameObject.GetComponent<Rigidbody>().velocity.y < 0.01)
{
if (Input.GetButtonDown("Jump"))
rb.AddForce(0, 225, 0);
}
}
}
The InputManager settings (also the same as other programs where it works fine):
If someone wants a screenshot of something else of my program, you can always ask it of course. I have no idea what the problem could be, if it isn't in the script or the inputmanager.
Following the comments in the OP, the solution should be to use:
if (Input.GetButton("Right"))
transform.localEulerAngles = transform.localEulerAngles + new Vector3(xRotation, 0, 0) * Time.deltaTime;
if (Input.GetButton("Left"))
transform.localEulerAngles = transform.localEulerAngles - new Vector3(xRotation, 0, 0) * Time.deltaTime;
Where xRotation is a float with the amount you want to rotate per second when and while one of the rotation keys is down.
(PS: Don't have unity open right now, so + and - might be inverted, but should be something like that.)

Categories