Sagar Naikele
Sagar Naikele

Reputation: 5

UI development and data binding in unity 3d with hololens 2.0 emulator

hi I am new to unity3d development with hololens 2

I want to display employee details in the tile which is interactable see the sample screenshot below.

Sample employee tile

AS of now, I created a prefab like a custom component but facing issues in data binding.

I have one empty game object on which dynamically instantiating prefab using c# script

Empty game object

enter image description here

I have prefab of employee tile as below

EmployeeTile Prefab

As you can see I have two fields image (emp image) and text (emp name)

A script which is bound to empty game object

public class CreateEmployeeInfoTiles : MonoBehaviour
{ 
    private TextMeshProUGUI textMesh;
    private string _employeeName;
    private Employee[] emp;
    public GameObject employeeTile;

    // Start is called before the first frame update
    void Start()
    {
        Employee empobj = new Employee();
        emp = empobj.GenrateEmployees(6).ToArray();
        employeeTile = Resources.Load("EmployeeTile") as GameObject;
        int j = 10;
        for (int i = 0; i < emp.Length; i++)
        {
            var empTi = Instantiate(employeeTile, new Vector3((i * 10), (j * 20), 115), Quaternion.identity) as GameObject;

            empTi.SendMessage("BindData", emp[i]);
            j =+ 30;
        }
    }

    // Update is called once per frame
    void Update()
    {

    }
}

Employee class as a DTO

public class Employee
{
    public string Name { get; set; }
    public string Job { get; set; }
    public string imageUrl { get; set;}

    public List<Employee> GenrateEmployees(int noOfEmployees)
    {
        var emp = new List<Employee>();
        for (int i = 0; i < noOfEmployees; i++)
        {     
            emp.Add(new Employee() { Name = RandomName(), Job = RandomName(),
                imageUrl = "https://url/image/placeimg.jpg"});
        }

        return emp;
    }
}

I want to set employee data to respective game object/UI fields in dynamically generated employee tile prefab. Thanks in advance.

Upvotes: 0

Views: 306

Answers (1)

derHugo
derHugo

Reputation: 90570

First it seems very strange to me that GenerateEmployees should be an instanced method. You are creating a new Employee just to then generate more. This should rather be a static method I guess!

[Serializable]
public class Employee
{
    public string Name;
    public string Job;
    public string ImageUrl;

    // RandomName will also have to be static
    public static List<Employee> GenrateEmployees(int noOfEmployees)
    {
        // Lists in c# grow dynamically bigger. 
        // It is more efficient to already set the final size
        var emp = new List<Employee>(i);
        for (int i = 0; i < noOfEmployees; i++)
        {     
            emp.Add(new Employee() 
                        { 
                            Name = RandomName(), 
                            Job = RandomName(),
                            imageUrl = "https://url/image/placeimg.jpg"
                        }
                    );
        }

        return emp;
    }
}

Then there should simply be a certain component (script) attached to the employee prefab like e.g.

public class EmployeeController : MonoBehaviour
{
    // These you reference via the Inspector in the prefab
    [SerializeField] private Image image;
    [SerializeField] private TextMeshProUGUI nameField;
    [SerializeField] private TextMeshProUGUI designationField;

    // And finally have a method you can call directly
    // Using SendMessage is very inefficient and unsecure
    public void BindData(Employee data)
    {
        nameField.text = data.Name;
        designationField.text = data.Job;

        // Start downloading the image
        StartCoroutine(DownloadImage(data.ImageUrl));
    }

    private IEnumerator DownloadImage(string url)
    {
        using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
        {
            yield return www.SendWebRequest();

            if (www.isNetworkError || uwr.isHttpError)
            {
                Debug.Log(www.error);
            }
            else
            {
                // Get downloaded texture
                var texture = DownloadHandlerTexture.GetContent(www);

                // Create a sprite from the texture
                var sprite = Sprite.Create(texture, new Rect(0,0, texture.width, texture.height), Vector2.one * 0.5f);

                // Assign it to the image
                image.sprite = sprite;
            }
        }
    }
}

And finally you would simply use the static method to create Employee data and then use GetComponent to retrieve a reference to the EmployeeController component on the instantiated prefab. Even better would be not using Resources at all! Rather put the prefab in a normal folder and directly drag&drop it into the prefab field of CrrateEmployeeInfoTiles

public class CreateEmployeeInfoTiles : MonoBehaviour
{ 
    // NOTE: Do NOT use Resources!
    // rather place your prefab in any other folder and then simply drag it in here
    // via the Inspector!
    // By using directly the correct type instead of GameObject you
    //  a) do not need the GetComponent later since Instantiate already returns the dsme type
    //  b) have more security since now you only can drag&drop a GameObject here
    //     that actually has the required component attached
    [SerializeField] private EmployeeController employeePrefab;

    // Start is called before the first frame update
    private void Start()
    {
        var employeeData = Employee.GenrateEmployees(6).ToArray();

        var j = 10;  
        for (int i = 0; i < employeeData.Length; i++)
        {
            // Since employeePrefab is of type EmployeeController 
            // Instantiate already returns the component reference
            var employee = Instantiate(employeePrefab, new Vector3((i * 10), (j * 20), 115), Quaternion.identity);

            employee.BindData(emp[i]);

            j =+ 30;
        } 
    }
}

Typed on smartphone but I hope the idea gets clear

Upvotes: 1

Related Questions