Why is rigidBody.velocity not very accurate in my unity2d project? - unity3d

I was trying to make my object change direction when it moves by 1 unit, so i set its rigidbody.velocity to be 0.25, and set a coroutine that changes its direction every 4 seconds. But i noticed that it has some small inaccuracies (such as changing direction when moved by 0.998), which builds up to a lot after running for some time.
Now I know the best way is probably to just directly change transform.position in this case, but could someone tell me why does my previous method have these inaccuracies?
Edit:
To add a bit of context, im trying to replicate a traditional snake game but with smooth movement(in stead of jumping between the grids). It was a bit hard to explain how the direction can only be changed when the snake has reached a whole unit so i just said that the direction is changed every 4 seconds in the original post. Here is the code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SnakeHead : MonoBehaviour
{
private Rigidbody2D rigidBody;
private Vector2 currDir;
[SerializeField] private float speed;
void Start()
{
rigidBody = gameObject.GetComponent<Rigidbody2D>();
currDir = Snake.Instance.GetDir();
StartCoroutine(Move());
}
IEnumerator Move()
{
while (GameManager.gameIsRunning)
{
currDir = Snake.Instance.GetDir();
rigidBody.velocity = currDir * speed;
yield return new WaitForSeconds(1 / speed);
}
}
}
note that i set speed to be 0.25 in the unity editor window.
im aware that changing transform.position directly is bad practice, but ive watched several tutorials and all of them did that on the snake's movement. Does anyone know if there's a better way?

It's pretty hard to make it such that you change direction exactly after 4 seconds. Using WaitForSeconds(4) will not wait exactly 4 second, instead it will wait at least 4 seconds as correctly mentioned in the comments. It largely depends on how frequently your coroutine is checked by the engine.
As you already mentioned, it would probably be a good idea to do some explicit actions. Either moving it "by hand" (not through the physics simulation), or periodically set the position to a known value.

Related

Unity 3D - Collisions

I have a problem with physics. It is my first time doing in 3D, so it may be just a beginner mistake.
I just wanted to create a simple player controller and make it so that it can not pass trough cubes.
The problem is that when going straight into the cube, part of the player is in the cube itself. When stop moving, it pushes me, so they are not intersecting (that makes sense).
I tried moving the player using .Transalte, .MovePosition and by changing the velocity of rigidbody itself. None of it change anything. The player can always move a part of him into the cube.
Any ideas how to solve this?
My player controller:
(The 2 lines commented out in Move() are just other ways to move the player.)
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float movementSpeed;
private Vector3 input;
private void Update()
{
GetInput();
}
private void FixedUpdate()
{
Move();
}
private void GetInput()
{
float inputHorizontal = Input.GetAxisRaw("Horizontal");
float intputVertical = Input.GetAxisRaw("Vertical");
input = Vector3.ClampMagnitude(new Vector3(inputHorizontal, 0, intputVertical), 1);
}
private void Move()
{
GetComponent<Rigidbody>().velocity += input * movementSpeed;
//GetComponent<Rigidbody>().MovePosition(GetComponent<Rigidbody>().position + input * movementSpeed * Time.deltaTime);
//transform.Translate(input * movementSpeed * Time.deltaTime, Space.World);
}
}
Player is standing still
Player is moving towards cube
Settings of the Game Objects itself
Now I think I understand your problem.
The collider is a geometric shape that is checked but the outcome wont take place until the collision has actually taken place, this means, one geometric shape being inside the other. By this I mean, that what you are experiencing is the normal behaviour of the collision. If both elemnts are rigid bodies, both will move and your problem wont be perceivable, but if your cube is not a rigid body or is kinematic, will stand still in the same position, and depending on the other object speed, its normal that an invasion/superposition of the elements is perceivable, because that is the frame were the collision took place, and were your element needs to be moved back because it has collided.
Consider that if the speed is high enough, and the position from one frame to another varies enough, the collision might not even take place, because the geometric parts do not interfere between frames, as the position variation might be bigger than the bounds of the collider itself. The collision check at the end of the day, is dicrete, and not continuous (even you can set it as continuous to be as frecuent as possible).
To solve or improve that, you can adjust the speeds to avoid that being perceivable + adjust your collider to make it react before the graphic superposition occurs. This means making the capsule or the cube collider bigger than the graphic element itself. You can even calculate , to make it as bigger as much as your your speed * Time.deltaTime result or speed * FixedTimeStep result, depending on your safety distance needs. I think one of those should be the safety distance you need to take into account before the graphic collision occurs.
Another thing you can do is tight more the times physics calculations are done.
https://docs.unity3d.com/Manual/class-TimeManager.html
But need to be careful with this as this can be a performance devourer and need to be handled with care. You can make some trials with that and check your problem can improve.
Hope that helps
You can increase the scale of your player's collider from the Collider component attached to it. You can check how big the collider is from the editor scene view.
Edit: The issue might be that your movement or collision code is called in Update instead of FixedUpdate. When working with rigidbodies, you want to call the physics calculations inside FixedUpdate.
remove rigidbody from the cube, you can click on 'Gizmos' in the top right of the editor and make sure the colliders are at the edges of the objects.

Best way to smoothly move a character from one point to another [duplicate]

This question already has answers here:
Move GameObject over time
(3 answers)
Closed 4 years ago.
I am trying to make a game where if the user taps the screen their character moves from one point (say left side of the screen) to another point (right side of the screen) smoothly.
I know you can do this a few ways: Coroutines, Lerp or even an animation. I wouldn’t mind code examples as well..
What are some different ways to achieve this?
Thanks in advance!
Well best is mostly opinion based and not a good way to ask actually... anyway
What the other answer didn't mention:
Of course the smoothness doesn't come from Vector3.Lerp nor Coroutines but actually from the Time.deltaTime.
This Time.deltaTime value is the real time passed since the last frame. This allows to do all kind of smooth and especially always taking the same amount of real time movements and actions independent of the frame rate.
In terms of the specific usecase of movements I personally would prefer the usage of Vector3.MoveTowards over Vector3.Lerp because the later gets slower and slower as it gets closer to the target. (At least if you use the transform.position as first value as often done in examples)
Here is the example provided by the Unity scripting API
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform target;
public float speed;
void Update() {
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
}
Instead of target.position of course you can also just define a Vector3 as target position.
If you need collision detection than both shouldn't be used because you might just move the object to far in one step so the collision isn't triggered.
In this case you might find a hint in this post

Wheel Collider Unity: after adding torque the vehicle starts moving sideways

I really killed few hours to try to fix this, Googling for a solution, but I could not.
I've got a vehicle, it's a go-cart, so there are no suspensions (technically there are, but the values are close to 0, to simulate the tires). The vehicle has a rigid body attached and the child object contains the 4 wheel colliders (and the model itself), as can be seen here:
https://dl.dropboxusercontent.com/u/76599014/sxc/Clipboard01.jpg
For testing, I added a short script to make the vehicle move. It's in the GameObject called "gokart":
public class carControler : MonoBehaviour {
public WheelCollider fr, fl, rr, rl;
public float performance = 50f;
void FixedUpdate () {
throttle();
}
public void throttle() {
this.rl.motorTorque = this.performance;
this.rr.motorTorque = this.performance;
} }
What happens is: the rear wheels start to rotate, as intended, but the vehicle starts moving sideways slowly. The movement speed depends on the torque amount (the wheel rotation in this case). There is no movement forward, so this is not the bug, where when you are standing on a flat surface you are drifting on the sides.
Any ideas? If you need a video or a GIF (I have to figure out how to make one) of the movement, I'll be glad to provide one.
I think you should try and apply 0 brake torque to the front wheels while applying motor torque to the rear wheels.
public void throttle() {
this.rl.motorTorque = this.performance;
this.rr.motorTorque = this.performance;
this.fr.brakeTorque = 0f;
this.fl.brakeTorque = 0f;
}
That being said, anything could go wrong if the Rigidbody/wheelcolliders aren't set up correctly. Unity's wheel colliders can be difficult to set up and work with. Unity changed the physics in Unity 5 so most documentations are outdated.
I found this very good short document that was made by unity: http://unity3d.com/profiles/unity3d/themes/unity/resources/downloads/beta/unity-5.0-user-guide.pdf
It highlights the changes that was made to unity 5 and at the end of page 5 you can find a section that explains how to set up a car. I have tried it about a month ago in a new unity project and it worked. the instructions are clear so try this tutorial out and I hope it will help.
Regards
Not having the image available I'm not a totally sure about the situation but my assumption based on your description is you should try increasing the sideways friction and tweak the forward friction a little bit according to your taste. You have to increase the sideways friction anyways as you are making a go-cart. As far as I know, most arcadey go-carts don't drift and behave a lot different from regular racing cars.
Hope that will solve the problem.

Unity Online Interpolation Lerp Flickering 2D Gameobject

I'm trying to get my basic game online and got into some problems.
I followed this tutorial which is really nice and everything worked but one thing, the interpolation.
Without interpolation, I have too much latency issues (the other player is "lagging" a lot). I tried to follow the tutorial, adding
void FixedUpdate()
{
if (networkView.isMine)
else{
syncTime += Time.deltaTime;
rigidbody2D.position = Vector3.Lerp(syncStartPosition, syncEndPosition, syncTime / syncDelay);
}
And using this method:
void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
{
Vector3 syncPosition = Vector3.zero;
if (stream.isWriting)
{
syncPosition = rigidbody2D.position;
stream.Serialize(ref syncPosition);
}
else
{
stream.Serialize(ref syncPosition);
syncTime = 0f;
syncDelay = Time.time - lastSynchronizationTime;
lastSynchronizationTime = Time.time;
syncStartPosition = rigidbody2D.position;
syncEndPosition = syncPosition;
}
}
But now the other player is invisible when not moving, and is visible but flickering a lot when moving (flickering so much I hardly see it). Since my method is called from FixedUpdate, I am wondering if the gameobject is simple refreshing so much that I don't even see it. Is that possible?
In any case, would you have an idea on how to fix this?
Thank you very much for your help in advance!
PS: I tried to lerp only if syncTime/syncDelay < 1.0 to be sure I don't extrapolate, but it did not change a thing.
PPS: When I use the interpolation, it flickers a lot but I can see that the position is right, it is not lagging like before, so the best would be to resolve how to make my interpolation and not removing it.
First of all, do not use Time.deltaTime in FixedUpdate(). FixedUpdate() is for physics only and actually runs around 50fps. On the other hand Time.deltaTime is the time for the last frame. So, technically you will get flickering in your lerp function. Use the function in Update(). And I can see, you are just transforming positions. So, why rigidbody2D.position? you can use transform.position and move the whole codes to Update(). Hope it will help.

unity3d 4.3 bullets coming back down

I am trying to build a 2D space shooter game where the player will remain constant at the bottom of the screen and will move left and right. When the player fires a bullet(projectile), the bullet is going up just fine, but it is coming back again. Also if two bullets collide, they react to the collision.
I have two questions here:
How can I ensure that the bullet does not come back? (One way is to destroy it after a few seconds, but not sure if this is the right way)
How do I avoid collision between the bullets.
Here is my code snippet:
void Update () {
if (Input.GetButtonDown("Fire1"))
{
Rigidbody2D clone = (Rigidbody2D)Instantiate(bullet, transform.position + transform.up, transform.rotation);
clone.velocity = transform.TransformDirection(Vector3.up * 20);
}
}
I am very new to Unity and somehow wrote this code by looking into Unity Forums.Any help will be very much appreciated.
Thanks
More details:
I have created the bullet and added Rigidbody2D and a BoxCollider2D for this object. Made the bullet object a prefab and I dragged it under the Player object. Now bullet is a child of the Player object. Attached the script above to the Player object.
To answer your immediate questions:
1) I am not too sure about how you have the scene setup or about using the Unity 2D tools but usually if your bullets are coming back down then I would assume that you still have gravity applied to the rigidbody -- so make sure that you have that unchecked.
2) With Unity3D for objects to interact with each other they need rigidbodies attached. This is vital, say, if you want your lasers to destroy Monster #1. However, you only need one rigidbody attached to an object to have a desired effect. I would suggest removing the rigidbody from your laser and attach rigidbodies to objects ( Monster #1 ) that you want to be affected by the laser fire. ( That should work, if not there are other options -- one using layers and ignoring particular objects on those layers ).
Tips:
Here are some extra things. When you are creating objects and they fly off screen over time they will build up. Imagine you are in a large battle and you instantiated hundreds of lasers -- it will eventually be an issue for performance. So always consider Destroying objects after a certain amount of time.
Also, after looking at your code, I can't tell whether the velocity of the object is based upon its current position and nothing is being added. What I think is happening is when you instantiate an object it may be moving up, but because there is no incrementer, the object ( as it gets higher ) slows until it is at a rate which it is falling. For example this
clone.velocity = transform.TransformDirection(Vector3.up * 20);
should probably do this:
clone.velocity += transform.TransformDirection(Vector3.up * 20);
Heres http://docs.unity3d.com/Documentation/ScriptReference/Vector3-up.html, to read up on velocity. The problem is is that you need to continuously apply a constant forward motion so things in motion will tend to stay in motion. If not gravity will pull it down.
Also, heres a bit of code that I've used in the past that's created a pretty cool shooting laser effect thing:
public class Laser : MonoBehaviour {
public int fireRate = 70;
void Start(){
InvokeRepeating("FireLaser", 0.01f, 0.009f);
Destroy( gameObject, 2.0f );
}
void FireLaser(){
transform.Translate( Vector3.up * fireRate * Time.deltaTime );
}
}
edit: it's 3 a.m. and I hate proofreading.