Search Unity

Handling The Selection Of My Buildings

Discussion in 'Entity Component System' started by coldasfrost979, Jun 21, 2018.

  1. coldasfrost979

    coldasfrost979

    Joined:
    Jun 9, 2018
    Posts:
    25
    Folks,

    What are you thoughts on this new Job / ECS system for handling the "click" on or selection of an object (in this case a cube) and indicating that object is "selected"? In the old world, you simply attach a monobehavior to the object and handle the method in the "onClick" method.
     
  2. JPrzemieniecki

    JPrzemieniecki

    Joined:
    Feb 7, 2013
    Posts:
    33
    (Note: I also want to handle mouse overs, so your method may differ if you don't)
    I define the following components:
    MouseOverTarget, MouseOver, ClickTarget, Clicked, ClickHandled

    I have the following systems:
    MouseOverSystem - goes through all MouseOverTarget entities and adds/removes MouseOver where appropriate
    ClickSystem - goes through MouseOver+ClickTarget and adds Clicked if LMB was pressed.

    then for each kind of clickable entity in my game I have systems like
    CardMouseOverSystem - goes through all Card+MouseOver, (e.g. highlights the card)
    CardClickSystem - goes through all Card+Clicked+Not(ClickHandled), does whatever it needs (this is your "OnClick" method) and adds ClickHandled. (For example, in my case it adds a Dragged component for Drag&Drop).

    Oh, and the ClickSystem also cleans up Clicked+ClickHandled pairs (just removes them).

    I would assume when the ECS matures you will get all but the entity-kind-specific systems built in (just like you don't have to call OnClick yourself in the UI system). Or maybe they will come up with a better method.
     
    Last edited: Jun 21, 2018
  3. coldasfrost979

    coldasfrost979

    Joined:
    Jun 9, 2018
    Posts:
    25
    Hey thank you very much for your response! I will try to implement something like this and wrap my head around this.
     
  4. coldasfrost979

    coldasfrost979

    Joined:
    Jun 9, 2018
    Posts:
    25
    Question, are you using a RayCast to detect if the mouse is over an object?
     
  5. JPrzemieniecki

    JPrzemieniecki

    Joined:
    Feb 7, 2013
    Posts:
    33
    I'm dealing with rectangles, so I'm using a ray-rectangle test, but I see no reason why a PhysX Raycast wouldn't work (you probably want to use Collider.Raycast instead of Physics.Raycast. I haven't touched the job-friendly physics api yet so can't help there)
     
  6. coldasfrost979

    coldasfrost979

    Joined:
    Jun 9, 2018
    Posts:
    25
    Well what you have suggested thus far has been a huge help. I am really struggling with thinking the way I need to be thinking to be productive with this new system.
     
  7. coldasfrost979

    coldasfrost979

    Joined:
    Jun 9, 2018
    Posts:
    25
    Sorry to bother but I have been bouncing around tutorials and the forum for a while now... how are you gaining access to a collider for a given entity? I have this thus far (which I know is incorrect):
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Entities;
    5. using static ComponentTypes;
    6. using Unity.Collections;
    7.  
    8. public class MouseOverSystem : ComponentSystem
    9. {
    10.    
    11.  
    12.     public struct MouseOverTargetGroup
    13.     {
    14.         [ReadOnly] public ComponentDataArray<MouseOverTarget> Targets;
    15.         public ComponentDataArray<EntityCollider> Colliders;
    16.         public EntityArray Entity;
    17.         //public BoxCollider BoxColliders;
    18.         public int Length;
    19.     }
    20.  
    21.     [Inject] MouseOverTargetGroup group;
    22.     private Ray ray;
    23.     private RaycastHit hit;
    24.  
    25.     protected override void OnUpdate()
    26.     {
    27.        
    28.         ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    29.        
    30.         for (int i = 0; i < group.Length; i++)
    31.         {
    32.             //Raycast(ray, out hit, 1000.0f)
    33.             //
    34.             if (group.Colliders[i].collider.Raycast(ray, out hit, 1000.0f))
    35.             {
    36.                 Debug.Log("did  I add it?");
    37.                 if(!FallenBootstrap.entityManager.HasComponent(group.Entity[i], ComponentType.Create<MouseOver>()))
    38.                 {
    39.  
    40.                     FallenBootstrap.entityManager.AddComponent(group.Entity[i], ComponentType.Create<MouseOver>());
    41.                 }
    42.             }
    43.         }
    44.     }
    45. }
    46.  
    47.  
    It doesn't matter if I try to add Collider, or BoxCollider, the error is the same. Something about blittable....
     
  8. JPrzemieniecki

    JPrzemieniecki

    Joined:
    Feb 7, 2013
    Posts:
    33
    You cannot store reference type objects (a.k.a. class instances) in IComponentData. All old Unity components are classes, which includes Collider.

    The workaround provided is ComponentArray<T> which lets you inject Monobehaviours and old-style built-in components (note, you apparently need a specific type, ComponentArray<Collider> finds nothing for me while ComponentArray<BoxCollider> works).

    This works for me:

    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Entities;
    3.  
    4. public class RaycastingSystem : ComponentSystem
    5. {
    6.     struct Data
    7.     {
    8.         public int Length;
    9.         public ComponentArray<BoxCollider> Collider;
    10.     }
    11.     [Inject] Data _data;
    12.  
    13.     protected override void OnUpdate()
    14.     {
    15.         var ray = new Ray(Vector3.zero, Vector3.forward);
    16.         for (int i = 0; i < _data.Length; i++)
    17.         {
    18.             RaycastHit hit;
    19.             var collider = _data.Collider[i];
    20.             if(collider.Raycast(ray, out hit, Mathf.Infinity))
    21.             {
    22.                 Debug.Log("Found a thing: " + collider.name);
    23.             }
    24.         }
    25.     }
    26. }
    27.  
    Read on the Hybrid ECS (and look at the Hybrid TwinStickShooter sample) to learn how to set up/spawn GameObjects that will be accessible from Systems (it boils down to attaching GameObjectEntity to an old-style GameObject).