Search Unity

Select with click/tap, drag'n'drop

Discussion in 'Project Tiny' started by Demoralizator, Dec 20, 2018.

  1. Demoralizator

    Demoralizator

    Joined:
    Apr 6, 2015
    Posts:
    2
    I'm trying to make a card game in Tiny and i wonder, what is the best way to implement a click on a sprite and dragging and dropping a sprite? Raycast, or maybe UI?
    I would really appreciate some clarifications on how Raycast works in Tiny.
     
    LauraLaureus likes this.
  2. LauraLaureus

    LauraLaureus

    Joined:
    Oct 5, 2018
    Posts:
    10
    I'm still playing with Tiny but In the Match-Three example they select the gems by checking the mouse/touch position is in the sprite limits.

    Since I really don't like to perform all the calculation for every entity in the game I reasearched in the forums (https://forum.unity.com/threads/button-press.595912/ ) and found a component called "MouseInteraction" that has a property called "clicked", but for me it always return false including when I force the system to perform after Input Fence.

    Also in the forums is shown a callback way but you cannot perform operations with this.data (in the case of Behaviour systems) since it's another scope.

    So I thing the only stable way to do this is in the way the tutorial shows.
     
    Demoralizator likes this.
  3. Nkon

    Nkon

    Unity Technologies

    Joined:
    Jun 12, 2017
    Posts:
    65
    Hey,

    Here's a small example demonstrating image dragging inside a UICanvas.

    You need to define two custom components for this system to work. They are 'Draggable' and 'Dragged'. These components don't need to have any fields in them.

    The code assumes you're using the default 'game' namespace for components and systems.

    Any objects you wish to drag should have the MouseInteraction and Draggable components added to them in the Editor.

    Code (JavaScript):
    1. namespace game {
    2. export class EntityDragSystem extends ut.ComponentSystem {
    3.     static initialized = false;
    4.  
    5.     OnMouseDown(e: ut.Entity): void {
    6.         console.log("Mouse down on Entity #" + e.index);
    7.         // add a game.Dragged component to the clicked entity
    8.         const oneworld = ut.HTML.HTMLService.oneWorld() as ut.World;
    9.         oneworld.addComponent(e, game.Dragged);
    10.     }
    11.  
    12.     OnMouseUp(e: ut.Entity): void {
    13.         console.log("Mouse up on Entity #" + e.index);
    14.         // remove a game.Dragged component from the clicked entity
    15.         const oneworld = ut.HTML.HTMLService.oneWorld() as ut.World;
    16.         oneworld.removeComponent(e, game.Dragged);
    17.     }
    18.  
    19.     OnUpdate(): void {
    20.         // set up callbacks for all entities with the required components
    21.         if (!EntityDragSystem.initialized) {
    22.             this.world.forEach([ut.Entity, ut.UIControls.MouseInteraction, game.Draggable],
    23.                 (entity, mouseInteraction, draggable) => {
    24.                     ut.UIControls.UIControlsService.addOnDownCallback(
    25.                         this.world, entity, this.OnMouseDown);
    26.                     ut.UIControls.UIControlsService.addOnUpCallback(
    27.                         this.world, entity, this.OnMouseUp);
    28.                 });
    29.                
    30.             EntityDragSystem.initialized = true;
    31.             console.log("Callbacks added");
    32.         }
    33.         // calculate new position for any dragged entities
    34.         const displayInfo = this.world.getConfigData(ut.Core2D.DisplayInfo);
    35.         let mousePos = ut.Core2D.Input.getInputPosition();
    36.         mousePos.x -= displayInfo.frameWidth / 2;
    37.         mousePos.y -= displayInfo.frameHeight / 2;
    38.         // update all dragged entities to use the new position
    39.         this.world.forEach([ut.Entity, game.Dragged, ut.UILayout.RectTransform],
    40.             (entity, dragged, rectTransform) => {
    41.                 rectTransform.anchoredPosition = mousePos;
    42.             });
    43.     }
    44. }
    45. }
     
    Demoralizator likes this.
  4. Demoralizator

    Demoralizator

    Joined:
    Apr 6, 2015
    Posts:
    2
    Hey, Laura. Thanks for the suggestion, but i think Match3 approach is only applicable when you have some kind of a grid and the elements are not overlapping.
    Hey, Nkon. Thanks a lot. I'll try it right away. I'm still not sure how to implement drop though.

    And my question about Raycast still stands. Would be nice to wrap my head around such a versatile tool.
     
  5. nik_ai

    nik_ai

    Joined:
    Jun 14, 2017
    Posts:
    9
    @Demoralizator
    Make sure Sprite2DRendererHitBox2D component attached to that entity which you want to hit.

    Code (JavaScript):
    1. let _hitResult = ut.HitBox2D.HitBox2DService.hitTest(this.world,tapPos,camEntity);
    2.  
    3. if(!_hitResult.entityHit.isNone())
    4. {
    5. console.log("Something hitted");
    6. console.log(this.world.getEntityName(_hitResult.entityHit));
    7. }
     
    Streamfall and Demoralizator like this.
  6. Streamfall

    Streamfall

    Joined:
    Aug 8, 2011
    Posts:
    28
    I'm also trying to accomplish this. I'm not receiving any hits.

    EDIT
    This seems to be a problem to converting camera space to world space, as I can output the positions of my sprites and position of raycast.

    EDIT 2
    Needed to convert the mouse position to world position, like so :
    let mousePos = ut.Core2D.Input.getInputPosition();
    let mp = ut.Core2D.Input.translateScreenToWorld(this.world,mousePos);

    EDIT 3
    Could probably have just used :
    getWorldInputPosition
     
    Last edited: Jan 8, 2019
    patolino and nik_ai like this.
  7. nik_ai

    nik_ai

    Joined:
    Jun 14, 2017
    Posts:
    9
    You are right @Streamfall ,
    We have to convert mouse position to world position.
    I have used below method from TinyArmProject

    Code (JavaScript):
    1. //For getting mouse pointer position in world space
    2.         static getPointerWorldPosition(world: ut.World, cameraEntity: ut.Entity): Vector3 {
    3.             let displayInfo = world.getConfigData(ut.Core2D.DisplayInfo);
    4.             let displaySize = new Vector2(displayInfo.width, displayInfo.height);
    5.             let inputPosition = ut.Runtime.Input.getInputPosition();
    6.             return ut.Core2D.TransformService.windowToWorld(world, cameraEntity, inputPosition, displaySize);
    7.         }