Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

Trying To Understand SetComponentData

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

  1. coldasfrost979

    coldasfrost979

    Joined:
    Jun 9, 2018
    Posts:
    25
    Hello,

    I am trying to understand how to use the EntityManager to create new components. I will be doing a lot of this in my game as it is a classic RTS style. Right now I am just trying to practice with a building.

    My initial scene contains the prefab 'Building'
    upload_2018-6-20_21-15-30.png

    upload_2018-6-20_21-15-51.png



    And my bootstrap has the following code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Entities;
    5. using UnityEngine.AI;
    6. using Unity.Transforms;
    7. using static BuildingProductionSystem;
    8.  
    9. public class FallenBootstrap  {
    10.     public static EntityManager entityManager;
    11.     private static EntityArchetype cameraArchetype;
    12.     private static EntityArchetype buildingArchetype;
    13.     private static EntityArchetype unitArchetype;
    14.     private static EntityArchetype groundArchetype;
    15.  
    16.    
    17.     // Use this for initialization
    18.     [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    19.     public static void Start () {
    20.         Debug.Log("I have started the game!");
    21.         entityManager = World.Active.GetOrCreateManager<EntityManager>();
    22.  
    23.         cameraArchetype = entityManager.CreateArchetype(typeof(Rotation), typeof(Position), typeof(Camera));
    24.  
    25.  
    26.         buildingArchetype = entityManager.CreateArchetype(typeof(MeshRenderer), typeof(BoxCollider), typeof(BuildingInputSystem),
    27.             typeof(RectTransform), typeof(MeshFilter), typeof(MouseOverSystem), typeof(Position));
    28.  
    29.         unitArchetype = entityManager.CreateArchetype(typeof(MeshRenderer), typeof(SphereCollider), typeof(NavMeshAgent));
    30.  
    31.         groundArchetype = entityManager.CreateArchetype(typeof(MeshRenderer), typeof(MeshCollider));
    32.  
    33.         Entity building = entityManager.CreateEntity(buildingArchetype);
    34.  
    35.         var proto = GameObject.Find("Building");
    36.         var proto_position = proto.GetComponent<Position>().Value; //why are these different?
    37.         var proto_rect_transform = proto.GetComponent<RectTransform>();
    38.         Object.Destroy(proto);
    39.  
    40.         entityManager.SetComponentData(building, proto_position);
    41.        
    42.  
    43.      //   var Camera = entityManager.CreateEntity(cameraArchetype);
    44.    
    45.     }
    46.    
    47. }
    48.  
    You can see when I do this I get the following exception:
    upload_2018-6-20_21-17-38.png

    It reads: "The type 'Unity.Mathematics.float3' cannot be used as type parameter 'T' in the generic type or method 'EntityManager.SetComponentData<T>(Entity, T)'. There is no boxing conversion from 'Unity.Mathematics.float3' to 'Unity.Entities.IComponentData'.

    In the TwoStick Pure example they do something similar where they get the playerLook from the mesh, but I do see how they are doing something like

    entityManager.AddSharedComponentData(player, PlayerLook);


    Does my data have to be shared? What should I be doing to convert the prefab position into a ComponentData?

    Thank you in advance.
     
  2. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,556
    SetComponentData
    has to be used with a whole component. It does not know if this float should go into
    Position
    IComponentData
    on the entity. Instead, you have to add
    new Position { Value = proto_position }


    Another issue, after this error it should say this entity does not have a component of type
    Position
    so you cannot use Set (but you can use
    AddComponentData
    ) A
    Position
    component is not magically added for all generated entity from
    GameObjectEntity
    nor magically converted from object's transform (But you do magically get
    TransformAccess
    from object's transform), you have to manually add them so
    GameObjectEntity
    can bundle it together at the time it creates an entity. Add a
    MonoBehaviour
    named
    PositionComponent
    for this, and now you can use
    SetComponentData
    because your entity has
    Position
    data of 0,0,0

    To not having 0,0,0 but instead prefab position in this
    Position
    component data additionally add
    MonoBehaviour
    named
    CopyInitialTransfromFromGameObject
    . Or if you want the
    Position
    in entity be continuously updated to match your game object use the one without Initial.
     
  3. coldasfrost979

    coldasfrost979

    Joined:
    Jun 9, 2018
    Posts:
    25
    Thank you very much for your response. I made a couple changes.

    I changed it to AddComponentData and did the New Position etc...., also I was trying to call GameObject.Find on a prefab when I really needed to "break" my prefab and turn it into a normal game object. However, when I call find on it I still get a null pointer reference. Running this code:

    Code (CSharp):
    1. var proto = GameObject.Find("BuildingPrototype");
    2.         if(proto == null)
    3.         {
    4.             Debug.Log("why?");
    5.         }
    6.         var proto_position = proto.GetComponent<Position>().Value; //why are these different?
    7.         var proto_rect_transform = proto.GetComponent<RectTransform>();
    8.         Object.Destroy(proto);
    will result in "why?" being printed out. Here is my building prototype: upload_2018-6-21_18-55-49.png



    any thoughts as to why that is? thank you for your time.
     
  4. coldasfrost979

    coldasfrost979

    Joined:
    Jun 9, 2018
    Posts:
    25
    Whoa! I am a noob. Sorry but I realized the reason I didn't find the object is this line!


    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]

    I see no reason to not change it to AfterSceneLoad so... fixed that problem. On to the next =).
     
  5. starikcetin

    starikcetin

    Joined:
    Dec 7, 2017
    Posts:
    340
    Note that you can have two separate methods, one marked with BeforeSceneLoad and another marked with AfterSceneLoad, coexisting in the same class.