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)
Related
So I am making a small game in unity where you have to shoot the enemy. However, when I made the script for the bullet and enemy, it half worked and half didn't. Sometimes, the bullet would hit the enemy and destroy the enemy, however, sometimes, it would take multiple shots for it to work. But when I turn the speed of the bullet to 1 (the speed of the bullet was 500), the bullet always destroys the enemy. So this leads me to think that this has something to do with the speed of the bullet. Here is my script
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
Destroy(other.gameObject);
Destroy(gameObject);
Debug.Log("e");
}
For the movement of the bullet, I just used transform.Translate(Vector3.up * Time.deltaTime * speed). How can I fix this?
The problem is not that Destroy do not work with a certain speed, the problem is that with certain speed you are not triggering the "OnTriggerEnter".
This fenomenon is called "tunneling" it happens when the object goes too fast.
That provokes that in one frame the projectile is on one side of the collider, and in the next frame is on the other side of the collider, giving the sensation like a teleport, so that's the why it do not collide, cause in any frame the engine has detected the collide.
If you're having troubles with high speed stuff, try to set your rigidbody (the one that is moving) to Interpolate, or use raycasts to fake bigger projectile colliders.
In addition to Lotan's answer
I just used transform.Translate(Vector3.up * Time.deltaTime * speed)
whenever using physics you do NOT want to set anything via Transform as this bypasses the physics engine and thereby breaks collision detection etc as in your case.
You rather want to through the Rigidbody component and e.g. use Rigidbody.MovePosition
Rigidbody.MovePosition moves a Rigidbody and complies with the interpolation settings
like
private Rigidbody _rigidbody;
private void Awake()
{
_rigidbody = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
_rigidbody.MovePosition(_rigidbody.position + _rigidbody.rotation * Vector3.up * Time.deltaTime * speed);
}
or why not simply set it only once
private void Start()
{
GetComponent<Rigidbody>().velocity = transform.up * speed;
}
Additionally you want to set the interpolation to dynamic.
A tricky way : bullet form A point to B point by one frame , so you can fake a point on a to b like
fake point: A+B/2
Point a ;
Point b ;
Update()
{
Point ab = (a+b)/2;
bullet.point = ab;
//check collider some .
bullet.point = b; // set it back.
a = b;
}
Not a good solution . but it have double hit rate.
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed;
public float jump;
private Rigidbody2D rb;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
rb.position += new Vector2(Input.GetAxis("Horizontal"), 0) * Time.deltaTime * speed;
if(Mathf.Abs(rb.velocity.y) < 0.001f && Input.GetKeyDown(KeyCode.W))
{
rb.AddForce(new Vector2(0, jump), ForceMode2D.Impulse);
}
}
So I have this code for my player movement. I am wondering how can I reduce my character from sliding that much. I don't want to stop instantly after I release the key.
You could add counter-movement to make the movement to feel more responsive, or you could change the friction by adding a physics material. Counter-movement makes the player stop by adding a force opposite to the wanted direction of the movement. It will stop the player from sliding too much. Another approach is to add a physics material and up the friction a bit. This will make the player stop faster. I hope you find this helpful!
Inside of the Input Manager, Edit->Project Settings->Input Manager, there is a property called gravity.
Gravity: Speed in units per second that the axis falls toward neutral when no input is present.
Decreasing this value will cause the input to fall quicker, resulting in less/no sliding.
You can debug your input value to confirm this. You should notice a ramp up from 0 to 1/-1 when you first hold the horizontal input. Once you let go of the input, you should see the value fall back down to 0.
var inputHorz = Input.GetAxis("Horizontal");
Debug.Log(inputHorz);
Lower the value until it feel correct. This can be changed while you are playing the game, but you will need to paste that value back in after pressing stop.
hi everyone so basically I was wondering how I could change this movement script to be with rigidbody. It works the way I want it to with wasd to change look direction and then space to move forward from that direction kinda but I want to convert it all to be done with rigidbody so I can do collisions. Thanks!!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fly : MonoBehaviour
{
public float moveSpeed;
void Start()
{
}
void Update()
{
if (Input.GetKey(KeyCode.Space))
{
transform.Translate(new Vector3(0,0,moveSpeed) * Time.deltaTime, Space.Self);
}
float rotatex = Input.GetAxis("Vertical");
float rotatey = Input.GetAxis("Horizontal");
transform.Rotate(0, rotatey, 0, Space.World);
transform.Rotate(-rotatex * 0.5f, 0, 0);
}
}
There are quite a few errors with your code as written. No problem, but you'll probably need to fix all of these before your code starts working as intended. This answer is meant to give you a springboard to google up on some of these errors and wrap your head around the Update() method and how it works in Unity.
First, you'll need to ensure the RigidBody2d component is on your Game Object. That's easy enough to do, right click in the inspector and add the component. Google: "How do I add components to game objects in Unity"
Next, you're going to want to understand how often Update() is called and how it works. Spoiler alert - it's called as fast as your computer can. What that means is that changing the rotation with transform.Rotate every call is likely going to lead to an object that's spinning extremely rapidly. Perhaps rapidly enough that it's spinning more than 360 degrees each frame and just appears to be "twitching" randomly. You'll need to scale your rotation, so Google up "delta time in Unity Update".
Lastly, you're going to want to collect your inputs, which you're doing correctly with Input.GetKey(), although there are lots of ways to skin this cat. Perhaps the most straightforward would be to collect your inputs in one method called GetAllInputs(), set some booleans in that method to things like IsMovingRight or IsJumping and then operate on them in your Update method. This is only one approach, there are literally dozens, and many ways that they can be improved. Google up "Unity Input System", "Unity 2D Physics", and "Finite State Machines" (since you're eventually going to want to have "states" like crouching, jumping, running, hanging on to a wall, etc). It seems like you're writing a platformer, so I'd also watch some of the youtube tutorials on that, and google phrases like "Creating a Unity Platformer Tutorial".
Assuming it works the way you want here is the code using rigidbody (Make Sure Rigid Body is attached to object) This code must be written in Fixed Update as RigidBody based calculation must be done in Fixed Update:
public class Fly : MonoBehaviour
{
public float moveSpeed;
[SerializeField] private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
if (Input.GetKey(KeyCode.Space))
{
//transform.Translate(new Vector3(0,0,moveSpeed) *
//Time.deltaTime, Space.Self);
if (rb)
{
rb.MovePosition(new Vector3(0,0,moveSpeed) *
Time.deltaTime);
}
}
float rotatex = Input.GetAxis("Vertical");
float rotatey = Input.GetAxis("Horizontal");
// transform.Rotate(0, rotatey, 0, Space.World);
// transform.Rotate(-rotatex * 0.5f, 0, 0);
if (rb)
{
rb.MoveRotation(Quaternion.Euler(rotatex , rotatey , 0));
}
}
}
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'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);
}