Search Unity

Get a sprite like it is displayed on the screen

Discussion in '2D' started by RhenaudTheLukark, Jul 26, 2016.

  1. RhenaudTheLukark

    RhenaudTheLukark

    Joined:
    Mar 11, 2016
    Posts:
    16
    Hey guys ! I need your help !

    I'm making some sort of Pixel-Perfect collision system and I wondered if this is possible to get a sprite from an Image object like it is displayed on the screen.

    I tried to get the mainTexture of the Image object, but it returns the sprite itself, with no rotation and such...

    It may looks weird, I know, but I really need that to make my PP collision :/

    Right now, I get the original sprite : for example, I'll get this :

    http://image.noelshack.com/fichiers/2016/30/1469492604-cross-straght.png

    But I need to get like it's displayer, so if the sprite has a rotation of 45°, I need to get it like this :

    http://image.noelshack.com/fichiers/2016/30/1469492604-cross-45.png

    Is there a way to do such a thing ? Thanks ^^
     
  2. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,445
    Hi,

    can grab pixels from screen, but its maybe too slow..
    https://docs.unity3d.com/ScriptReference/Texture2D.ReadPixels.html

    you could rotate the texture with script (there's few examples in forum),
    but that's not so fast either if large textures, although you only need to rotate when sprite rotates, not every frame..

    i also did pixel perfect collisions for a small game, but it didn't have free rotations,
    so would be interesting to know how to do that..
     
  3. RhenaudTheLukark

    RhenaudTheLukark

    Joined:
    Mar 11, 2016
    Posts:
    16
    The thing is that this will not be the only item on the screen that uses Pixel-Perfect, plus there are UI elements and such that I don't need...

    I really need the sprite, and only the sprite :/
     
  4. BIG-BUG

    BIG-BUG

    Joined:
    Mar 29, 2009
    Posts:
    457
    What exactly are you trying to achieve?
    For simple shapes like in your example sprite you could easily use colliders for perfect collision.
    If you want to go the ReadPixel route you just could calculate the rotation and offset by your own.
     
  5. RhenaudTheLukark

    RhenaudTheLukark

    Joined:
    Mar 11, 2016
    Posts:
    16
    This is just an example sprite : later, I'd be able to use all possible shapes.

    I'll just show you the REAL thing : http://image.noelshack.com/fichiers/2016/30/1469790831-screenshot-2.png

    The purple square is the cross' rect, the black square is the heart's square.
    What I need here is to get the cross' texture, and only the cross'.
    I want to get it to make a Pixel-Perfect collision system : right now, it works, but I have a problem : I can't know which cross object is touching me.

    In this example : http://image.noelshack.com/fichiers/2016/30/1469791162-screenshot-3.png

    The engine can't know which cross is actually hitting the heart, as I'm already using a ReadPixels.

    Here is my code, if you're curious :

    Code (csharp):
    1. public virtual bool HitTestPP() {
    2.   UpdateHitRect(); //updates the rect of the bullet and the player
    3.   if (selfAbs.Overlaps(PlayerController.instance.playerAbs) && !Collision) {
    4.     StartCoroutine(ICheckCollision());
    5.   } else if (Collision) {
    6.     Collision = false;
    7.     return true;
    8.   }
    9.   return false;
    10. }
    11.  
    12. IEnumerator ICheckCollision() {
    13.   Rect rectPlayer = PlayerController.instance.playerAbs; //The heart's rect
    14.   Texture2D tex = new Texture2D(Mathf.FloorToInt(rectPlayer.width) - 2, Mathf.FloorToInt(rectPlayer.height) - 2, TextureFormat.RGB24, false);
    15.   Color colorPlayer = GameObject.Find("player").GetComponent<Image>().color;
    16.   yield return new WaitForEndOfFrame();
    17.   tex.ReadPixels(new Rect(rectPlayer.x + rectPlayer.width / 2 + 2, rectPlayer.y + rectPlayer.height / 2 - 1, tex.width, tex.height), 0, 0);
    18.   Color[] pixs = tex.GetPixels();
    19.   for (int i = 0; i < pixs.Length; i++)
    20.     if (pixs[i] != colorPlayer && i != 0) {
    21.       Collision = true;
    22.       yield break;
    23.     }
    24. }


    I'm checking the color of every pixel in the created image, to see if the color of the screen is the same as the player's.
    If it is, there is no collision, else there is a collision.

    My only problem is that I can't know what projectile is touching the player, but if someone know a workaround about it...

    This function is laucnhed when the player's rect overlaps the cross' rect, once per frame. Each cross launches this function.
     

    Attached Files:

    Last edited: Jul 29, 2016
  6. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    Just approximate your shapes with as many colliders as you need to. I don't think this is something that would really benefit from being 100% pixel perfect. Most likely you are wasting your time for something that most players won't notice. They'll notice if a collider is slightly bigger than the pixel representation of the object and they get hit "unfairly", but when the collider is a tiny bit smaller and they don't get hit when the shapes actually visually overlapped for 1 pixel, I think they won't notice and just think it was a close call.
     
  7. RhenaudTheLukark

    RhenaudTheLukark

    Joined:
    Mar 11, 2016
    Posts:
    16
    The thing is that these bullets are generated automatically...so if you have a way to create colliders out of a sprite automatically I'll take it, otherwise I'm stuck with this
     
  8. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    I don't yet fully understand your usecase, but can't you create prefabs for your objects and then make your script choose from the prefabs instead of generating them from scratch?
    It's very possible there also is a way to generate coliders from sprites, but I'm not familiar with such techniques.
     
  9. RhenaudTheLukark

    RhenaudTheLukark

    Joined:
    Mar 11, 2016
    Posts:
    16
    Hm. The thing is that I'm creating an engine that permits people to create their own Undertale-like battles with Lua scripts.

    That is to say that the users will be able to use their own sprites and such, so I can't make any prefab about that.

    The "collision zone" is created automatically with the sprite's rect.