Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Sprite pixel perfect hitbox

Discussion in 'Project Tiny' started by Exsert, Apr 30, 2019.

  1. Exsert

    Exsert

    Joined:
    Oct 22, 2015
    Posts:
    42
    Hello all.

    I'm currently playing around with a project that can be loaded in browser on a website, It's an Isometric 2D Pixel game. I have gotten fairly far in normal unity but wanted to try this html5 project to see how well it would work.

    I am currently working on making the floor tiles have a hover state on them. But I am having trouble with reading much information on how hitboxes or any kind of sprite to mouse interaction would work?

    I was trying to implement Pixel perfect with Sprite2DRendererHitBox2D But the documentation didn't really help me get anywhere (I'm not the best at just reading and understanding unfortunately) Also It seems that the Image2D documentation has gone? https://docs.unity3d.com/Packages/c...nual/manual-module-core2d.md#image2dalphamask

    Any information on this would be greatly appreciated.

    upload_2019-4-30_23-44-1.png
    (Example of what a sprite looks like in Tiny Project)

    upload_2019-4-30_23-47-3.png
    (Example of my Unity collider)

    Any help would be greatly appreciated!
     
    Last edited: May 1, 2019
  2. Rupture13

    Rupture13

    Joined:
    Apr 12, 2016
    Posts:
    131
    Yes, the documentation on this part isn't worth much.
    It says this:
    But it doesn't point in a direction of how you would add the Image2DAlphaMask component to the image entity.

    I did however figure it out earlier in this thread.
    The code snippet from that thread:
    Code (CSharp):
    1. this.world.forEach([ut.Entity, Scratcher, ut.Core2D.Sprite2DRenderer], (entity, scratcher, renderer) => {
    2.  
    3.     let trueSource = this.world.getComponentData(renderer.sprite, ut.Core2D.Sprite2D).image;
    4.     if (!this.world.hasComponent(trueSource, ut.Core2D.Image2DAlphaMask)) {
    5.  
    6.         let loader = this.world.getOrAddComponentData(trueSource, ut.Core2D.Image2DLoadFromFile);
    7.         loader.imageFile = UT_ASSETS[this.world.getComponentData(trueSource, ut.Core2D.Image2D).sourceName.substring(9)];
    8.         this.world.setComponentData(trueSource, loader);
    9.  
    10.         let alphaMask = this.world.getOrAddComponentData(trueSource, ut.Core2D.Image2DAlphaMask);
    11.         alphaMask.threshold = 0.5;
    12.         this.world.setComponentData(trueSource, alphaMask);
    13.     }
    14. });
     
    reallyhexln and Exsert like this.
  3. Rupture13

    Rupture13

    Joined:
    Apr 12, 2016
    Posts:
    131
    Also don't forget to add something to the system to make sure the code to add the AlphaMask isn't executed every frame.
     
  4. Exsert

    Exsert

    Joined:
    Oct 22, 2015
    Posts:
    42
    Thanks for the response :) great work with getting it working.

    I had read over your thread prior to me posting but it's very difficult to test if it's implemented correctly.

    I'm still trying to get used to how to program quickly in this new ECS system so I didn't try to do the same thing last night as I had hoped the engine would just pull in the sprite as a default (it did not).

    How did you test the implementation of this ?

    Also, I'll be adding the alpha masks on instantiation of the entity group, so should only be execute once.

    The way I'm looking at doing the tile interaction is to have a system that will handle all mouse interactions on every Update. It will do a mouse to world pos then a hitbox2d hittest. Which I think only returns an entity ID but I assume I can get the entity from this ID?


    Unfortunately I'm at work at the moment so can only tinker for like an hour a day during the week, so will play around tonight.
     
  5. Rupture13

    Rupture13

    Joined:
    Apr 12, 2016
    Posts:
    131
    Two ways of testing this that I know of:
    • MousePosition hittest:
      This is the one you mentioned.
      It performs a hitTest on the current mousePosition and returns an entity.
      Clicking on the transparent area of the image should now not return the entity, so we know pixelAccurate stuff is working properly.
      (Sidenote: you mentioned entity ID, but hitTest returns the entire entity... although that still isn't more than just index and version, which combined is sort of its ID)

      Code (CSharp):
      1. //Get mouse position in world-space:
      2. let displayInfo = this.world.getConfigData(ut.Core2D.DisplayInfo);
      3. let displaySize = new Vector2(displayInfo.width, displayInfo.height);
      4. let camera = this.world.getEntityByName("Camera");
      5. let inputPosition = ut.Runtime.Input.getInputPosition();
      6. let mousePos: Vector3 = ut.Core2D.TransformService.windowToWorld(this.world, camera, inputPosition, displaySize);
      7.  
      8. //Perform hitTest with the found mouse position:
      9. let hit = ut.HitBox2D.HitBox2DService.hitTest(this.world, mousePos, camera);
      10. if (!hit.entityHit.isNone()) {
      11.     //This is the entity found by the hitTest
      12.     // entity name printed to console for fast and easy testing if the hitTest found the entity we expect it to find
      13.     console.log(this.world.getEntityName(hit.entityHit);
      14. }
    • Colliding entities and eyeballing where/when the entities hit:
      This method involves making entities collide and doing something on collision and then eyeballing at what contact point the entities collide. If that contact point is on the sprite and not on the transparent part of the image, then you know the pixelAccurate stuff is working.

      Code (CSharp):
      1. this.world.forEach([ut.Entity, MyTagComponent, ut.HitBox2D.HitBoxOverlapResults], (entity, tag, hitResults) => {
      2.     hitResults.overlaps.forEach(hitResult => {
      3.         if (!hitResult.otherEntity.isNone()) {
      4.             //Do something so we know collision happened
      5.             ut.Core2D.TransformService.destroyTree(this.world, hitResult.otherEntity, true);
      6.         }
      7.     });
      8. });
    I hope this helps :]
     
    reallyhexln and Exsert like this.
  6. Exsert

    Exsert

    Joined:
    Oct 22, 2015
    Posts:
    42
    Awesome yeah that's all definitely going to be useful :)

    Thank you for this response, it's invaluable.

    I'll try and get back tonight to see if this all worked :)
     
  7. Exsert

    Exsert

    Joined:
    Oct 22, 2015
    Posts:
    42
    @Rupture13 The code worked flawlessly, It's annoying how close it was yesterday.

    I have now got pixel perfect rendering for the game which is great.
    It's a Shame how much longer it is taking to implement these features comparatively to normal Unity.

    I am slowly getting used to everything.

    Is there a git repo anywhere that has like a good utility library yet?
    It feels like all of the things I am looking for someone probably has done already, but the only real resource is the Unity search tool.

    Again, Thank you so much :)
     
  8. Rupture13

    Rupture13

    Joined:
    Apr 12, 2016
    Posts:
    131
    Glad it worked!

    I only know of one repo with the purpose of offering general functionalities, in this thread, but I don't think it's very complete or anything.

    If you're looking for some functionality though, just keep posting on this forum. Doesn't matter if questions get asked multiple times. It's better than using the Unity search tool that's far from perfect.