I’m updating my project from 2021.3 to Unity 6. One of the first issues I’ve run into is that prefabs that I instantiate end up being in the wrong position. Specifically, these are prefabs that have a rigidbody on them.
I’m instantiating the prefab, then assigning its position:
var preRiftGameObject = Instantiate(prefab);
preRiftGameObject.transform.position = startPosition;
In the prefab’s controller, I’m then emitting the following debug info:
Prior to Unity 6, these would emit the same value. But under Unity 6, I’m finding that (seemingly at random) the _rigidbody’s will not be the same as this.transform.position. Instead, the rigbody’s initial position will be whatever the prefab asset’s transform position is. For example, if the prefab asset in my project has a position of (7,8,9), then the instantiated instance will have an initial rigidbody position of (7,8,9).
But maybe half the time everything works as expected, and the rigidbody’s initial position is identical to the transform position.
Anyone know what’s going on here? Are there changes to physics since 2021.3 that it’s no longer reasonable to set transform.position to initialize a rigidbody’s position? I can work around this issue by calling _rigidbody.position = this.transform.position; in the Start() method, but this seems weirdly clumsy.
I’m not 100% sure if this is a bug now, or just a change in behavior since 2021.3. I did identify that this seemed to be a bug with Rigidbody interpolation, since this was only occurring when the rigidbody’s interpolation was set to Interpolate. I reported bug IN-90557 on that topic.
However, I later figured out that the “bug” does not occur if I set the initial position within the Instantiate call, rather than setting it on the transform in the subsequent line of code, as I showed in my initial post.
So, I’m not sure if the interpolation issue is a bug, or if people are supposed to realize they need to set the initial position within Instantiate instead of immediately after. It’s at least a reliable approach that I can use for now, assuming it’s not considered a bug.
Yeah, seems to be related to the ordering of when you position the transform and when Unity creates the native physics objects. If you set the position in Instantiate, the position is set from the beginning and all physics objects are positioned correctly. However, if you set it after, the physics objects are created using the prefab’s position and it might take until the next physics update for the position to sync.
What’s “Auto Sync Transform” set to in your project and did that setting maybe get changed during the upgrade?
Unity has been trying to optimize transform sync, so this change could be some side effect of an optimization they did. I can see how interpolation could complicate things but would expect behavior to be the same with it turned on or off. Let us know what response you get for your bug report!
I looked into “Auto Sync Transform” right after I first noticed this happening. It’s kind of interesting. It was turned off before the update (under 2021.3), and it remained turned off after the update (under Unity 6). So, it’s always been off. However, the interesting part is that if I turn it on in Unity 6, it “fixes” the interpolation issue.
It seems to state that it was kind of a bug that setting transform positions on interpolated rigidbodies was working, and that this was “fixed” in 2022. Maybe I’m misunderstanding it. But it does seem likely that what I’m seeing is a side effect of the fix, and that I should have never been setting position/rotation on the transform, and I was just getting away with sloppy practices earlier.
We’ll see if the bug reports gets considered a bug, or as a working-as-intended issue.
It does sound like how it was working before wasn’t intentional. With “Auto Sync Transform” turned off, you always have to wait for the next physics update for transform changes to be synced, so the behavior you observe would be the expected behavior.
Supplying the position to Instantiate is the exception, since that allows to set the position before anything is initialized. This distinction exists for regular scripts as well, as Awake/OnEnable run as part of Instantiate. So, if you set the position with Instantiate, those methods will see the position. But if you set it later on the transform like you do, those methods will see the prefab’s original position, because they run before the transform is updated.
I don’t think setting the position like this is wrong per se, you just have to be aware the that objects will be created first and then moved later. And that some systems and scripts might run before and use the original position. Though, instantiating directly with the correct parent/position/rotation is likely more optimal and avoids these considerations.
Regardless of whether this turns out to be a bug now, or a fix to a 2021 bug, I’m just going to sweep through my code and assign the position and rotation in Instantiate(). Good point about how this avoids Awake having the wrong position for the object if that approach isn’t followed.
I also noticed this error. Theoretically, setting the position should be applied in the next physical frame, but in reality, it was not applied. I think this is a bug
I think it’s just that older versions of Unity technically had a bug, where setting the position on the transform would force a sync with the rigidbody. They’ve fixed that now, but if your code depended on that behavior, it will seem like there’s a bug now that wasn’t there before.
In my case, I’ve just gone through to any code I was running where I instantiated then set the position, and instead sent that position into the Instantiate() method. And in a handful of places where that didn’t work (such as activating an object in an object pool), I now check if the object has a rigidbody, and assign the position to it, rather than assigning the position to the transform.
So I’m pretty confident my bug will be closed as “not a bug” in the near future, and I’m fine with that. If anyone really wants their Unity 6 project to keep doing the thing that 2021.3 was doing, they can check Auto Sync Transforms.
I believe the reason is a bug: Instantiating sets the coordinates for the physics system, so the position set in the current frame won’t be refreshed in the next physics frame because it has already been refreshed. This issue only occurs in Interpolate mode, which doesn’t align with common sense.
The cause I can think of is that setting the coordinates during Instantiation causes it to be filtered out by the physics loop, and the instruction is cleared at the end of the physics frame, resulting in the loss of that instruction.