Search Issue Tracker
By Design
Votes
0
Found in
2017.4.0f1
2018.2.20f1
2018.3.0a1
2019.1.0a1
2019.2.0a1
Issue ID
1117255
Regression
No
Sprite.OverridePhysicsShape raises an error when using it in Editor Mode
Repro Steps:
1. Open attached "UnityBug.zip" project
2. Press on the "TrollRuntSprites" Spritesheet in the Project view
3. In the Inspector context menu, select "Set Physics Shape For All Sprites"
4. Observe the Console error tab
Expected Behavior: All the Sprite physics in the Spritesheet are overridden and set to be identical to the first sprite
Actual Behavior: The error is raised that the use of Sprite.OverridePhysicsShape is not allowed
Reproducible with: 2017.4.18f1, 2018.3.2f1, 2019.1.0a14, 2019.2.0a1
-
ohin
Jan 17, 2021 18:30
I also wanted to set physics shape from the script when importing spritesheet. Ended up here. Using the code from resolution works, however I don't like the usage of reflection.
This should really be reconsidered. -
SunnysideGames
Aug 19, 2020 07:44
Ok so thanks to the code in the resolution note I managed to put together a script to easily copy / paste sprite physics shape to multiple selected sprites:
Screenshot and code:
https://forum.unity.com/threads/same-custom-physic-shape.761795/#post-6218889 -
Yemnefer
Jul 31, 2020 20:49
You should use the AssetDatabase.
string path = AssetDatabase.GetAssetPath (Selection.activeObject);
Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath (path)
.OfType<Sprite> ().ToArray ();
if (sprites.Length == 0)
return;for textures not only inside the Resources folder.
-
ExNinja
Oct 17, 2019 15:39
These lines do not work in version 2019.2:
Sprite[] sprites = (Selection.activeObject as Texture2D).GetSprites();
if (sprites.IsNullOrEmpty()) {
return;
}They can be replaced by these lines IF the selection is in the Resources folder:
Texture2D tex = Selection.activeObject as Texture2D;
Sprite[] sprites = Resources.LoadAll<Sprite>(tex.name);
if (sprites.Length == 0) return; -
ExNinja
Oct 17, 2019 15:18
Regardless of whether this is by design, it is still very problematic that it does not work. Please consider re-opening this bug so that we can modify physics shapes of sprites in code.
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- Articulation Body with 'Revolute' Joint Type has erratic behavior when Upper Limit is set to above 360
- WebGL Player fails to render Scene when Terrain with Detail Mesh is added and WebGPU Graphics API is used
- Inconsistent errors are logged when different types are passed into the Query "Q<>" method in UIToolkit and the ancestor VisualElement is null
- Crash on GetMaterialPropertyByIndex when opening a specific Scene
- Discrepancies in the styling are present when using a TSS file instead of a USS file in custom EditorWindow
Resolution Note:
Sprite.OverridePhysicsShape can only be used in Edit Mode when importing the Sprite, for example when post processing a Sprite through AssetPostprocessor.OnPostprocessSprites(Texture2D, Sprite[]). The changes done in Sprite.OverridePhysicsShape only update the physics shape for the Sprite asset and will be lost when the Texture Importer is reimported and regenerates the Sprite assets.
Instead, you will need to update the actual physics shape inside the Texture Importer in order to have the behavior you want. Here is an example script which can do this:
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Experimental.U2D;
using UnityEngine;
public class SetPhysicsShapeForAllSpritesTool : Editor {
private Vector2Int pivot;
private bool normalized;
[MenuItem("CONTEXT/TextureImporter/Set Physics Shape For All Sprites")]
public static void ShowSetPhysicsShapeForAllSpritesWindow() {
// Overwrite physics shape for each sprite in the spritesheet
Sprite[] sprites = (Selection.activeObject as Texture2D).GetSprites();
if (sprites.IsNullOrEmpty()) {
return;
}
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
var spritePhysicsShapeImporter = new SpritePhysicsShapeImporter(importer);
List<Vector2[]> copyShapes = spritePhysicsShapeImporter.GetPhysicsShape(0);
for (int i = 0; i < sprites.Length; ++i) {
spritePhysicsShapeImporter.SetPhysicsShape(i, copyShapes);
}
// Save the changes made to the importer and refresh the database
spritePhysicsShapeImporter.Save();
}
}
public class SpritePhysicsShapeImporter
{
private TextureImporter m_TI;
private SerializedObject m_TISerialized;
public SpritePhysicsShapeImporter(TextureImporter ti)
{
m_TI = ti;
m_TISerialized = new SerializedObject(m_TI);
}
public List<Vector2[]> GetPhysicsShape(int index)
{
var physicsShapeProperty = GetPhysicsShapeProperty(index);
var physicsShape = new List<Vector2[]>();
for (int j = 0; j < physicsShapeProperty.arraySize; ++j)
{
SerializedProperty physicsShapePathSP = physicsShapeProperty.GetArrayElementAtIndex(j);
var o = new Vector2[physicsShapePathSP.arraySize];
for (int k = 0; k < physicsShapePathSP.arraySize; ++k)
{
o[k] = physicsShapePathSP.GetArrayElementAtIndex(k).vector2Value;
}
physicsShape.Add(o);
}
return physicsShape;
}
public void SetPhysicsShape(int index, List<Vector2[]> data)
{
var physicsShapeProperty = GetPhysicsShapeProperty(index);
physicsShapeProperty.ClearArray();
for (int j = 0; j < data.Count; ++j)
{
physicsShapeProperty.InsertArrayElementAtIndex(j);
var o = data[j];
SerializedProperty outlinePathSP = physicsShapeProperty.GetArrayElementAtIndex(j);
outlinePathSP.ClearArray();
for (int k = 0; k < o.Length; ++k)
{
outlinePathSP.InsertArrayElementAtIndex(k);
outlinePathSP.GetArrayElementAtIndex(k).vector2Value = o[k];
}
}
m_TISerialized.ApplyModifiedPropertiesWithoutUndo();
}
public void Save()
{
AssetDatabase.ForceReserializeAssets(new string[] { m_TI.assetPath }, ForceReserializeAssetsOptions.ReserializeMetadata);
m_TI.SaveAndReimport();
}
private SerializedProperty GetPhysicsShapeProperty(int index)
{
if (m_TI.spriteImportMode == SpriteImportMode.Multiple)
{
var spriteSheetSP = m_TISerialized.FindProperty("m_SpriteSheet.m_Sprites");
if (index < spriteSheetSP.arraySize)
{
var element = spriteSheetSP.GetArrayElementAtIndex(index);
return element.FindPropertyRelative("m_PhysicsShape");
}
}
return m_TISerialized.FindProperty("m_SpriteSheet.m_PhysicsShape");
}
}