Adding child to rigidbody makes it move - unity3d

I have a parent object with a rigidbody (gravity disabled). With a script I am adding simple cubes with box colliders as children to this parent.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
public GameObject prefab;
void Update()
{
if(Input.GetMouseButtonDown(0))
{
GameObject go = Instantiate(prefab, transform);
go.transform.localPosition = new Vector3(10f, 10f, 10f);
}
}
}
This works fine, but a slight movement of the parent object is visible everytime a cube is instantiated and parented. So eventually after adding quite a few cubes the parent moves even whole units from its original position, although the velocity is always Vector3.zero.
How does this movement happen and how do I prevent it?

So, it appears that the small movement of the rigidbody parent comes from a change in the centre of mass. By moving or instantiating objects as childs this value has been changed as it states in https://docs.unity3d.com/ScriptReference/Rigidbody-centerOfMass.html:
If you don't set the center of mass from a script it will be
calculated automatically from all colliders attached to the rigidbody.
After a custom center of mass set, it will no longer be recomputed
automatically on modifications such as adding or removing colliders,
translating them, scaling etc. To revert back to the automatically
computed center of mass, use Rigidbody.ResetCenterOfMass.
Finally, as solution I just set the local center of mass to a fixed value.
rig.centerOfMass = Vector3.zero;
I am quite happy with this solution, because this also changes the center of rotation. Still I am not quite sure why it adds a movement on a change in the center of mass, because I don't see why that would be realistic behaviour.
Also there is a difference between rigidbody.position and transform.position. By using solutions such as commented under the question:
Unparent, move child, parent again
Disable child, move child, enable child again
Disable the child's collider, move child, enable it again
...it is possible to keep the transform.position the same, but rigidbody.position will still change. This difference between both values persists as long as the rigidbody is asleep. Waking it up e.g. by calling Rigidbody.Wakeup() will sync both values again. Due to a difference in both values even things like a raycast can fail, although the ray might be hitting the spot where the meshes are actually drawn and just the physics engine thinks they are somewhere else. Also waking up again looks ugly because the mesh snaps back into place were it should be to match the rigidbody.

Related

Why does the object get stuck in the wall when repelled?

I made the endless movement of the object and its repulsion from the walls, but it does not always work correctly. At rounded corners (sometimes even at a straight wall), it just gets stuck and stops moving altogether, or moves slowly to the point where it stops moving. What can this be related to and how can it be fixed?
private void FixedUpdate() {
rb.velocity = direction * normalSpeed;
lastDirection = direction;
}
private void OnCollisionEnter2D(Collision2D collision) {
//Repulsion from objects.
direction = Vector3.Reflect(lastDirection.normalized, collision.GetContact(0).normal);
}
There is a small distance between the objects, but the circle seems to stick to the wall and moves with it until it collides with another collider:
Example
there are objects under the circle that also have colliders, but the collision between them is not considered, since they have the same layer (in the settings, I disabled the collision for objects on the same layer). What can be done to fix this error and what can it be related to?
The object in the general scale:
Example
I tried to increase the size of the wall collider, tried to change polygon collider to box collider, connect composite collider, changed the mechanics of the object movement (in these cases, the movement could work incorrectly), but the result was always the same - the jams (sticking to the wall) continued.
It is difficult to answer your question without having more information, but I can suggest if you are using physics to move your objects - utilize physic materials and remove code that changes direction manually in OnCollisionEnter. Using physic materials you can easily make your object bounce from colliders of your choice without losing velocity.

How do I check for and resolve collisions within FixedUpdate using a kinematic rigidbody?

I have been working on my own kinematic character controller for a while, but only recently learned that one should consider updating its position and rotation using Rigidbody.MovePosition and Rigidbody.MoveRotation instead of directly modifying the Transform component, which is what I am doing now. While my controller works fine, and does not cause any noticeable performance impact in my small games, I want to better understand the benefits of manipulating the Rigidbody component, and especially how this all works within FixedUpdate instead of Update.
To be clear about the supposed impacts on performance, Unity's manual on 2D rigidbodies says:
Any Collider 2D component added to the same GameObject or child GameObject is implicitly attached to that Rigidbody 2D. When a Collider 2D is attached to the Rigidbody 2D, it moves with it. A Collider 2D should never be moved directly using the Transform or any collider offset; the Rigidbody 2D should be moved instead. This offers the best performance and ensures correct collision detection.
Right now, my basic controller loop looks like this in the Update method:
Read the user's input velocity
Modify the controller's velocity based on this input (this velocity is distinct from Rigidbody.velocity)
Using Physics queries, sweep the controller's body against the appropriate collision layers by velocity * Time.deltaTime
Pick a collision resolution position based on a set of rules
Set the controller's Transform.position to this resolution position
I also have a method that moves the controller using Transform.Translate if no collision detection is needed.
As you can see, though my controller GameObject has a kinematic rigidbody attached to it, I never actually use it for anything. Unity's documentation on kinematic rigidbodies is conflicting, stating here:
Note: MovePosition is intended for use with kinematic rigidbodies.
but also here:
If isKinematic is enabled...The rigidbody will be under full control of animation or script control by changing transform.position
I am also unsure about how to manually check for collisions within FixedUpdate, as I have read that FixedUpdate can be called more than once per frame. Frankly, I thought FixedUpdate was only supposed to be used with dynamic rigidbodies to simulate real physics, and thus have only used this method for simple manipulation of those kinds of rigidbodies.
And then Rigidbody.MovePosition states that
2D rigidbodies have a fixed limit on how fast they can move therefore attempting to move large distances over short time-scales can result in the rigidbody not reaching the specified position during the next physics update. It is recommended that you use this for relatively small distance movements only.
What if my character needs to move a very large amount? Do I just set Rigidbody.position directly?
I guess I am trying to figure out how I can reconcile all of this logic to conform to what Unity says is best for performance. Perhaps I need to combine Update and FixedUpdate, but ultimately I am just hoping to receive some clarification and guidance regarding all of this.

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.

Make rigid body bounce off the screen edge

I'm currently working on an object that involves bubble-like movement. This object has a rigidbody and a sphere collider.
I use the AddForce method every 1-3 seconds to make it move continuously and slowly.
Now I'd like to know how to make the rigidbody move in the opposite direction (a.k.a bounce off) when they reach the screen edge already. I have already computed the screen edges using ViewportToWorldPoint method.
One ineffective solution that I thought of is to put empty game objects with collider at the edges but that won't work in my case since I'm building for mobile devices which have different screen resolutions/sizes.
Anyone know a good solution for this?
I'm not sure i got the idea. But i think i had the same problem when i was writing an old mobile game.
I had the same idea you did, use empty game objects with box collider on the edges, but then i thought, this isn't responsive, so i wrote this code:
public class Walls_c : MonoBehaviour {
public Transform righttop;
public Transform rightbottom;
public Transform lefttop;
public Transform leftbottom;
// Use this for initialization
void Start () {
righttop.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(1,1,0));
rightbottom.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(1,0,0));
lefttop.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0,1,0));
leftbottom.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0,0,0));
}
}
With this, i always get the corners of the screen. It's no fancy... but it works.
Let me now if it works.
In order to get a reflection effect, you need Material. Attach a bouncy material to the edges(gameObject) and let the physics calculate what should be the reaction of collision.
Create a Physics 2D material and set the bounceness to some appropriate value say 0.2.
Regarding your issue:
One ineffective solution that I thought of is to put empty game
objects with collider at the edges but that won't work in my case
since I'm building for mobile devices which have different screen
resolutions/sizes.
If you are working with UI component then dealing with boundaries should not be a problem (since it anchors with different resolution) but if it is not the case you can create a script CameraResizer and an enum Anchor (Left, Right, Top, Bottom) and using the same way ViewportToWorldPoint you can align your empty gameObject (boundary) to any screen size by attaching it the gameObject.
Hope it helps!

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.