Does anyone have a good jumping script for 2d games in unity? The code I have works but still is far from jumping, it looks like it is flying.
using UnityEngine;
using System.Collections;
public class movingplayer : MonoBehaviour {
public Vector2 speed = new Vector2(10,10);
private Vector2 movement = new Vector2(1,1);
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float inputX = Input.GetAxis ("Horizontal");
float inputY = Input.GetAxis ("Vertical");
movement = new Vector2(
speed.x * inputX,
speed.y * inputY);
if (Input.GetKeyDown ("space")){
transform.Translate(Vector3.up * 260 * Time.deltaTime, Space.World);
}
}
void FixedUpdate()
{
// 5 - Move the game object
rigidbody2D.velocity = movement;
//rigidbody2D.AddForce(movement);
}
}
Usually for jumping people use Rigidbody2D.AddForce with Forcemode.Impulse. It may seem like your object is pushed once in Y axis and it will fall down automatically due to gravity.
Example:
rigidbody2D.AddForce(new Vector2(0, 10), ForceMode2D.Impulse);
The answer above is now obsolete with Unity 5 or newer. Use this instead!
GetComponent<Rigidbody2D>().AddForce(new Vector2(0,10), ForceMode2D.Impulse);
I also want to add that this leaves the jump height super private and only editable in the script, so this is what I did...
public float playerSpeed; //allows us to be able to change speed in Unity
public Vector2 jumpHeight;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
transform.Translate(playerSpeed * Time.deltaTime, 0f, 0f); //makes player run
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) //makes player jump
{
GetComponent<Rigidbody2D>().AddForce(jumpHeight, ForceMode2D.Impulse);
This makes it to where you can edit the jump height in Unity itself without having to go back to the script.
Side note - I wanted to comment on the answer above, but I can't because I'm new here. :)
Use Addforce() method of a rigidbody compenent, make sure rigidbody is attached to the object and gravity is enabled,
something like this
gameObj.rigidbody2D.AddForce(Vector3.up * 10 * Time.deltaTime); or
gameObj.rigidbody2D.AddForce(Vector3.up * 1000);
See which combination and what values matches your requirement and use accordingly.
Hope it helps
Related
I was attempting to put simple movement into a project and for some reason this has caused the object its applied to to fall extremely slow. I am using the newer input system and I haven't really been using it previously so I'm unsure if it's an error regarding that.
The movement is working as intended so far. Gravity is at default in settings.
public class Movement : MonoBehaviour
{
public Rigidbody2D rb;
public float moveSpeed = 4f;
public InputAction playerControl;
Vector2 moveDirection = Vector2.zero;
private void OnEnable()
{
playerControl.Enable();
}
private void OnDisable()
{
playerControl.Disable();
}
// Update is called once per frame
void Update()
{
moveDirection = playerControl.ReadValue<Vector2>();
}
private void FixedUpdate()
{
rb.velocity = new Vector2(moveDirection.x * moveSpeed, moveDirection.y * moveSpeed);
}
}
This is what I have applied to the player object so far. When actually moving there is no issue, but falling doesn't work as intended
In FixedUpdate, you set the velocity of the RigidBody, including the y component. This does not interact well with gravity.
Gravity decreases the vertical speed of the RigidBody2D to make the object fall. Meanwhile, your code erases these changes each frame, which means that it cannot accelerate downwards, leading to it falling very slowly and at a constant speed (rather than accelerating downwards as expected).
If you have complete control over your vertical movement, how would gravity work? If the player is not meant to be able to control their vertical movement, change the line to:
rb.velocity = new Vector2(moveDirection.x * moveSpeed, rb.velocity.y);
This will fix the issue but will remove your vertical control. Is this what you want?
If you want to keep vertical movement but not overwrite gravity, you have to make some kind of compromise. If you want gravity to act whenever you are not controlling your character's vertical movement, you can do something like this:
if (moveDirection.y > 0.001)
{
rb.velocity = new Vector2(moveDirection.x * moveSpeed, moveDirection.y * moveSpeed);
}
else
{
rb.velocity = new Vector2(moveDirection.x * moveSpeed, rb.velocity.y);
}
You can also add the vertical movement to your vertical speed. This will mean that the player does not have complete control over their vertical speed like their horizontal speed, but rather being able to apply a force against it.
rb.velocity = new Vector2(moveDirection.x * moveSpeed, rb.y + moveDirection.y * verticalMoveSpeed);
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.
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!
I was trying to create a car in unity using a C# Script, everything seems to be fine, the car rotates left and right, except 1 problem. when I press the forward or backwards keys, the car moves left and right instead of forward and backwards, I can't see anything wrong with my code, here's my code:
using UnityEngine;
using System.Collections;
public class Car : MonoBehaviour {
private Rigidbody carRigid;
public int speed;
public int rotateSpeed;
// Use this for initialization
void Start () {
carRigid = GetComponent<Rigidbody> ();
}
// Update is called once per frame
void Update () {
}
void FixedUpdate(){
if (Input.GetButton("Forward")){
carRigid.AddForce (transform.forward * speed * Time.deltaTime);
}
if (Input.GetButton("Reverse")){
carRigid.AddForce (transform.forward * -speed * Time.deltaTime);
}
if (Input.GetButton("Left")){
transform.Rotate (0, rotateSpeed, 0);
}
if (Input.GetButton("Right")){
transform.Rotate (0, rotateSpeed, 0);
}
}
}
Your car is moving on another axis which is different than the axis you want. try transform.right / transform.left or transform.up / transform.down .
I've just tested your code in a blank Unity scene, and I think you AddForce() is the culprit!
I used
if (Input.GetKey(KeyCode.W))
{
transform.position += transform.forward * speed * Time.deltaTime;
}
and this seems to be working great!
Maybe it's because you have imported a 3D model which it's local forward is not correct.
You have some choices:
1) Fix it in the 3d modeling program an export it again.
2) Create an empty GameObject and make this the parent of your car. Assign the rigid body and relevant codes to this GameObject and Rotate the car model in it's local space until it's fixed ( 90 degrees I guess).
3) use transform.right or transform.left depending on the rotation of your model.
I personally prefer first choice.
I've been programming like an hour or so, then i realice that in unity 5 the charactercontroller.isGrounded doesn't work. Could anyone give me a answer?
This is the code i had
public float playerSpeed = 3f;
public float realSpeed = 3f;
public float jumpSpeed= 7f;
public float sprintSpeed= 5f;
public float gravity = 20f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
CharacterController CC = GetComponent<CharacterController>();
if(Input.GetKey(KeyCode.W)){
transform.Translate(Vector3.forward * playerSpeed* Time.deltaTime);
}
if(Input.GetKey(KeyCode.S)){
transform.Translate(Vector3.back * playerSpeed* Time.deltaTime);
}
if(Input.GetKey(KeyCode.D)){
transform.Translate(Vector3.right * playerSpeed* Time.deltaTime);
}
if(Input.GetKey(KeyCode.A)){
transform.Translate(Vector3.left * playerSpeed* Time.deltaTime);
}
if(Input.GetKey(KeyCode.Space) && CC.isGrounded){
transform.Translate(Vector3.up * jumpSpeed* Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftShift)) {
playerSpeed = sprintSpeed;
} else {
playerSpeed = realSpeed;
}
}
}`
So you're trying to make your character jump but only when it's on the ground?
I had this problem before a well. My solution was to make an empty gameobject and place it as a child of your character and a little bit and then put a collider as a trigger on your empty object.
Then you can have collision detection on your empty object to detect whether it is ontriggerstay on just the bottom side. It also compensates for little bumps and stuff.
According to your code you are not using any character controller. You are just changing the position of Object by using translate which will never collide with your ground. Where as to use character controller you have to provide a move direction with gravity to character controller so that its will use character controller to move your player. Gravity vector will pull your character downward and collide with ground then isGrounded will be true. Check Character Controller implementation in this unity script reference for detail.