Reputation: 5
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.
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
I have prefab of employee tile as below
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
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