Search Unity

Adjust click-position on a sprite with BoxCollider2D

Discussion in 'Scripting' started by pKallv, Mar 31, 2014.

  1. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    I have a number of sprites/prefabs on the screen at the same time.

    When i click towards to the edge on the sprite it jumps, under the mouse, to the center of the sprite. Is there anyone that knows a good way of smoothing this behavior so when i click somewhere on the sprite i can adjust the position so i do not get the "jump" and can drag the sprite from were i initially clicked?

    I guess this has something to do with the "center" property. I tested but have not been able to fix it.
     
  2. cherub

    cherub

    Joined:
    Apr 26, 2006
    Posts:
    493
  3. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    Thanks, could you please point out were and how it solves the problem with were i click on a sprite and BoxCollider2D center parameter so it adjust that? Effect should be that the sprite does not jump when click outside of the BoxCollider2D center (0, 0).
     
  4. Bivrost

    Bivrost

    Joined:
    Mar 26, 2014
    Posts:
    80
    Simply use the delta between the hit position and the object's center. And as long as the mouse button is down, the object's new position is the mouse position in world space minus the delta.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class ObjectPicker : MonoBehaviour
    6. {
    7.     void Update()
    8.     {
    9.         if ( Input.GetMouseButtonDown( 0 ) )
    10.         {
    11.             Vector3 worldPoint = Camera.main.ScreenToWorldPoint( Input.mousePosition );
    12.             RaycastHit2D hit = Physics2D.Raycast( worldPoint, Vector2.zero );
    13.  
    14.             if ( hit.collider != null )
    15.             {
    16.                 Vector2 position = hit.transform.position;
    17.                 StartCoroutine( DragObject( hit.transform, hit.point - position ) );
    18.             }
    19.         }
    20.     }
    21.  
    22.     IEnumerator DragObject( Transform pickedTransform, Vector2 delta )
    23.     {
    24.         while ( Input.GetMouseButton( 0 ) )
    25.         {
    26.             Vector3 worldPoint = Camera.main.ScreenToWorldPoint( Input.mousePosition );
    27.  
    28.             Vector3 position = pickedTransform.position;
    29.             position.x = worldPoint.x - delta.x;
    30.             position.y = worldPoint.y - delta.y;
    31.             pickedTransform.position = position;
    32.  
    33.             yield return null;
    34.         }
    35.     }
    36. }
    37.  
     
    Last edited: Apr 17, 2014
  5. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    Bivrost, I am afraid that it does not work. If i click on the corner of one card it adjust immediately, with a jump, to the center of the card. I guess that is BoxCollider2D center property (0, 0).
     
  6. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    I was able to change the BoxCollider2D center property and found out that it had no effect on how the sprite is selected.

    How can i make it so if i click in the corner of the sprite that is where the select will stay while i drag the sprite?
     
  7. Bivrost

    Bivrost

    Joined:
    Mar 26, 2014
    Posts:
    80
    Here's what I just cobbled together: Web Player

    Is this the effect you are looking for?
     
  8. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    Bivrost, exactly that :)
     
  9. Bivrost

    Bivrost

    Joined:
    Mar 26, 2014
    Posts:
    80
    Last edited: Apr 17, 2014
  10. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    Bivrost, ohh just realized that it was my dragScript that prohibited your script to work. This is absolutely super. A BIG thank you!
     
  11. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
  12. Bivrost

    Bivrost

    Joined:
    Mar 26, 2014
    Posts:
    80
    Maybe it's not the most beautiful or most efficient solution but you could just reassign z-positions and sorting orders after the player picked a card. Which really shouldn't be a problem at all because you only have a few cards you need to iterate through and not thousands of game objects.

    Codewise this could look like this:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class ObjectPicker : MonoBehaviour
    7. {
    8.     public Transform[] m_objectsBackToFront;
    9.  
    10.     private class Item
    11.     {
    12.         public Transform transform { get; set; }
    13.         public SpriteRenderer renderer { get; set; }
    14.     }
    15.  
    16.     private List< Item > m_items;
    17.  
    18.     void Awake()
    19.     {
    20.         int count = m_objectsBackToFront.Length;
    21.         m_items = new List< Item >( count );
    22.  
    23.         for ( int i = 0; i < count; ++i )
    24.         {
    25.             Item item = new Item();
    26.             item.transform = m_objectsBackToFront[ i ];
    27.             item.renderer = m_objectsBackToFront[ i ].GetComponent< SpriteRenderer >();
    28.             m_items.Add( item );
    29.  
    30.             Vector3 position = item.transform.position;
    31.             position.z = count - i - 1;
    32.             item.transform.position = position;
    33.  
    34.             item.renderer.sortingOrder = i;
    35.         }
    36.     }
    37.  
    38.     void Update()
    39.     {
    40.         if ( Input.GetMouseButtonDown( 0 ) )
    41.         {
    42.             Vector3 worldPoint = Camera.main.ScreenToWorldPoint( Input.mousePosition );
    43.  
    44.             worldPoint.z = Camera.main.transform.position.z;
    45.             Ray ray = new Ray( worldPoint, new Vector3( 0, 0, 1 ) );
    46.             RaycastHit2D hit = Physics2D.GetRayIntersection( ray );
    47.  
    48.             if ( hit.collider != null )
    49.             {
    50.                 Transform transform = hit.transform;
    51.                 PutInFront( transform );
    52.                 Vector2 position = transform.position;
    53.                 StartCoroutine( DragObject( transform, hit.point - position ) );
    54.             }
    55.         }
    56.     }
    57.  
    58.     void PutInFront( Transform transform )
    59.     {
    60.         int index = -1;
    61.         int count = m_items.Count;
    62.         for ( int i = 0; i < count; ++i )
    63.         {
    64.             if ( m_items[ i ].transform == transform )
    65.             {
    66.                 index = i;
    67.                 break;
    68.             }
    69.         }
    70.  
    71.         if ( index >= 0 )
    72.         {
    73.             Item item = m_items[ index ];
    74.             m_items.RemoveAt( index );
    75.             m_items.Add( item );
    76.         }
    77.  
    78.         for ( int i = 0; i < count; ++i )
    79.         {
    80.             Item item = m_items[ i ];
    81.             Vector3 position = item.transform.position;
    82.             position.z = count - i - 1;
    83.             item.transform.position = position;
    84.  
    85.             item.renderer.sortingOrder = i;
    86.         }
    87.     }
    88.  
    89.     IEnumerator DragObject( Transform pickedTransform, Vector2 delta )
    90.     {
    91.         while ( Input.GetMouseButton( 0 ) )
    92.         {
    93.             Vector3 worldPoint = Camera.main.ScreenToWorldPoint( Input.mousePosition );
    94.             Vector3 position = pickedTransform.position;
    95.             position.x = worldPoint.x - delta.x;
    96.             position.y = worldPoint.y - delta.y;
    97.             pickedTransform.position = position;
    98.             yield return null;
    99.         }
    100.     }
    101. }
    102.  
     
  13. Bivrost

    Bivrost

    Joined:
    Mar 26, 2014
    Posts:
    80
  14. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    Bivrost, a BIG thank you again for that. I decided to try to rework your latest code based on the code i have in my Objective-C version and got it to work with the code below. Great C# learning for me.I think the combination of the z-property and the sortingOrder property confused me as the sprites, initially, was stacked in the wrong order to what i expected.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class CSMainScript : MonoBehaviour {
    6.  
    7.     public static List<string> cardDeckList = new List<string> {
    8.         "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10",};
    9.     int nrOfCards;
    10.     GameObject aGameObject;
    11.     public float addIT = 0.1f;
    12.     float ff = 0f;
    13.  
    14.     // Use this for initialization
    15.     void Start () {
    16.  
    17.         nrOfCards = cardDeckList.Count;
    18.  
    19.         for (int loop = 0; loop < nrOfCards; loop++) {
    20.             aGameObject = Resources.Load(cardDeckList[loop]) as GameObject;
    21.             aGameObject.transform.position =  new Vector3(0f + ff, 0f + ff, 5f);
    22.             aGameObject.renderer.sortingOrder = loop;
    23.  
    24.             Instantiate(aGameObject);
    25.  
    26.             ff = ff + addIT;
    27.  
    28.         }
    29.    
    30.     }
    31.  
    32.     void Update () {
    33.  
    34.         if(Input.GetMouseButtonDown(0)) {
    35.             RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
    36.            
    37.            
    38.            
    39.             if(hit.collider != null) {
    40. //              print ("Tag: " + hit.collider.tag + " Name: " + hit.collider.name);
    41.  
    42.                 //=================================================================//
    43.                 PutCardOnTop(hit.transform);
    44.                 //=================================================================//
    45.  
    46.                 //=================================================================//
    47.                 Vector2 position = hit.transform.position;
    48.                 StartCoroutine( DragObject( hit.transform, hit.point - position ) );
    49.                 //=================================================================//
    50.             }
    51.         }
    52.    
    53.     }
    54.  
    55.  
    56.     void PutCardOnTop(Transform pickedTransform) {
    57.  
    58.         for (int listLoop = 0; listLoop < nrOfCards; listLoop++) {
    59.                
    60.             if(cardDeckList[listLoop] == pickedTransform.tag) {
    61.  
    62.                 cardDeckList.RemoveAt(listLoop);
    63.                 cardDeckList.Add(pickedTransform.tag);
    64.                 break;
    65.  
    66.             }
    67.  
    68.         }
    69.  
    70.         for (int listLoop = 0; listLoop < nrOfCards; listLoop++) {
    71.  
    72.             aGameObject = GameObject.FindWithTag (cardDeckList[listLoop]);
    73.             aGameObject.transform.renderer.sortingOrder = listLoop;
    74.                
    75.         }
    76.  
    77.     }
    78.  
    79.  
    80.     IEnumerator DragObject( Transform pickedTransform, Vector2 delta )
    81.     {
    82.         while ( Input.GetMouseButton( 0 ) )
    83.         {
    84.             Vector3 worldPoint = Camera.main.ScreenToWorldPoint( Input.mousePosition );
    85.            
    86.             Vector3 position = pickedTransform.position;
    87.             position.x = worldPoint.x - delta.x;
    88.             position.y = worldPoint.y - delta.y;
    89.             pickedTransform.position = position;
    90.            
    91.             yield return null;
    92.         }
    93.     }
    94. }
    95.  
     
    Last edited: Apr 20, 2014