I'm new to unity and wanted to know how can i set the A and D keys to move me right and left with Rigidbody2D. I found this script on a forum but it doesn't seem to work:
public float speed = 5f;
private float movement = 0f;
private Rigidbody2D rigidBody;
// Use this for initialization
void Start()
{
rigidBody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
movement = Input.GetAxis("Horizontal");
if (movement > 0f)
{
rigidBody.velocity = new Vector2(movement * speed, rigidBody.velocity.y);
}
else if (movement < 0f)
{
rigidBody.velocity = new Vector2(movement * speed, rigidBody.velocity.y);
}
else
{
rigidBody.velocity = new Vector2(0, rigidBody.velocity.y);
}
}
Is there an error being thrown?
First thing to check is that whatever you have attached this script to actually has a Rigidbody2D.
Physics, ie setting rigidbody speeds, should be done in FixedUpdate rather than Update, if you look that up and it seems too confusing right now don't worry, you can get away with this for now.
Perhaps you should try using rb.AddForce(movement * speed, ForceMode2D.Impluse);.
Since the var movement will actually be positive or negative depending on what key you press, the first two bits of the if statements don't have any use.
Try out looking at this for a single tutorial about moving the player.
Related
Im trying to learn coding and watch youtube tutorials learn to code and I came across this code that I put in my prototype game, Im just asking what should I add to make my character do a double jump?
Code:
public class fpsmovement : MonoBehaviour
{
private float yaw = 0.0f, pitch = 0.0f;
private Rigidbody rb;
[SerializeField] float movementspeed = 5.0f, sensitivity = 2.0f;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
rb = gameObject.GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.Space) && Physics.Raycast(rb.transform.position, Vector3.down, 1 + 0.001f))
rb.velocity = new Vector3(rb.velocity.x, 5.0f, rb.velocity.z);
Look();
}
void FixedUpdate()
{
Movement();
}
void Look()
{
pitch -= Input.GetAxisRaw("Mouse Y") * sensitivity;
pitch = Mathf.Clamp(pitch, -90.0f, 90.0f);
yaw += Input.GetAxisRaw("Mouse X") * sensitivity;
Camera.main.transform.localRotation = Quaternion.Euler(pitch, yaw, 0);
}
void Movement()
{
Vector2 axis = new Vector2(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal")).normalized * movementspeed;
Vector3 forward = new Vector3(-Camera.main.transform.right.z, 0.0f, Camera.main.transform.right.x);
Vector3 wishDirector = (forward * axis.x + Camera.main.transform.right * axis.y + Vector3.up * rb.velocity.y);
rb.velocity = wishDirector;
}
}
First of all you need to check if your player is grounded to be allowed to jump. You problably have a player which can jump again forever like a rocket right now. Then you need to create a boolean variable to check if the player can double jump. Set the variable to true when you jump and set the variable to false when you do the 2nd jump. Also, to allow jump, you should check if the player is grounded OR if can doublejump. There is a lot of tutorials on youtube about this topic, I hope you find the code needed easily.
You can try two methods, "Jump" and "Jump1", the first "Jump" method first uses if to judge whether it is on the ground, if it is allowed to jump on the ground, the "Jump1" method judges if it is not on the ground. On this basis, the code logic for judging the jump state is implemented, and finally the button is reset.
Hello I want to make my first game in 2D but when i want to Jump, my Player is flying and he doesnt come back to the ground. I don't know why it doesnt work. Hopefully someone can help me. Thank you. Here is my Code:
using UnityEngine;
using System.Collections;
public class Move2D : MonoBehaviour
{
public float speed = 5f;
public float jumpSpeed = 8f;
private float movement = 0f;
private Rigidbody2D rigidBody;
// Use this for initialization
void Start()
{
rigidBody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
movement = Input.GetAxis("Horizontal");
if (movement > 0f)
{
rigidBody.velocity = new Vector2(movement * speed, rigidBody.velocity.y);
}
else if (movement < 0f)
{
rigidBody.velocity = new Vector2(movement * speed, rigidBody.velocity.y);
}
else
{
rigidBody.velocity = new Vector2(0, rigidBody.velocity.y);
}
if (Input.GetButtonDown("Jump"))
{
rigidBody.velocity = new Vector2(rigidBody.velocity.x, jumpSpeed);
}
}
}
You set the y velocity on jump but never set it back to anything else. I suggest that for jump you use rigidBody.AddForce:
rigidBody.AddForce(transform.up * jumpSpeed, ForceMode2D.Impulse);
I also have to say that your first if..else if...else seems to be redundant.
If movement > 0, you do X, is movement is < 0, you do exactly the same, and
if movement == 0, you still do the same even tho you write it differently. (If movement == 0 then movement * speed is also 0). So you could just state that
rigidBody.velocity = new Vector2(movement * speed, rigidBody.velocity.y);
without using if at all.
edit: I accidentally wrote wrong line for what to use, fixed it now.
edit2: So after both of these changes your Update function would be like:
void Update()
{
movement = Input.GetAxis("Horizontal");
rigidBody.velocity = new Vector2(movement * speed, rigidBody.velocity.y);
if (Input.GetButtonDown("Jump"))
{
rigidBody.AddForce(transform.up * jumpSpeed, ForceMode2D.Impulse);
}
}
Earlier I was facing problem regarding the unity camera problem it always stuck on 0,0,0.08 and also find a solution so I first create an empty gameobject and then drag the camera in that empty gameobject but after doing this the scripts which I applied to the gameobject is working fine but the script which I place in camera is not working at all
Camera Script
public float MovementAmplitude = 0.1f;
public float MovementFrequency = 2.25f;
void Update()
{
transform.position = new Vector3(
transform.position.x,
Mathf.Cos(transform.position.z * MovementFrequency) * MovementAmplitude,
transform.position.z
);
}
Player Script
public float speed = 4.5f;
public float JumpingForcec = 450f;
void Update()
{
transform.position += speed * Vector3.forward * Time.deltaTime;
if (Input.GetKeyDown("space"))
{
Debug.Log("SPace is pressed");
Debug.Log(GetComponent<Rigidbody>());
GetComponent<Rigidbody>().AddForce(Vector3.up * JumpingForcec);
}
}
First of all when dealing with a Rigidbody (or the Physics in general) you shouldn't set a position directly through the Transform component but rather use Rigidbody.position or in your case for a smooth movement even rather Rigidbody.MovePosition, both in FixedUpdate.
In general anything related to the Physics (so also everything using Rigidbody) should be done in FixedUpdate while the check for GetKeyDown has to be done in Update.
PlayerScript
public class PlayerScript : MonoBehaviour
{
public float speed = 4.5f;
public float JumpingForcec = 450f;
// If possible reference this in the Inspector already
[SerializeField] private Rigidbody rigidBody;
private bool jumpWasPressed;
private void Awake()
{
if (!rigidBody) rigidBody = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
rigidBody.MovePosition(transform.position + speed * Vector3.forward * Time.deltaTime);
if (!jumpWasPressed) return;
Debug.Log("SPace was pressed");
rigidBody.AddForce(Vector3.up * JumpingForcec);
jumpWasPressed = false;
}
private void Update()
{
// Note that currently you can multijump .. later you will want to add
// an additional check if you already jump again
if (Input.GetKeyDown(KeyCode.Space)) jumpWasPressed = true;
}
}
Make sure that Is Kinematic is disabled in the Rigidbody component! Otherwise AddForce is not processed.
If isKinematic is enabled, Forces, collisions or joints will not affect the rigidbody anymore.
The camera movement I would move to LateUpdate in order to make sure it is the last thing calculated after the other Update calls have finished. Especially after all user input has been processed (in your case maybe not that relevant since movement is processed in FixedUpdate but in general).
Second problem: Here you are not taking the changed Y position by jumping into account so rather add the "wobbling" effect to the player's transform.position.y and rather use the localPosition for the Camera:
public class CameraScript : MonoBehaviour
{
public float MovementAmplitude = 0.1f;
public float MovementFrequency = 2.25f;
// reference the player object here
public Transform playerTransform;
private float originalLocalPosY;
private void Start()
{
if(!playerTransform) playerTransform = transform.parent;
originalLocalPosY = transform.localPosition.y;
}
private void LateUpdate()
{
transform.localPosition = Vector3.up * (originalLocalPosY + Mathf.Cos(playerTransform.position.z * MovementFrequency) * MovementAmplitude);
}
}
Maybe you want to disable the wobbling effect during a jump later, though ;)
Try to put all the update stuff in the same method, it should work both (theorically, not tested) so you have to fix your code in order to get what you want:
void Update() {
// Camera update
transform.position = new Vector3(
transform.position.x,
Mathf.Cos(transform.position.z * MovementFrequency) * MovementAmplitude,
transform.position.z
);
// Player update
transform.position += speed * Vector3.forward * Time.deltaTime;
if (Input.GetKeyDown("space"))
{
Debug.Log("SPace is pressed");
Debug.Log(GetComponent<Rigidbody>());
GetComponent<Rigidbody>().AddForce(Vector3.up * JumpingForcec);
}
}
Hope this helps you, cheers!
So
Below you see what I initially used to control my characters movement.
_RigidBody.velocity = _ConstantWalkingSpeed * direction.normalized;
This works for walking around in 4 directions. However, if my character falls over an edge, he falls veeeeeery slowly. If I then in mid air disable the walking script, gravity picks up and goes at normal speed.
This leads me to believe that my movement script somehow affects the gravity effect.
As such I tried this solution:
_RigidBody.velocity = _ConstantWalkingSpeed * direction.normalized + new Vector3(0f, _RigidBody.velocity.y, 0f);
That didn't work either, so I tried this:
_RigidBody.velocity = _ConstantWalkingSpeed * direction.normalized + new Vector3(0f, _RigidBody.velocity.y, 0f) + Physics.gravity;
That did make the gravity work, but then the gravity became so strong that I can't move.
I tried only adding Physics.gravity and skipping the new vector part, but then the gravity is still too strong.
TL;DR
The movement script I use affects the players downward gravity, which it shouldn't. I want him to move around but still be affected by gravity. Ideas I have tried didn't work.
Please note that I'd prefer to keep the gravity at -9.81.
Hoping you guys have a suggestion that works :-)
Instead of setting or modifying the velocity, You can use RigidBody.movePositon:
Here is a quick example script I wrote up:
using UnityEngine;
public class simpleMoveRB : MonoBehaviour {
public Rigidbody myBody;
public float _constantWalkSpeed = 3.0f;
Vector3 moveDirection = Vector3.zero;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update() {
if (Input.GetKey(KeyCode.A))
{
moveDirection.x = -1.0f;
}
else if(Input.GetKey(KeyCode.D))
{
moveDirection.x = 1.0f;
}
else
{
moveDirection.x = 0.0f;
}
if(Input.GetKeyDown(KeyCode.Space))
{
myBody.AddForce(Vector3.up * 500.0f);
}
}
private void FixedUpdate()
{
myBody.MovePosition(transform.position + moveDirection * _constantWalkSpeed * Time.deltaTime);
}
}
You can handle movement using this script, and still have gravity work on your object.
Instead of setting the velocity, modify the velocity.
You're overwriting any velocity applied by the physics engine (e.g. gravity) with your input.
_RigidBody.velocity += _ConstantWalkingSpeed * direction.normalized;
You may also want to cap the velocity X and Z values to a maximum:
Vector3 vel = _RigidBody.velocity;
vel.x = Mathf.Min(vel.x, ConstantWalkingSpeed);
vel.z = Mathf.Min(vel.z, ConstantWalkingSpeed);
_RigidBody.velocity = vel;
I'm using this:
void Update(){
if(leftJoystick){
rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
}
}
to move my character forward in the air (using jetpack). When I let go of the joystick my character stops immediately. What I want is that the character keeps moving forward after joystick is released and with time slow down and gradually stop. It looks stupid that my character stops like it hit a wall. What kind of force/velocity/transform I should use so that physics slow down my character after I let go of the joystick?
My rigidbody settings:
Mass: 100
Drag: 0
Angular drag: 0.05
Uses gravity
Not kinematic
Interpolate: interpolate
Collision detection: Discrete
Freeze position: none
Freeze rotation: all
Character also has a capsule collider that is NOT trigger and has no physics material.
EDIT: here is the full code so you can see if there is any conflicts in my code
using UnityEngine;
using System.Collections;
using UnityStandardAssets.CrossPlatformInput;
public class JetpackController : MonoBehaviour{
Rigidbody rb;
// controller axes
[SerializeField]
public string speedAxis = "Vertical";
public string rotateAxis = "HorizontalRotate";
[SerializeField]
public float forwardSpeed;
public float upSpeed;
public float rotateSpeed;
public float rotationIgnoreZone;
public float MAX_HEIGHT;
float speedInput;
float rotateInput;
public bool leftJoystick;
public bool rightJoystick;
ParticleSystem jetpackFire1;
Vector3 originalGravity;
// access Joystick script in Standard assets to detect when right joystick is held down
Joystick joystick_left;
Joystick joystick_right;
void Start () {
if (GetComponent<Rigidbody> ()) {
rb = GetComponent<Rigidbody> ();
} else {
Debug.LogError ("Player needs to have a rigidbody.");
}
// get Joysticks
if (GameObject.Find ("MobileJoystick_left").GetComponent<Joystick> ()) {
joystick_left = GameObject.Find ("MobileJoystick_left").GetComponent<Joystick> ();
} else {
Debug.LogError ("Either gameobject with name 'MobileJoystick_right' does not exist in the scene or it does not have script called Joystick.cs attached to it.");
}
if (GameObject.Find ("MobileJoystick_right").GetComponent<Joystick> ()) {
joystick_right = GameObject.Find ("MobileJoystick_right").GetComponent<Joystick> ();
} else {
Debug.LogError ("Either gameobject with name 'MobileJoystick_right' does not exist in the scene or it does not have script called Joystick.cs attached to it.");
}
jetpackFire1 = GameObject.Find("JetpackFire1").GetComponent<ParticleSystem> ();
jetpackFire1.playbackSpeed = 5.0f;
originalGravity = Physics.gravity;
}
void FixedUpdate () {
GetInput ();
// move forward and backward according to left joysticks input
if(leftJoystick){
// left joystick held down
rb.AddRelativeForce(0, 0, forwardSpeed*speedInput, ForceMode.Impulse);
}
// if right joystick is used
if (rightJoystick) {
jetpackFire1.Play ();
if (transform.position.y < MAX_HEIGHT) {
// allow going up
//rb.AddRelativeForce (0, upSpeed, 0, ForceMode.Impulse);
rb.AddForce(transform.forward * forwardSpeed);
} else if (transform.position.y >= MAX_HEIGHT) {
// prevent player to go any further up and also falling
Physics.gravity = Vector3.zero; // no gravity to prevent player from falling
rb.velocity = Vector3.zero;
}
// rotate
// always keep rotating (player can go past look at joystick dir)
if (rotateInput >= rotationIgnoreZone || rotateInput <= -rotationIgnoreZone) {
transform.Rotate(Vector3.up * rotateInput, Time.deltaTime * rotateSpeed);
}
} else {
jetpackFire1.Stop ();
// if right joystick is released
Physics.gravity = originalGravity; // normal gravity -> player can fall
}
}
public void GetInput(){
speedInput = CrossPlatformInputManager.GetAxis (speedAxis);
rotateInput = CrossPlatformInputManager.GetAxis (rotateAxis);
// access Joystick.cs script to grab wether right joystick is pressed or not
leftJoystick = joystick_left.leftJoystickPressed;
rightJoystick = joystick_right.rightJoystickPressed;
}
}
Can't comment yet
Like J.Small said, you could multiply the velocity with a number around 0.95 to slowly slow the rigidbody down. If you put the multiplication in the Update method I suggest you to multiply the ~0.95 number with Time.deltaTime, so the velocity decrease will be proportional to the passed time.
void Update(){
if(leftJoystick){
rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
}
if(noJoystick){
rb.velocity = rb.velocity * 0.95 * Time.deltaTime;
//Or: rb.velocity.x
}
}
You could also apply a small amount of force instead of multiplying the velocity if you want to slow down the rigidbody in a more configurable way (the amount should be based on Time.deltaTime if you put it into Update - which gets called once a frame), but the method above is easier.
I'm not a pro at coding, so I'm not sure if this'll work for everyone, but I tried something like this to fix a similar issue.
void FixedUpdate()
{
playerRigidbody.AddRelativeForce(Vector2.up * forwardInput * playerSpeed * Time.fixedDeltaTime);
if (forwardInput <= 0)
{
playerRigidbody.velocity = playerRigidbody.velocity / 1.005f; // <-- This will gradually slow down the player when they're idle.
}
}
You could do a simple linear slow down.
void Update(){
if(leftJoystick){
rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
}
if(noJoystick){
rb.velocity = rb.velocity * 0.9;
}
}
Note that the update function gets called on frame update, so I would suggest putting this in a FixedUpdate() function that way the slow rate won't depend on the frame rate.