Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Adjust Pivot - without using an empty parent object [Open Source]

Discussion in 'Assets and Asset Store' started by yasirkula, Mar 3, 2018.

  1. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    Hi there,

    I'd like to share a simple editor extension that helps you modify the pivot position/rotation of an object without using an empty parent object.

    Asset Store: https://assetstore.unity.com/packages/tools/utilities/adjust-pivot-112883
    Also available at: https://github.com/yasirkula/UnityAdjustPivot
    Discord: https://discord.gg/UJJt549AaV
    GitHub Sponsors ☕

    screenshot (2).png

    There are two types of pivot adjustments:

    a. If the object does not have a mesh (MeshFilter, to be precise), then the script simply changes the positions and rotations of child objects accordingly

    b. If the object does have a mesh, then the script first creates an instance of the mesh, adjusts the mesh's pivot point by altering its vertices, normals and tangents, and finally changes the positions and rotations of child objects accordingly

    Enjoy!
     
    Last edited: May 31, 2023
  2. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    Now available on Asset Store!
     
  3. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    1,047
    Hi this does not seem to work correctly for me using 2017.1.3f1.Following your simple example the pivot does not end up in the corner.
     
  4. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    Are you sure that the Pivot Mode is set as 'Pivot' rather than 'Center' (see attached image)? Is the pivot point not moving at all? Are there any error messages? It works correctly on Unity 5.6.2f1, Unity 2017.2.0f3 and Unity 2017.3.0p2. I don't have 2017.1 installed, so I wasn't able to test it on that version yet.
     

    Attached Files:

  5. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    1,047
    Ooop - it is set to center. Will try again. I probably missed that step in your instructions. Thanks for the asset!

    Maybe check it and show a warning in the script?
     
  6. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    It will work regardless of the pivot mode, it is just that the effect won't be visible while the pivot mode is set as Center. I may add a warning as suggested, if this becomes a common issue. Thank you for the suggestion.
     
    ibyte likes this.
  7. dan_wipf

    dan_wipf

    Joined:
    Jan 30, 2017
    Posts:
    314
    I'm editing the code for my needs, hope it's ok for you!

    changeant it from an EditorWindow script to a normal script, which can be attached to any Object which holds a collider(right now box only).

    - with the script you can move the pivot point to any point inside the boundaries of the Object. (XYZ axis) but not out side. (well it's for sure possible but at the point necessary for me)

    (not well formatted and performed, but right now it works =) )

    EDIT: Final Simple Code (debug mode)
    Set's automatically the Transform which Script is applied.

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. [ExecuteInEditMode]
    6. [RequireComponent(typeof(MeshFilter))]
    7.  
    8. public class PivotAdjustment : MonoBehaviour {
    9.    
    10.     [System.Serializable] public struct PivotTransform
    11.     {  
    12.         public Transform Pivot_Transform;
    13.         public bool ChangePivot;
    14.     [Range(-1,1f)]public float OffsetX,OffsetY,OffsetZ;
    15. public float OuterOffset;
    16.         [HideInInspector] public Vector3 PivotOffset;
    17.         [HideInInspector] public Vector3[] vertices;
    18.         [HideInInspector] public Vector3[] normals;
    19.         [HideInInspector] public Vector4[] tangents;
    20.     [HideInInspector] public Vector3[] OriginalVertices;
    21.         [HideInInspector] public Quaternion OriginalRotation;
    22.     [HideInInspector] public Mesh mesh;
    23.     }
    24. public PivotTransform PivotTransform_0 = new PivotTransform();
    25.  
    26. #region [Executional Part]
    27. void Start(){
    28.         PivotTransform_0 = PivotTransformSetup(PivotTransform_0);
    29. }
    30.    
    31. public void Update () {
    32.  
    33. if(PivotTransform_0.ChangePivot){
    34.         PivotTransform_0 = CalcMinMaxOffset(PivotTransform_0);
    35. PivotChanger(PivotTransform_0);
    36. PivotTransform_0.ChangePivot = false;
    37. }
    38. }
    39. #endregion
    40.  
    41. #region [Pivot Calculations]
    42. public void PivotChanger(PivotTransform p){
    43.  
    44.         //reposition
    45. for(int i = 0; i< p.vertices.Length; i++){
    46. p.vertices[i] = p.OriginalVertices[i] + p.PivotOffset;
    47. }
    48.         //rotation
    49. Quaternion PivotRotation = Quaternion.Inverse(p.OriginalRotation);
    50. for( int i = 0; i < p.vertices.Length; i++ )
    51. {
    52. p.vertices[i] = PivotRotation * p.vertices[i];
    53. p.normals[i] = PivotRotation * p.normals[i];
    54.  
    55. Vector3 tangentDir = PivotRotation * p.tangents[i];
    56. p.tangents[i] = new Vector4( tangentDir.x, tangentDir.y, tangentDir.z, p.tangents[i].w );
    57. }
    58.  
    59.         //recalculate and apply
    60.  
    61. p.mesh.vertices = p.vertices;
    62. p.mesh.normals = p.normals;
    63. p.mesh.tangents = p.tangents;
    64.  
    65. p.mesh.RecalculateBounds();
    66. if(p.Pivot_Transform.GetComponent<Collider>() != null){
    67. RecalculateColliderBounds(p.mesh.bounds,p);}
    68. }
    69.     PivotTransform PivotTransformSetup(PivotTransform p){
    70.         //Debug
    71.         p.Pivot_Transform = transform;
    72.         //Debug
    73. p.mesh = p.Pivot_Transform.GetComponent<MeshFilter>().sharedMesh;
    74.  
    75. p.OriginalVertices = p.mesh.vertices;
    76. p.vertices = p.mesh.vertices;
    77. p.normals = p.mesh.normals;
    78. p.tangents = p.mesh.tangents;
    79.  
    80. p.OriginalRotation = p.Pivot_Transform.localRotation;
    81. Vector3 OriginaPosition = p.Pivot_Transform.position;
    82. p.Pivot_Transform.position = Vector3.zero;
    83.  
    84.         //center pivot to model
    85.         p.PivotOffset = transform.position - p.Pivot_Transform.GetComponent<Renderer>().bounds.center;
    86. PivotChanger(p);
    87. p.Pivot_Transform.position = OriginaPosition;
    88. p.OriginalVertices = p.mesh.vertices;
    89.         return p;
    90.     }
    91.     PivotTransform CalcMinMaxOffset(PivotTransform p){
    92. Vector3 pvo3 = new Vector3();
    93. p.OuterOffset = Mathf.Clamp(p.OuterOffset,1,p.OuterOffset);
    94.         pvo3.x = Mathf.Lerp(p.mesh.bounds.size.x * p.OuterOffset,-p.mesh.bounds.size.x * p.OuterOffset,(p.OffsetX + 1) / 2) / 2;
    95. pvo3.y = Mathf.Lerp(p.mesh.bounds.size.y * p.OuterOffset,-p.mesh.bounds.size.y * p.OuterOffset,(p.OffsetY + 1) / 2) / 2;
    96.         pvo3.z = Mathf.Lerp(p.mesh.bounds.size.z * p.OuterOffset,-p.mesh.bounds.size.z * p.OuterOffset,(p.OffsetZ + 1) / 2) / 2;
    97. p.PivotOffset = pvo3;
    98. return p;
    99. }
    100. void RecalculateColliderBounds(Bounds b,PivotTransform p){
    101. Collider col = p.Pivot_Transform.GetComponent<Collider>();
    102. if(col.GetType() == typeof(BoxCollider)){
    103. p.Pivot_Transform.GetComponent<BoxCollider>().center = b.center;
    104. }
    105. if(col.GetType() == typeof(SphereCollider)){
    106. p.Pivot_Transform.GetComponent<SphereCollider>().center = b.center;
    107. }
    108. if(col.GetType() == typeof(CapsuleCollider)){
    109.             p.Pivot_Transform.GetComponent<CapsuleCollider>().center = b.center;
    110. }
    111. }
    112. #endregion
    113. }
    114.  
    115.  
    116.  
    117.  
     
    Last edited: Jan 9, 2019
    yasirkula likes this.
  8. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    It's totally fine for me. In Update method, I'd recommend you to cache the value of GetComponent<BoxCollider>().center for better performance.
     
    dan_wipf likes this.
  9. dan_wipf

    dan_wipf

    Joined:
    Jan 30, 2017
    Posts:
    314
    @yasirkula yeah I know. I'm developing a fence building system(open source). where every post and paling is acceptable =) so I'm glad I can use your code.

    |---|---|---|
     
  10. dan_wipf

    dan_wipf

    Joined:
    Jan 30, 2017
    Posts:
    314
    Ok I've re done now the code and it works perfectly, off to fence placing now :cool: thanks again for providing this!
     
    yasirkula likes this.
  11. dan_wipf

    dan_wipf

    Joined:
    Jan 30, 2017
    Posts:
    314

    Attached Files:

    yasirkula likes this.
  12. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    Congratulations :)
     
    dan_wipf likes this.
  13. Xulain-SineSpace

    Xulain-SineSpace

    Joined:
    Oct 14, 2017
    Posts:
    26
    Doesnt seem to work in 2018.4.30f1. Its moves the pivot point to the child but does not set the rotation to rotation of the child
     
  14. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    Could you reproduce the issue using simple Cube objects? If so, please tell me the parent-child hierachy and position and rotation values of those cube objects so that I can reproduce the issue.
     
  15. Moroh209

    Moroh209

    Joined:
    Apr 12, 2022
    Posts:
    5
    Hi there! Is there a way to change the Pivot with a Script?
     
  16. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    Hi! If this is about runtime support, I'm afraid AdjustPivot doesn't provide a solution for this but you can check out this topic (haven't actually tested the code myself): https://github.com/yasirkula/UnityAdjustPivot/issues/2. For editor scripting, you can make the SetParentPivot and SaveMesh functions public and call them like
    GetWindow<AdjustPivot>().SetParentPivot(...)
    .
     
  17. xiaojianh6

    xiaojianh6

    Joined:
    Jan 20, 2021
    Posts:
    25
    Multiple materials not supported
     
  18. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    Hmm, after modifying the pivot, submeshes are combined into a single mesh if I understand correctly?
     
  19. xiaojianh6

    xiaojianh6

    Joined:
    Jan 20, 2021
    Posts:
    25
    upload_2023-5-17_5-3-16.png upload_2023-5-17_5-3-39.png

    I need to keep its material
     
  20. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,865
    Can you send this FBX to me via private message? I've tested the plugin with a mesh that has 2 materials and the materials remained intact.