Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved Setting rigidbody.position sometimes doesn't change the position

Discussion in 'Scripting' started by Hannes213, Aug 22, 2023.

  1. Hannes213

    Hannes213

    Joined:
    Aug 8, 2022
    Posts:
    6
    The point of the code:
    I have this code that shatters glass using a fracture pattern

    The problem:
    I have noticed a problem a while back where, sometimes when I shoot the glass and thus trigger the code, the new shattered glass doesn't get it's position changed to where it should be when I change the rigidbody.position. This seems to happen no matter the isKinematic value as well.
    Also, the code creates many pieces, and when this issue happens, it happens to every one of them which leads me to believe it could have to do with timing. I have also noticed that when adding both of the Debug.Log()s in the code the issue stops appearing.

    The rigid body (in case it matters):
    rigidbody.interpolation = RigidbodyInterpolation.Extrapolate;
    rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;

    The code:

    I am not gonna post the full code as long as not requested as I believe this includes everything important, but I could be wrong.

    The following is the function where I change the position of the rigidbody.
    Code (CSHARP):
    1.  
    2. private GameObject ConvertConvexPolygon2DToShard(Vector2[] polygon, Transform relativeTo){
    3. //relativeTo is the glass piece being shattered, which is used here to move the newly created polygon to the correct place
    4. if(emptyShardsIn.childCount == 0){
    5. CreateEmptyShards();
    6. }
    7. GameObject shatterPiece = emptyShardsIn.transform.GetChild(0).gameObject; //Get a pooled object
    8. shatterPiece.SetActive(true);
    9. GlassInfo glassInfo = shatterPiece.transform.GetComponent<GlassInfo>();
    10. Rigidbody rigidbody = glassInfo.m_rigidbody; //So that I wouldn't have to do GetComponent<T>() everywhere
    11. rigidbody.rotation = relativeTo.rotation;
    12. MeshFilter meshFilter = glassInfo.meshFilter;
    13. MeshRenderer meshRenderer = glassInfo.meshRenderer;
    14. shatterPiece.transform.parent = glassPieces;
    15. meshRenderer.material = brokenGlassMaterial;
    16. Mesh newMesh = new Mesh();
    17. Vector3[] vertices = new Vector3[polygon.Length];
    18. int[] triangles = new int[(vertices.Length-2)*3];
    19. Vector2 addedPoints = new Vector2(0,0);
    20. for(int i = 0; i < polygon.Length; i++){
    21. Vector2 point = polygon[i];
    22. addedPoints += point;
    23. }
    24. Vector2 pointsMedianCenter = addedPoints/polygon.Length;
    25. rigidbody.position = relativeTo.position + relativeTo.right * pointsMedianCenter.x + relativeTo.up * pointsMedianCenter.y;
    26. //Debug.Log(rigidbody.position); //Adding BOTH of these makes the issue stop
    27. //Debug.Log(relativeTo.position); //When printing these out by themselves though, everything seems alright
    28. for(int i = 0; i < polygon.Length; i++){
    29. Vector2 point = polygon[i];
    30. vertices[i] = Vector3.right*(point.x-pointsMedianCenter.x) + Vector3.up*(point.y-pointsMedianCenter.y); //Move the vertices to counter the rigidbody moving
    31. }
    32. //The following is most likely unimportant
    33. for(int i = 2; i < vertices.Length; i++){ //Fill the polygon
    34. int triangleStart = (i-2)*3;
    35. triangles[triangleStart] = 0;
    36. triangles[triangleStart+1] = i-1;
    37. triangles[triangleStart+2] = i;
    38. }
    39. newMesh.vertices = vertices;
    40. newMesh.triangles = triangles;
    41. meshFilter.mesh = newMesh;
    42. return shatterPiece;
    43. }
    44.  
    Note that I have filtered the code a bit to get rid of completely unimportant lines such as changing the name of the object

    In the code, when logging the two positions by themselves so that the problem still appears, everything seems to be fine which, again, leads me to believe towards this being a timing problem.

    I have attempted to get help for this problem multiple times (in the discord server), but without success.
    Also, I apologize, as this is the first time I use this forum and I might have gotten something wrong, or forgotten to include information that I should have included.

    This could totally be an oversight by me, but I haven't been able to fix this for over a week now so I have come here for help.

    Linux - Unity Version 2022.3.7f1
     
  2. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    According to the documentation:
    https://docs.unity3d.com/ScriptReference/Rigidbody-position.html
    "If you want to continuously move a rigidbody use MovePosition instead, which takes interpolation into account."

    So if these shards are moving, which I think you mention is the problem, try:
    rigidbody.MovePosition(position);

    And see if that helps. :)
     
  3. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,899
    Doesn‘t get the position changed to where it should be: what should it be and what is actually happening? What exactly is the incorrect position? Does it correlate with some other object?

    When do you call this method? From Update, FixedUpdate, or some other Unity event? If you suspect a timing issue you could defer the code by starting a coroutine that yields null (or WaitForFixedUpdate) once and then calls the method.

    Personally I suspect it could be an odd scenario where it matters whether this code runs in Update vs FixedUpdate since you extrapolate the position. In such a case it‘s advisable to modify rigidbody properties only in FixedUpdate because during Update the body‘s position is being inter/extrapolated.

    This would fall in line with the suspicion of this issue being timing related.
     
  4. Hannes213

    Hannes213

    Joined:
    Aug 8, 2022
    Posts:
    6
    No, that's not quite what I want, I need to teleport them to the place the glass broke at first, not move them there continuously, but rigidbody.position = ...; seems to not always actually set the position.
     
  5. Hannes213

    Hannes213

    Joined:
    Aug 8, 2022
    Posts:
    6
    This code is being ran when the player shoots at the glass, which is checked for in Update.

    What should be happening is that once the player shoots at the glass, the broken pieces are generated and then positioned to the glass with a little offset, but what is happening is that the glass isn't being moved at all, it just stays at 0,0,0 where the "emptyShardsIn" objects were created to. I am yet to find any correlation with other objects or the behaviour of the player, other than maybe the timing, but I haven't been able to confirm that yet.

    I suppose I can try to store the changes that need to be done in FixedUpdated in a list and let them be done the next time FixedUpdate is called.

    If the FixedUpdate thing stated above doesn't help then I'll try this, but I am a little unsure if this would change anything if this is timing related and also I definitely couldn't keep it like that as the delay would probably be noticable.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    That's not going to be true; setting the body position will work just fine whenever you do it. You can verify this by setting it and read it immediately after. If that doesn't read back what you set then you are correct and it should be reported as a bug.

    What I expect is though that you're saying "not always actually set the position" to mean the Transform position or some code depending on the Transform position. Setting the body position will only do that. The Transforms are only updated when then simulation is run as is all other physics related data.

    If you're saying that if you read the body position by printing it out and it's all then working, that sounds like auto-sync-transforms is on which will, if you read a property that has a transform change, will update it there and then. You should avoid this and NOT have that property on (it's off by default). You're also doing Transform work by reparenting which makes things very confusing; that stuff doesn't affect the physics stuff immediately.

    The main thing to always know is that the Transform pose != Rigidbody pose. They are completely separate and during normal operation, the Rigidbody will write its pose to the Transform pose when the simulation is run which, by default, is during the FixedUpdate.

    Mixing Transform reparenting, setting body rotation/position, doing calculations before that has updated etc is asking for bugs/confusion. You need to use one pose as your reference, don't change and mix them up.

    I've tried to look over your code but the poor formatting is giving me a headache and it's not clear what is going on TBH.
     
    wideeyenow_unity likes this.
  7. Hannes213

    Hannes213

    Joined:
    Aug 8, 2022
    Posts:
    6
    Oh, and I have also noticed that if I change the transforms and the rigidbodies position then it works. This is most likely very inefficient and I'd much rather only have to move one of them, but moving only the transform also doesn't work and I had moved to changing the rigidbodies position due to that a while back. This feels pretty interesting to me.
     
  8. Hannes213

    Hannes213

    Joined:
    Aug 8, 2022
    Posts:
    6
    Yeah, I don't really know why the code looks like that.
    I am slightly confused of the response, but anyways, I am not changing the transform position. And also I don't have auto-sync-transforms on, I think, at least I haven't intentionally enabled it.
    I had changing the unused and used shards being parented to just storing them in separate arrays or smth on my to-do list, but I didn't know that changing the parent could affect the current situation.
    I'll try and see if it will fix the issue, if not, I'll continue trying the things others have suggested.

    EDIT:
    Yeah, sadly, but as expected, removing the parenting thing didn't change anything.
     
    Last edited: Aug 23, 2023
  9. Hannes213

    Hannes213

    Joined:
    Aug 8, 2022
    Posts:
    6
    Yep, changing the position and rotation in FixedUpdate seems to have fixed the problem.