Разработка пользовательского интерфейса и привязка данных в Unity 3D с эмулятором hololens 2.0 - PullRequest
0 голосов
/ 12 февраля 2020

привет Я новичок в разработке unity3d с hololens 2

Я хочу отобразить детали сотрудника в интерактивном виде, см. Пример снимка экрана ниже.

Sample employee tile

На данный момент я создал префаб, как пользовательский компонент, но столкнулся с проблемами в привязке данных.

У меня есть один пустой игровой объект, для которого динамически создается префаб с использованием c# script

Empty game object

enter image description here

У меня есть сборная клетка сотрудника, как показано ниже

EmployeeTile Prefab

Как видите, у меня есть два поля: image (emp image) и text (emp name)

Скрипт, который привязан к пустому игровому объекту

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()
    {

    }
}

Класс сотрудника как 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;
    }
}

Я хочу установить данные сотрудника для соответствующих полей игрового объекта / пользовательского интерфейса в динамически сгенерированном префабе плиток сотрудника. Заранее спасибо.

1 Ответ

1 голос
/ 12 февраля 2020

Сначала мне кажется очень странным, что GenerateEmployees должен быть инстанцированным методом. Вы создаете новый Employee, чтобы потом генерировать больше. Скорее, это должен быть метод static, я думаю!

[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;
    }
}

Тогда к префабу сотрудника должен быть просто присоединен определенный компонент (скрипт), например,

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;
            }
        }
    }
}

И, наконец, вы просто использовали бы метод static для создания данных Employee, а затем использовали бы GetComponent для получения ссылки на компонент EmployeeController в созданном префабе. Еще лучше не использовать Resources вообще! Вместо этого поместите сборный файл в обычную папку и сразу перетащите его в готовое поле 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;
        } 
    }
}

Напечатано на смартфоне, но я надеюсь, что идея проясняется

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...