Skip to content

Commit cd79fb0

Browse files
capnslippChuanXin-Unity
authored andcommitted
Fixed RuleTile instantiatedGameObject rotation/scale (Unity-Technologies#158)
* Fixed RuleTile instantiatedGameObject rotation/scale Performed fixes to the math in `RuleTile`'s `StartUp()` method so that instantiated GameObjects match the rotation and scale transformations of sprites (done internally by Unity's SpriteRenderer). The desired intent here is that if you create a RuleTile with 3D GameObjects and 2D Sprites that are visually a flattened version of the 3D art (imagine 3D walls in a maze, and 2D sprites showing the top-down outlines of the walls), they should _always_ match up with each other in the Unity Editor and Player. * Added application of the `Tilemap`'s `orientationMatrix` to the `transform` matrix. This is necessary for GameObjects to to be rotated correctly when using any of the `Tilemap` `orientation` & `Grid` `cellSwizzle` modes beyond the default `.XY` & `.XYZ`. * Now setting the `instantiatedGameObject.transform`'s `localPosition` and `localRotation` instead of using the `Tilemap`'s `LocalToWorld()` method for (world) `position` and setting (world) `rotation` unconverted. This fixes a variety of issues that occur when the `Tilemap` or `Grid`'s GameObject (or any parents) have a non-identity rotation or scale. * Adding the calculated translation from the `orientationMatrix` to the `instantiatedGameObject.transform.localPosition`. This enables the `Tilemap`'s Orientation: Custom: Position values to apply properly. * Also, setting the `instantiatedGameObject.transform`'s `localScale` to the Tilemap's `orientationMatrix.lossyScale`. This ensures that Orientation: Custom: Scale affects the GameObjects.  Also, if a parent Transform has a scale in any axis, the `instantiatedGameObject`'s scale ends up with an inverse value of the parent. Again, the end result of all of the above modifications/fixes are to match what Unity's `SpriteRenderer` does— that's the ground truth I've thoroughly tested these calculations against. * Revised instantiatedGameObject position/rotation/scale to include flipped transform Revised the math in `StartUp()` to decompose the `transform`'s translation, rotation, and scale all separately and apply those each to the `instantiatedGameObject.transform`. This fixes an issue where negative scale values applied to the `transform` in `RuleMatches(…)` used to flip tiles weren't being applied to the `instantiatedGameObject`. This is also more uniform and easier to understand than how I had it before— using `orientationMatrix.MultiplyPoint3x4(…)` for position, `(orientationMatrix * transform)`-derived values for the rotation, and `orientationMatrix.lossyScale` for the scale.  Now the T, R, & S are all `(orientationMatrix * transform)`-derived with just T getting an additional `CellToLocalInterpolated(…)`-based offset. * Fixed instantiatedGameObject to just use the orientationMatrix if no rules match * Added a `bool ruleMatched` flag to check if none of the `m_TilingRules` matched— in that case, we set `gameObjectTranslation`/`Rotation`/`Scale` to just the `orientationMatrix` (instead of `(orientationMatrix * transform)`). * Minor: Copied the `orientationMatrix` into a `orientMatrix` local instead of calling the accessor repeatedly.
1 parent 4eff73f commit cd79fb0

File tree

1 file changed

+27
-8
lines changed

1 file changed

+27
-8
lines changed

Runtime/Tiles/RuleTile/RuleTile.cs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -281,23 +281,42 @@ public override bool StartUp(Vector3Int location, ITilemap tilemap, GameObject i
281281
{
282282
if (instantiatedGameObject != null)
283283
{
284+
Tilemap tmpMap = tilemap.GetComponent<Tilemap>();
285+
Matrix4x4 orientMatrix = tmpMap.orientationMatrix;
286+
284287
var iden = Matrix4x4.identity;
285-
Quaternion gameObjectQuaternion = new Quaternion();
286-
288+
Vector3 gameObjectTranslation = new Vector3();
289+
Quaternion gameObjectRotation = new Quaternion();
290+
Vector3 gameObjectScale = new Vector3();
291+
292+
bool ruleMatched = false;
287293
foreach (TilingRule rule in m_TilingRules)
288294
{
289295
Matrix4x4 transform = iden;
290296
if (RuleMatches(rule, location, tilemap, ref transform))
291297
{
292-
// Converts the tile's rotation matrix to a quaternion to be used by the instantiated Game Object
293-
gameObjectQuaternion = Quaternion.LookRotation(new Vector3(transform.m02, transform.m12, transform.m22), new Vector3(transform.m01, transform.m11, transform.m21));
298+
transform = orientMatrix * transform;
299+
300+
// Converts the tile's translation, rotation, & scale matrix to values to be used by the instantiated Game Object
301+
gameObjectTranslation = new Vector3(transform.m03, transform.m13, transform.m23);
302+
gameObjectRotation = Quaternion.LookRotation(new Vector3(transform.m02, transform.m12, transform.m22), new Vector3(transform.m01, transform.m11, transform.m21));
303+
gameObjectScale = transform.lossyScale;
304+
305+
ruleMatched = true;
294306
break;
295307
}
296308
}
297-
298-
Tilemap tmpMap = tilemap.GetComponent<Tilemap>();
299-
instantiatedGameObject.transform.position = tmpMap.LocalToWorld(tmpMap.CellToLocalInterpolated(location + tmpMap.tileAnchor));
300-
instantiatedGameObject.transform.rotation = gameObjectQuaternion;
309+
if (!ruleMatched)
310+
{
311+
// Fallback to just using the orientMatrix for the translation, rotation, & scale values.
312+
gameObjectTranslation = new Vector3(orientMatrix.m03, orientMatrix.m13, orientMatrix.m23);
313+
gameObjectRotation = Quaternion.LookRotation(new Vector3(orientMatrix.m02, orientMatrix.m12, orientMatrix.m22), new Vector3(orientMatrix.m01, orientMatrix.m11, orientMatrix.m21));
314+
gameObjectScale = orientMatrix.lossyScale;
315+
}
316+
317+
instantiatedGameObject.transform.localPosition = gameObjectTranslation + tmpMap.CellToLocalInterpolated(location + tmpMap.tileAnchor);
318+
instantiatedGameObject.transform.localRotation = gameObjectRotation;
319+
instantiatedGameObject.transform.localScale = gameObjectScale;
301320
}
302321

303322
return true;

0 commit comments

Comments
 (0)