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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

How does rb2d.MovePosition() interact with Physics2d.Simulate()?

Discussion in 'Physics' started by jusw85, Apr 7, 2020.

  1. jusw85

    jusw85

    Joined:
    Apr 21, 2016
    Posts:
    21
    How does rb2d.MovePosition() interact with Physics2d.Simulate()?

    Background:

    I use raycasts and transform.translate for a 2D application with the following pattern:
    Code (CSharp):
    1.  
    2. [RequireComponent(typeof(RigidBody2D))]
    3. public class KinematicRigidbody2DObject
    4. {
    5.     private void Awake()
    6.     {
    7.         // I don't need world.step
    8.         Physics2D.autoSimulation = false;
    9.     }
    10.     private void Update()
    11.     {
    12.         var hits = PerformRaycasts();
    13.         var posDelta = Calculate(hits);
    14.  
    15.         transform.Translate(posDelta);
    16.     }
    17.     private void LateUpdate()
    18.     {
    19.         // run once per frame
    20.         // make sure box2d sees updated body positions for raycasts
    21.         Physics2D.SyncTransforms();
    22.     }
    23. }
    24.  
    But based on the following discussion,
    https://forum.unity.com/threads/smooth-movement-test-application-2d-webgl.734021/

    I'm trying out the following pattern:
    Code (CSharp):
    1.  
    2. [RequireComponent(typeof(RigidBody2D))]
    3. public class KinematicRigidbody2DObject
    4. {
    5.     private void Awake()
    6.     {
    7.         Physics2D.autoSimulation = false;
    8.     }
    9.     private void Update()
    10.     {
    11.         var hits = PerformRaycasts();
    12.         var newPos = Calculate(hits);
    13.  
    14.         rb2d.MovePosition(newPos);
    15.     }
    16.     private void LateUpdate()
    17.     {
    18.         Physics2D.Simulate(Time.deltaTime);
    19.     }
    20. }
    21.  
    I didn't need a timestep in my original method, but now I need to supply a timestep in Physics2D.Simulate.

    From what I understand, MovePosition sets the velocity of the rb2D to move to position over a single physics simulation step, then resets the velocity. This allows it to interact with colliders along the way rather than teleporting, which is nice to have.

    But what's correct value of timestep? MovePosition sets velocity, velocity is distance over time, what time step was used? When I try Physics2D.Simulate(100), it doesn't work properly.

    Thus my questions:
    - What timestep should I use?
    - What's the relation between MovePosition and Simulate?
    - If I MovePosition and Simulate in an Update frame, is the transform immediately updated?

    Also, the following passage is a little concerning:
    https://docs.unity3d.com/ScriptReference/Rigidbody2D.MovePosition.html
    Side question: How expensive is multiple invocations of Physics2d.SyncTransforms if there are no dirty transforms?
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    Your new pattern is far better performance-wise for sure. It's the job of the Rigidbody2D to modify the Transform so it should be treated as a proxy to it and changed if only absolutely necessary. When you change a Transform, it only does that and Physics doesn't know about it, nor do any other internal Unity systems. At some point, they have to query the Transform system to ask if any changes have occurred. The only good part about that is that we can set-up queries beforehand on GameObjects we're interested in. Physics does this for GameObject that have Rigidbody2D/Collider2D on them. This way we can query if there are any Transform changes physics is interested in. The physics system is hoping that there are no changes as they are treated as interruptions resulting in unnecessary work. Interpolation is stopped because bodies are instantly teleported, colliders are recreated if they're Implicitly Static (no RB) or are on a GameObject with no RB on it etc. Not good but we have to jump through the hoops of what the user is allowed by Unity to do.

    Explictly running SyncTransform checks to see if there are any user Transform changes and relocates any bodies/colliders (instant reposition or recreation of colliders). This should be avoided. We automatically do that once prior to simulation but the hope is that there are none as modifying the Transform is bad and hopefully avoidable in most cases.

    Setting Rigidbody2D.position/.rotation doesn't update the Transform either. Performance-wise doing this would be terrible and would create annoying side-effects. The only time this is done though is after the simulation has stepped updating the Transform poses to the Rigidbody2D poses. This is known as the write-back phase. This is why we say the Rigidbody2D is in control of and should be used as a proxy to the Transform.

    So treat the above as a preface. Now to your questions:

    Previously there was a bug (since we introduced manually simulation) where if you used per-frame simulation or anything that wasn't fixed-time where the calculated velocity for the move wasn't correct. This has been fixed however as I mention in that thread you referenced here.

    If you want physics to be simulated per-frame the you use the per-frame time-delta (Time.deltaTime). If you're doing it during the fixed-update then (Time.fixedDeltaTime). If you're using 2020.1 you don't even need to manually do this, you can select per-frame in the Physics 2D settings.

    MovePosition asks the body to move when the simulation is run. When the simulation is run, it is noted that the body has been asked to move to a position/rotation. At that point, the linear/angular velocity is calculated to move to that pose over the time-step passed into the simulation (this comes from what you pass or if AutoSimulation is on, what Unity passes). Also, linear/angular drag is temporarily set to zero. The simulation is run and the body will be at the new pose. The velocities/drags for the body are restored prior to returning from the simulation call and prior to the physics callbacks happening.

    As stated above, MovePosition has nothing to do with the Transform. It's a request to move to a position. Also as I said above, when the simulation runs, one of its final acts (prior to returning) is to write the body poses back to the Transform system.

    A body has a limit on how large a Translation and Rotation can happen in a single simulation step. This is controlled by Physics2D.maxTranslationSpeed and Physics2D.maxRotationSpeed. These already default to many times larger than what Box2D defaults to and should be more than adequate but we exposes these Box2D compile-time constants as properties you can change.

    Doing something like "Physics2D.Simulate(100)" is kind of crazy though if you expect some realistic simulation over 100 seconds. By default, at fixed-update of 50hz this would be done by 5000 simulation steps (50 * 100). You would quickly hit the Translation/Rotation limits here. Increasing them because you want to simulation 100 seconds in one go (which would not be the same results as 5000 simulation steps) would potentially make things very unstable.

    You'd have to use the profiler. Know that this isn't a lot of fancy physics work. All the expense here is the call into the Transform system asking if anything has changed. The devs who work on this have tried to make the case of no changes as fast as possible but it's not something the physics has any control over. We do it once regardless and it's proven to be insignificant. The train of thought though is correct; make sure this is always the situation where you have none or as few as possible Transform changes.[/QUOTE]

    You'd have to use the profiler. Know that this isn't a lot of fancy physics work. All the expense here is the call into the Transform system asking if anything has changed. The devs who work on this have tried to make the case of no changes as fast as possible but it's not something the physics has any control over. We do it once regardless and it's proven to be insignificant. The train of thought though is correct; make sure this is always the situation where you have none or as few as possible Transform changes.
     
    Last edited: Apr 7, 2020
    jusw85 likes this.
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    (Sorry, had to edit the above as the quotes got confused)
     
    jusw85 likes this.
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    Code (CSharp):
    1. [RequireComponent(typeof(RigidBody2D))]
    2. public class KinematicRigidbody2DObject
    3. {
    4.     private void Awake()
    5.     {
    6.         Physics2D.autoSimulation = false;
    7.     }
    8.     private void Update()
    9.     {
    10.         var hits = PerformRaycasts();
    11.         var newPos = Calculate(hits);
    12.         rb2d.MovePosition(newPos);
    13.     }
    14.     private void LateUpdate()
    15.     {
    16.         Physics2D.Simulate(Time.deltaTime);
    17.     }
    18. }
    By the way, I'm hoping this is pseudo-code and not something you use for real. Performing the simulation does this for all of the physics scene. The above doesn't update physics for a single "object".
     
    jusw85 likes this.
  5. jusw85

    jusw85

    Joined:
    Apr 21, 2016
    Posts:
    21
    Thanks! Your post was illuminating! Actually I already understand most what's in the preface, let me summarise and clarify a few points:

    I want precise control of my simulation by using raycasts and moving directly to a computed point. All I need from Box2D is raycasts, overlaps, etc. with it's shapes, I don't need to world.step the simulation, I don't use velocity, drag, etc., so I turn off autoSimulation. Then I update Unity transform directly, then make sure Box2D has an updated internal representation by using SyncTransforms (Unity -> Box2D), so that my raycasts using Box2D isn't using outdated data.

    But I'm aware that it's always been recommended in documentation and various sources to work with Box2D representation directly using the rb2d. In the past, Box2D only happened during FixedUpdate. Because FixedUpdate and Update run on different frequencies, it's caused various problems for me in the past, so I've always used my previous pattern and used Update only.

    But now I'm aware of Physics.Simulate, which allows me to sync manually in Update. Which means I can use MovePosition as recommended to move Box2D shapes internally, then Physics.Simulate to make sure Unity transforms are updated (Box2D -> Unity) in Update.

    My original question was, within one Update frame, I use MovePosition to move directly and precisely to Point X. Now I want to use Physics.Simulate() to:
    1. Perform the move, triggering any collisions/triggers along the way
    2. More importantly, update Unity transform with the new position X in Box2D internal representation

    What should be the argument in Simulate(timestep), since MovePosition is moved using velocity, which is distance/time.
    If I understand correctly, I can use any argument for timestep after the fix e.g. Physics2D.Simulate(100) and Physics2D.Simulate(0.001) would work, and they would give the same result? This is within the context of one call to MovePosition only, to move directly to a point. I'm not interested in simulating bodies due to velocity, drag, etc.. Of course, if I were interested in simulating the movement of a body with an applied velocity over time t, I would specify Physics2D.Simulate(t) specifically.

    My default Physics2D.maxTranslationSpeed is 100. From documentation, that's "maximum linear speed of a rigid-body per physics update". For the sake of argument, let's say I want to move an object from (0,0) to (10000,10000) using MovePosition + Physics2D.Simulate() in a single frame. Is each call to Physics2D.Simulate(t) a "physics update" regardless of t? In that case, does that mean that it exceeds maxTranslationSpeed? How then would I move a large distance using MovePosition?

    Thanks in advance for your time and your detailed responses!
     
    Last edited: Apr 7, 2020
  6. jusw85

    jusw85

    Joined:
    Apr 21, 2016
    Posts:
    21
    Yeah haha no, it's pseduocode. It's only run once per frame in a Manager object.
     
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    Yes. When you call MovePosition/MoveRotation it simply stores the target position/rotation you requested and flags that it needs to happen. Prior to the bug-fix mentioned above, it also calculated the velocity which was obviously incorrect. Now when you perform the simulation, it calculates velocity required to move the distance to target over the specified tmie-step (pass into Physics2D.Simulate).

    I'd like to clarify something. You're asking about what time-delta to use and seem to be indicating that you've only got Kinematic bodies and no dynamic bodies using gravity, forces or collision-detection/response. Is this the case?

    If this isn't the case then the choice of time-delta should be based upon the time elapsed since you last did a simulation step if you want physics to maintain real game-time.
     
    jusw85 likes this.
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    Forgot to answer this. Yes, a "physics update" is a single simulation step but this is time-integrated movement. Normally for fixed-update this is 50hz so (1/50) i.e. "Physics2D.Simulate(1/50)". An object with a linear velocity of (1000,0) would only move (1000,0) * 1/50 per simulation step so wouldn't be limited by 100 translation speed as it'd move (20,0). This is the case for movement using its velocities.

    Because MovePosition/MoveRotation moves in a single step then it'd be limited by the exact settings above for max translation/rotation. Then again, I don't see why you'd be wanting an object to move through space in a single integration step over such a large distance.

    If all of this is with Kinematic bodies then you can just set the position directly. You won't get continuous col-det between Kinematic bodies as they won't stop at the point of impact or contact each other.
     
    Last edited: Apr 7, 2020
    jusw85 likes this.
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    I feel like there's a shorter way to get you your answers though. If you could describe in more detail what types of bodies and interaction you're doing. All I know is bodies being told to move to a position then some raycast stuff.
     
    Last edited: Apr 7, 2020
    jusw85 likes this.
  10. jusw85

    jusw85

    Joined:
    Apr 21, 2016
    Posts:
    21
    Yup, I only have moving kinematic bodies and non moving static bodies (implicitly added by colliders).

    Mainly 2D top down and platformers. When I first started Unity 4 years ago I grappled endlessly with the physics system trying to get it to do precisely what I wanted. In the end I found it much easier to just move transforms directly and only use physics for raycasts and overlaps.

    But the documentation and forum posts has always made it clear that moving transforms directly with rb2d is not recommended. So now that there's a "proper" way to do things, to move the physics objects directly and update the Unity transforms from the physics objects. I'm experimenting and intending to try the new pattern starting from my next mini project.

    Before doing that, I want to understand and assess whats going on under the hood, what the limitations are, etc.. That's why I'm speaking in hypotheticals somewhat instead of discrete examples. And, through my experimentation, it doesn't seem that straightforward (to me) compared to my original pattern, mainly because:
    1. I need to supply an additional timestep argument
    2. MovePosition doesn't move to position directly, it does so via a calculated velocity, which is subject to some limits
    My conclusion so far is:

    Option A:
    1. Use rb2d.position to set position directly, thus foregoing callbacks such as OnTrigger if it teleports through a trigger collider
    2. Physics.simulate(t) to update Unity transform. Technically, any t will do.
    Option B:
    1. Use rb2d.MovePosition to move to position. This will trigger callbacks such as OnTrigger if it passes through a trigger collider. However, this cannot move exceedingly large distances due to limit of maxTranslationSpeed
    2. Physics.simulate(t) to update Unity transform. Technically, any t will do.

    Just to clarify:
    If I rb2d.MovePosition from (0, 0) to (5, 0), and Physics.simulate(0.02), I would end up with an internal linear speed of 5/0.02=250 in one physics update, which exceeds the default of 100.

    But if I rb2d.MovePosition from (0, 0) to (5, 0), and Physics.simulate(1), I would end up with an internal linear speed of 5/1=5 in one physics update, well below 100.

    And since they both achieve the same effect, speaking purely from the perspective of performing MovePositions only, no velocities or drag, I should just Physics.simulate(float.MaxValue) to keep my linear velocity low.
     
    MelvMay likes this.
  11. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    Triggers or anything that cannot stop at the contact point are not supported by continous collision detection in Box2D anyway. It's correct however that if you never simulate, you don't get contacts being generated and therefore no callbacks for them. Continuous collision detection only works when one of the collider is attached to a Dynamic body.

    You should not be calling this to sync transforms. You can just call "Physics2D.SyncTransform" to do that if you're not simulating anything.

    As said above, continuous collision detection isn't supported by Triggers or anything that doesn't involve actually stopping at the contact point. Continuous is exactly this and only this. You won't get an Enter & Exit callback.

    You are free to set the max to whatever you like so why is this a limitation for you?

    If you don't care about physics time matching real game time then that's true. You should still use a sensible value though like <= 1 second to keep interval values sane.

    Box2D makes this an internal limit but it's exposed as a variable property so it's not a hard limit.
    Everything inside that is using floats though and that just creates an insane value. Why on earth would you want to do that? So you can not hit the max thresholds? Why not just set the max thesholds to a high value? I'm very very confused! :)
     
    Last edited: Apr 7, 2020
    jusw85 likes this.
  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    With no simulation involved, you're free to just set the Rigidbody2D.position and the Transform.position (for visuals) there and then. No sync, no simulation and you can just perform queries immediately.

    Everything is still discrete collision detection but with your set-up, it was anyway. For Kinematic stuff, you use queries for the equivalent i.e. casts such as raycast (basic) or accurate Rigidbody2D.Cast or Collider2D.Cast etc.
     
    jusw85 likes this.
  13. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    By the way, I see statements like this all the time. This statement is true but only in a specific but common context. What you've described here is far from a common context i.e. a purely Kinematic set-up which does nothing but want to position bodies over large distances then perform queries.

    If you set a Kinematic body position then yes, it's best done via the Rigidbody2D API. Why? Because it'll just happen correctly when you perform the simulation step and interpolation will also work unlike if you set the pose via the Transform or body directly which is just teleporting it. Your set-up seems to want to move body over very large distances; something you wouldn't want interpolation on so just set the position directly.
     
    jusw85 likes this.
  14. jusw85

    jusw85

    Joined:
    Apr 21, 2016
    Posts:
    21
    Thanks for clarifying regarding triggers! It was an incorrect assumption of mine.

    I thought "Physics2D.SyncTransform" was (Unity -> Box2D), to synchronise Box2D's internal representation with Unity's transform.
    "Physics.simulate(t)" is (Box2D -> Unity), it will simulate, then update the Transform pose with the Box2D pose in the write-back phase as you alluded to above. In my example I was using rb2d.MovePosition followed by Physics.Simulate in an Update() to update the transform positions.

    Because [0.0001, 1000000] :(


    Yup, just making sure my understanding was correct that time didn't really matter in this case. I'd most likely use Time.deltaTime.

    Haha, again because [0.0001, 1000000], and confirming my understanding that time didn't really matter.

    THANK YOU! This is kind of what I needed. If I understand this right, setting rb2d.position in Update will update Box2D's internal representation immediately. Subsequent physics queries will have updated values. No need for sync or simulation. This is not documented in the manual nor in C# source since it just delegates to native calls.

    Honestly, I feel all this technical architecture, internals, etc. should be documented somewhere in the manual. Most of the time I find myself going over various sections of the manual trying to decipher and piece together what's precisely going on under the hood so that I can design my architecture and implementation properly, otherwise it would result in unexpected or unperformant behaviour and hair pulling bugs down the road (and it has happened).

    Thanks! I really enjoyed our discussion, and now have a much clearer understanding of what's happening internally!
     
    Last edited: Apr 7, 2020
  15. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    You intend on moving something 1000km? Why is this (sensible) upper limit an issue? Even after we've already come to the conclusion that you don't even need to use MovePosition either. I'm not even sure the Transform system will like you moving that far anyway.

    If you simulate 1 second then it can move 1000km
    If you simulate 0.1 second then it can move 100km
    If you simulate 0.01 second then it can move 10km
    If you simulate 0.001 second then it can move 1km

    Yours is some special case where you're not simulating though so non of the above even applies to you.

    BTW: This is the Box2D constant of 2! :)

    Rigidbody2D.position sets the body position, what else would it do though? It doesn't matter where you call it (why would it?) No physics call knows when you call it, it's irrelevant. The Rigidbody2D *is* the Box2D body. :) We don't mention Box2D because we don't need to in the docs; the two are synonymous. We should add, this sets the body position and sets the Box2D body position?

    Maybe you mean document that if you call it at a certain point (like during "Update") it does the above. If so, and with all due respect, that's something you've invented. It matters not when you call it. :)

    Hope my clarification above doesn't sound like I'm jumping on top of you. It's important to me that I'm getting the correct information across for you and anyone else who might read it.

    Feel free to messsage me if you need any more info.
     
    Last edited: Apr 7, 2020
    jusw85 likes this.
  16. jusw85

    jusw85

    Joined:
    Apr 21, 2016
    Posts:
    21
    Before I go on, I really want to take the time to thank you for entertaining my seemingly pointless questions, it's been really helpful to me :)
    I was just putting out a hypothetical to understand the limits of what I can or can't do if I adopt this approach. Again, I'm not simulating so it doesn't really apply. But for the sake of info for future users:
    • Just to make sure we're on the same page, I'm assuming that 1 metre = 1 unit.
    • 1000000 units per physics time step is the maximum limit.
    • Thus, if I simulate 0.01s, then it can move 10km, or 10000 units.
    • I use PPU values to match tileset, so 128 PPU, and each sprite takes 1 unit. Not a problem.
    • But I've seen recommendations to use 1 PPU for pixel art games. Old advice, awful for physics, and Unity has pixel perfect packages now, but for the sake of argument, let's say I use 1 PPU.
    • If my sprites are 128x128 pixels, then each tile would occupy 128x128 units
    • Moving a tile 80 tiles horizontally would mean 80 * 128 = 10240 units horizontally, which exceeds the limit if I use Physics.Simulate(0.01)
    It's a contrived example, but it does highlight to me these limits exist, it can possibly happen in an unlikely scenario, and I should be aware of these limits when developing my applications, however unlikely I am to run into them.

    Also, if we didn't have this conversation, I wouldn't know about how MovePosition works internally, and wouldn't have connected this method call with maxTranslationSpeed, for which the default value is 100. I would've done Physics.Simulate(0.02f) with the default limit, which is a maximum translation distance of (100 * 0.02f) = 2 units, possibly running into janky behaviour and much hair pulling trying to figure out what's wrong.
    From reading the manual and documentation, I'd always connected RigidBody2D.* methods with FixedUpdate. Internally, I'd conceptualised my mental model as, the physics system is a separate subsystem which only gets called during FixedUpdate. Calling rb2d.position only caches these values somewhere, and the physics system only gets called during FixedUpdate to update it's internal representation of the new position.

    My understanding was wrong, and as you clarified, the Rigidbody2D *is* the Box2D body. Calling rb2d.position updates the physics system internal representation of body positions immediately, it isn't cached and only updated during FixedUpdate.
    I dont mean those methods specifically, I mean in general, the technical architecture and internals. I don't have a clear understanding of what's happening, and have to form a mental model based on the manual, scattered blog posts, multiple Unite talks, C# source, then implement and hope I've done it correctly and nothing goes wrong because my mental model was totally flawed.

    I mean, alot of it still *just works*, and I think you've mentioned in another thread, you have to anticipate what devs will do, and code defensively for that, even if it's the "wrong" way of doing things. For example, I think you've always advocated that transform should *not* be modified directly with a rb2d, instead the rb2d should be manipulated with rb2d.* methods and act as a proxy for the transform. This whole thread is me trying to do it the "recommended" way, and finding out that I can just use rb2d.position + transform.translate in Update directly, against your recommendation, and filling a gap in my mental model, although I could've just fumbled my way through, and it would still have worked, short of some totally unnoticeable performance issues and maybe unexplained extremely rare bugs.

    All of this is not apparent from reading the documentation. I like to have a clear mental model of what's happening during implementation to avoid issues like the above. I use libGDX in a commercial non-game context, and whatever gaps and unexplained bugs I have, I can jump directly into and read off the source. The MovePosition issue would not have occurred, cause I would have read the source code and seen that it computes velocity, uses maxTranslationSpeed, and understood precisely how it works, and understood the gotchas and limits.

    I mean, I love Unity's ecosystem and tooling, but the partially closed source nature and having to piece together a clear mental model frustrates me sometimes.
    NOT AT ALL! If anything, I'm honoured that a Unity staff member would spend the time to type out replies to me with so much detail.

    Sorry for the long post :p /endrant
     
    Last edited: Apr 7, 2020
  17. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,623
    There's a reason why Box2D sets this to 2 as that's 2 meters per sim step. The suggestion that Unity setting this limit to 1 milliion still creates a limitation is only true in an acedemic sense but not in any practical sense. You have to remember that this is a physics system and you're saying that the physics system not allowing you to move a body at 1 million meters/sec (Mach 2915) is a limitation? I'd instead classify it as a misuse of a function. :)

    In this case there's no reason whatsoever not to just set the position directly.

    You do not use MovePosition to teleport a body to a completely different position over large distances and I've never come across anyone trying to use it that way and for good reason. You use it to move a body by small increments as you would normally move in a physics simulation i.e. do as a Dynamic rigidbody would move as in a standard character controller or just moving a kinematic platform by a small amount.

    Also, you suggested docs are the answer to detail internals but the basic stuff above is clearly stated in the docs (MovePosition) including: "It is recommended that you use this for relatively small distance movements only." so yeah, use it appropriately. :)
     
    Last edited: Apr 7, 2020
    jusw85 likes this.
  18. jusw85

    jusw85

    Joined:
    Apr 21, 2016
    Posts:
    21
    I actually thought of using MovePosition because
    1. I'm using kinematic bodies, and in the manual it says "Kinematic Rigidbody 2D is designed to be repositioned explicitly via Rigidbody2D.MovePosition or Rigidbody2D.MoveRotation"
    2. You mentioned in the other thread, "MovePosition needs to be superior to just setting the position because that can cause collision tunnelling because it just instantly teleports to that position."
    Therefore, my conclusion was, use MovePosition if possible, which in my case is an incorrect usage due to incomplete understanding and glossing over that section in documentation. Also, I wouldn't have moved large distances normally, but was hypothesizing for the possibility that I might in the future. Knowing that this limitation exists, and that I don't really need it and can set position directly, I'd just use setPosition in my application.
    I think this is one of our main differences in how I see the 2D physics system. I'm not interested in the physics simulation, practical limits on velocity, or representing realistically in metres. I just want to perform mathematical intersect and overlap tests on convex polygons in 2D space which Physics2D can do for me. I believed that the only limitation is max and min position based on size of the data type used to repesent the position (float). And I was confused with the proper way to update the position of physics shapes, using MovePosition instead of .position directly.

    [edit]
    I'm now using this pattern:
    Code (CSharp):
    1.  
    2. [RequireComponent(typeof(RigidBody2D))]
    3. public class KinematicRigidbody2DObject
    4. {
    5.     private void Awake()
    6.     {
    7.         Physics2D.autoSimulation = false;
    8.     }
    9.     private void Update()
    10.     {
    11.         var hits = PerformRaycasts();
    12.         var newPos = Calculate(hits);
    13.  
    14.         rb2d.position = newPos;
    15.     }
    16.     private void LateUpdate()
    17.     {
    18.         Physics2D.Simulate(0);
    19.     }
    20. }
     
    Last edited: Apr 7, 2020