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);
}
Related
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.
This the strangest thing i ever saw, i swear! So i have a script to the player that when you click on screen the cube jumps in the direction of the arrow(the arrow rotates 360 degres).I changed some settings to the rigidbody2d to make the jump better.Now here comes the strange part,when i run the game and the player is selected in the scene or hierrachy the jump works fine,if i select something else for exemple the camera something chenges the jump,from a very good one to a very bad one,i tryed to build the project and test and is the same,the cube dosen't have the same "Jump".I think it's becouse i changed something in the rigidbody,idk.PLS HELP!!!center
P.S if u ask for the script here it is :
public void Update()
{
Lava.transform.position = new Vector2(transform.position.x, Lava.transform.position.y);//other,not important
cam.transform.position = transform.position + offset;//camera follow player
Arrow.transform.RotateAround(gameObject.transform.position, new Vector3(0, 0, 180), ArrowSpeed * Time.deltaTime); //to make the arrow rotate 360
if (Input.GetMouseButtonDown(0))
{
rb.AddForce(Arrow.transform.right * -ImpulseForce * Time.deltaTime, ForceMode2D.Impulse); //this makes the cube jump
}
//other
score = (int) transform.position.y;
ScoreUI.text = score.ToString();
}
Firstly, RotateAround method takes a normalized vector as its second parameter, such as Vector3.forward in your case.
Secondly, applying any force to a rigidbody should be done in FixedUpdate, not Update (see Rigidbody.AddForce and ForceMode)
In your case it's an impulse, and it's only called when you click, so no need to multiply by delta time.
rb.AddForce(Arrow.transform.right * -ImpulseForce, ForceMode2D.Impulse);
It may not solve all of your issues, but without further information it's tough to know. At least you wont have weird physics behaviors anymore.
I want to move object to right and to left and i have a weird problem when doing it. I am doing Transform.Translate in update method with If(Input..)
This is my code for moving to right
player.transform.Translate(Vector3.right * Time.deltaTime * varLeftRight, Space.World);
(I tried to use ("player") with gameobject attached in inspector and I tried to use rigidbody ("b") but it doesn't help same issue happens))
where the variable varLeftRight is 125.
I am adding force to go forward in oncollision like this:
b.AddForce(Vector3.forward * speed);
And lets say my player is on coordinates:
-0.074 ->x
-1.5166 ->y
4.173041 -z
I put on player rigidbody is kinematic because I want to test why same issue happens when playing. The problem is when I click once it works and moves right
Cordinates with one click:
1.592691
-1.5166
4.173041
But the problem is when i click twice very fast the player position brakes and goes too much to right.
With twice fast clicks to go to right he goes too much and when I get back one field he need to be on this coordinates:
1.592691
-1.5166
4.173041
and he is on this cordinates:
2.101478
-1.5166
4.173041
Idk did I described issue good. I hope you will understand me,
so when I click once to move with trasnform.translate everything works fine
when I click twice quickly he goes too much to right and when I get back one field to see where is he with one click he is not on right place, to go back to left one field is the same method only with adding left parametar like this:
player.transform.Translate(Vector3.left * Time.deltaTime*varLeftRight, Space.World);
I tried removing the Space.World but it doesn't help.
btw: my obstacle collision have all rigidbody is kinematic to true (Tried without rigidbody same issue happens.
In on Collision I am adding force to go forward no other scripts in code.
public class PlayerControl : MonoBehaviour
{
public float bounce;
public float speed;
public float right;
Rigidbody rb;
public GameObject player;
public float varLeftRight;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
rb.AddForce(Vector3.forward * speed);
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Debug.Log("add force");
player.transform.Translate(Vector3.right * Time.deltaTime * varLeftRight, Space.World);
}
if (Input.GetMouseButtonDown(1))
{
player.transform.Translate(Vector3.left * Time.deltaTime*varLeftRight, Space.World);
}
}
private void OnCollisionEnter(Collision collision)
{
rb.AddForce(Vector3.forward * speed);
}
}
I couldn't make sense of why you're adding force on collision, but I have a feeling that's where the issue lies.
I'd comment that out to see if you're still having an issue.
Say that's really the problem, maybe consider only adding force on collision on the proper circumstances (ie. if the player is just colliding with the ground should they get force? or just if colliding with certain elements? etc)
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.)
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.