diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce7df870c..d11382035 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -246,6 +246,7 @@
* Now providing `BeforeApply` update callbacks at all skeleton animation components (`SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`).
* Added `BoundingBoxFollowerGraphic` component. This class is a counterpart of `BoundingBoxFollower` that can be used with `SkeletonGraphic`.
* Added Inspector context menu functions `SkeletonRenderer - Add all BoundingBoxFollower GameObjects` and `SkeletonGraphic - Add all BoundingBoxFollowerGraphic GameObjects` that automatically generate bounding box follower GameObjects for every `BoundingBoxAttachment` for all skins of a skeleton.
+ * `GetRemappedClone()` now provides an additional parameter `pivotShiftsMeshUVCoords` for `MeshAttachment` to prevent uv shifts at a non-central Sprite pivot. This parameter defaults to `true` to maintain previous behaviour.
* **Changes of default values**
* `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`.
diff --git a/spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs b/spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs
index bea5f22e9..b5dba28e6 100644
--- a/spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs
+++ b/spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs
@@ -94,13 +94,13 @@ namespace Spine.Unity.Examples {
// Let's do this for the visor.
int visorSlotIndex = skeleton.FindSlotIndex(visorSlot); // You can access GetAttachment and SetAttachment via string, but caching the slotIndex is faster.
Attachment templateAttachment = templateSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
- Attachment newAttachment = templateAttachment.GetRemappedClone(visorSprite, sourceMaterial); // STEP 1.2 - 1.3
+ Attachment newAttachment = templateAttachment.GetRemappedClone(visorSprite, sourceMaterial, pivotShiftsMeshUVCoords : false); // STEP 1.2 - 1.3
customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
// And now for the gun.
int gunSlotIndex = skeleton.FindSlotIndex(gunSlot);
Attachment templateGun = templateSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
- Attachment newGun = templateGun.GetRemappedClone(gunSprite, sourceMaterial); // STEP 1.2 - 1.3
+ Attachment newGun = templateGun.GetRemappedClone(gunSprite, sourceMaterial, pivotShiftsMeshUVCoords: false); // STEP 1.2 - 1.3
if (newGun != null) customSkin.SetAttachment(gunSlotIndex, gunKey, newGun); // STEP 1.4
// customSkin.RemoveAttachment(gunSlotIndex, gunKey); // To remove an item.
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentCloneExtensions.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentCloneExtensions.cs
index ece990f36..52c4ba1ad 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentCloneExtensions.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentCloneExtensions.cs
@@ -83,8 +83,18 @@ namespace Spine.Unity.AttachmentTools {
/// If true, a premultiply alpha clone of the original texture will be created.
/// If true MeshAttachments will be cloned as linked meshes and will inherit animation from the original attachment.
/// If true the size of the original attachment will be followed, instead of using the Sprite size.
- public static Attachment GetRemappedClone (this Attachment o, Sprite sprite, Material sourceMaterial, bool premultiplyAlpha = true, bool cloneMeshAsLinked = true, bool useOriginalRegionSize = false) {
+ /// If true and the original Attachment is a MeshAttachment, then
+ /// a non-central sprite pivot will shift uv coords in the opposite direction. Vertices will not be offset in
+ /// any case when the original Attachment is a MeshAttachment.
+ public static Attachment GetRemappedClone (this Attachment o, Sprite sprite, Material sourceMaterial,
+ bool premultiplyAlpha = true, bool cloneMeshAsLinked = true, bool useOriginalRegionSize = false,
+ bool pivotShiftsMeshUVCoords = true) {
var atlasRegion = premultiplyAlpha ? sprite.ToAtlasRegionPMAClone(sourceMaterial) : sprite.ToAtlasRegion(new Material(sourceMaterial) { mainTexture = sprite.texture } );
+ if (!pivotShiftsMeshUVCoords && o is MeshAttachment) {
+ // prevent non-central sprite pivot setting offsetX/Y and shifting uv coords out of mesh bounds
+ atlasRegion.offsetX = 0;
+ atlasRegion.offsetY = 0;
+ }
return o.GetRemappedClone(atlasRegion, cloneMeshAsLinked, useOriginalRegionSize, 1f/sprite.pixelsPerUnit);
}