# Question
Title: Creating a custom Editor Window using a Multi Column Header
Hey there I'm trying to use the `MultiColumnHeader` to create a tool to view materials in the scene, inspired by the light explorer. The problems I'm facing are two fold. First I can't figure out how to place the content of the `MultiColumnHeader` in a scrollable view and secondly I can't figure out how to give the rows a different background color that alternates like in the light explorer. This is my `OnGUI` code:

```
 void OnGUI()
    {
        windowVisibleRect.width = position.width;
        windowVisibleRect.height = position.height;
        // draw the column headers
        var headerRect = windowVisibleRect;
        headerRect.height = columnHeader.height;

        float xScroll = scrollPos.x;

        columnHeader.OnGUI(headerRect, xScroll);

        // draw the column's contents
        for (int i = 0; i < columns.Length; i++)
        {
            // calculate column content rect
            var contentRect = columnHeader.GetColumnRect(i);
            contentRect.x -= xScroll;
            contentRect.y = contentRect.yMax;
            contentRect.yMax = windowVisibleRect.yMax;
            Rect rowRect = new Rect(contentRect.x, contentRect.y, windowVisibleRect.width,20);
            for (int j = 0; j < analyzerList.Count; j++)
            {

                Rect MatcellRect = columnHeader.GetCellRect(0, rowRect);
                Rect ShaderCellRect = columnHeader.GetCellRect(1, rowRect);
                Rect GameObjectsRect = columnHeader.GetCellRect(2, rowRect);
                rowRect.y += 25;
                EditorGUI.ObjectField(MatcellRect, GUIContent.none, analyzerList[j].mat, typeof(Material), false);
                EditorGUI.ObjectField(ShaderCellRect, GUIContent.none, analyzerList[j].shader, typeof(Shader), false);

                analyzerList[j].ShowGameObject = EditorGUI.Foldout(GameObjectsRect,analyzerList[j].ShowGameObject, "Show " + analyzerList[j].gameObjects.Count + " GameObjects");
                if (analyzerList[j].ShowGameObject)
                {
                    foreach (GameObject go in analyzerList[j].gameObjects)
                    {
                        GameObjectsRect.y += GameObjectsRect.height;
                        EditorGUI.ObjectField(GameObjectsRect, GUIContent.none, go, typeof(Material), false);

                        rowRect.y += GameObjectsRect.height;
                    }
                }

            }
        }

    }

```

If a Editor GUI guru could explain to me how to do it like I'm a child that would be great :). I don't do custom GUI stuff and most of this is beyond me.

As per requested I'm uploading two example images. One from unity and one I randomly found from the net. Note that I do not need the "stacking"(I dont know how to call them) headers from the second example. I do how ever require a vertical and horizontal scrollbar like in the second example.

And finally just for reference this is what my code does so far

# Answer
**Code:**

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.IMGUI.Controls;

public class MCHEditorWindow : EditorWindow
{
    /// <summary>
    /// This is a test object, just to showcase how this could be used.
    /// </summary>
    private class Enemy
    {
        public string Name { get; set; }
        public float Health { get; set; }
        public Color SkinColor { get; set; }

        public Enemy(string name, float health, Color skinColor)
        {
            this.Name = name;
            this.Health = health;
            this.SkinColor = skinColor;
        }
    }

    [MenuItem(itemName: "Tools/MCH Editor Window")]
    public static MCHEditorWindow Open()
    {
        MCHEditorWindow commentsNotebookEditorWindow = EditorWindow.GetWindow<MCHEditorWindow>(
            title: "MCH Editor Window",
            focus: true
        );

        commentsNotebookEditorWindow.minSize = new Vector2(x: 450.0f, y: 100.0f);

        commentsNotebookEditorWindow.Show();

        return commentsNotebookEditorWindow;
    }

    private MultiColumnHeaderState _multiColumnHeaderState;
    private MultiColumnHeader _multiColumnHeader;

    private MultiColumnHeaderState.Column[] _columns;

    // Create a few test subjects.
    private Enemy[] _testObjects = new Enemy[]
    {
        new Enemy("Orc", 25.0f, Color.green),
        new Enemy("Fairy", 10.0f, Color.cyan),
        new Enemy("Mech Golem", 57.0f, Color.grey),
        new Enemy("Orc", 25.0f, Color.green),
        new Enemy("Fairy", 10.0f, Color.cyan),
        new Enemy("Mech Golem", 57.0f, Color.grey),
        new Enemy("Orc", 25.0f, Color.green),
        new Enemy("Fairy", 10.0f, Color.cyan),
        new Enemy("Mech Golem", 57.0f, Color.grey),
        new Enemy("Orc", 25.0f, Color.green),
        new Enemy("Fairy", 10.0f, Color.cyan),
        new Enemy("Mech Golem", 57.0f, Color.grey),
    };

    private void Initialize()
    {
        // We can move these columns into some ScriptableObject or some other data saving object/file to save their properties there, otherwise because of some events these settings will be recreated and state of the window won't be saved as expected.
        this._columns = new MultiColumnHeaderState.Column[]
        {
            new MultiColumnHeaderState.Column()
            {
                allowToggleVisibility = false, // At least one column must be there.
                autoResize = true,
                minWidth = 250.0f,
                canSort = true,
                sortingArrowAlignment = TextAlignment.Right,
                headerContent = new GUIContent("Name", "A name of an enemy."),
                headerTextAlignment = TextAlignment.Left,
            },
            new MultiColumnHeaderState.Column()
            {
                allowToggleVisibility = true,
                autoResize = true,
                minWidth = 300.0f,
                canSort = false,
                sortingArrowAlignment = TextAlignment.Right,
                headerContent = new GUIContent("Health", "A health of an enemy."),
                headerTextAlignment = TextAlignment.Center,
            },
            new MultiColumnHeaderState.Column()
            {
                allowToggleVisibility = true,
                autoResize = true,
                minWidth = 125.0f,
                maxWidth = 175.0f,
                canSort = false,
                sortingArrowAlignment = TextAlignment.Right,
                headerContent = new GUIContent("Skin Color", "A color of an enemy skin."),
                headerTextAlignment = TextAlignment.Center,
            },
        };

        this._multiColumnHeaderState = new MultiColumnHeaderState(columns: this._columns);

        this._multiColumnHeader = new MultiColumnHeader(state: this._multiColumnHeaderState);

        // When we chagne visibility of the column we resize columns to fit in the window.
        this._multiColumnHeader.visibleColumnsChanged += (multiColumnHeader) => multiColumnHeader.ResizeToFit();

        // Initial resizing of the content.
        this._multiColumnHeader.ResizeToFit();
    }

    private readonly Color _lighterColor = Color.white * 0.3f;
    private readonly Color _darkerColor = Color.white * 0.1f;

    private Vector2 _scrollPosition;

    private void OnGUI()
    {
        // After compilation and some other events data of the window is lost if it's not saved in some kind of container. Usually those containers are ScriptableObject(s).
        if (this._multiColumnHeader == null)
        {
            this.Initialize();
        }

        // Basically we just draw something. Empty space. Which is `FlexibleSpace` here on top of the window.
        // We need this for - `GUILayoutUtility.GetLastRect()` because it needs at least 1 thing to be drawn before it.
        GUILayout.FlexibleSpace();

        // Get automatically aligned rect for our multi column header component.
        Rect windowRect = GUILayoutUtility.GetLastRect();

        // Here we are basically assigning the size of window to our newly positioned `windowRect`.
        windowRect.width = this.position.width;
        windowRect.height = this.position.height;

        float columnHeight = EditorGUIUtility.singleLineHeight;

        // This is a rect for our multi column table.
        Rect columnRectPrototype = new Rect(source: windowRect)
        {
            height = columnHeight, // This is basically a height of each column including header.
        };

        // Just enormously large view if you want it to span for the whole window. This is how it works [shrugs in confusion].
        Rect positionalRectAreaOfScrollView = GUILayoutUtility.GetRect(0, float.MaxValue, 0, float.MaxValue);

        // Create a `viewRect` since it should be separate from `rect` to avoid circular dependency.
        Rect viewRect = new Rect(source: windowRect)
        {
            xMax = this._columns.Sum((column) => column.width) // Scroll max on X is basically a sum of width of columns.
        };

        this._scrollPosition = GUI.BeginScrollView(
            position: positionalRectAreaOfScrollView,
            scrollPosition: this._scrollPosition,
            viewRect: viewRect,
            alwaysShowHorizontal: false,
            alwaysShowVertical: false
        );

        // Draw header for columns here.
        this._multiColumnHeader.OnGUI(rect: columnRectPrototype, xScroll: 0.0f);

        // For each element that we have in object that we are modifying.
        //? I don't have an appropriate object here to modify, but this is just an example. In real world case I would probably use ScriptableObject here.
        for (int a = 0; a < this._testObjects.Length; a++)
        {
            //! We draw each type of field here separately because each column could require a different type of field as seen here.
            // This can be improved if we want to have a more robust system. Like for example, we could have logic of drawing each field moved to object itself.
            // Then here we would be able to just iterate through array of these objects and call a draw methods for these fields and use this window for many types of objects.
            // But example with such a system would be too complicated for gamedev.stackexchange, so I have decided to not overengineer and just use hard coded indices for columns - `columnIndex`.

            Rect rowRect = new Rect(source: columnRectPrototype);

            rowRect.y += columnHeight * (a + 1);

            // Draw a texture before drawing each of the fields for the whole row.
            if (a % 2 == 0)
                EditorGUI.DrawRect(rect: rowRect, color: this._darkerColor);
            else
                EditorGUI.DrawRect(rect: rowRect, color: this._lighterColor);

            // Name field.
            int columnIndex = 0;

            if (this._multiColumnHeader.IsColumnVisible(columnIndex: columnIndex))
            {
                int visibleColumnIndex = this._multiColumnHeader.GetVisibleColumnIndex(columnIndex: columnIndex);

                Rect columnRect = this._multiColumnHeader.GetColumnRect(visibleColumnIndex: visibleColumnIndex);

                // This here basically is a row height, you can make it any value you like. Or you could calculate the max field height here that your object has and store it somewhere then use it here instead of `EditorGUIUtility.singleLineHeight`.
                // We move position of field on `y` by this height to get correct position.
                columnRect.y = rowRect.y;

                GUIStyle nameFieldGUIStyle = new GUIStyle(GUI.skin.label)
                {
                    padding = new RectOffset(left: 10, right: 10, top: 2, bottom: 2)
                };

                EditorGUI.LabelField(
                    position: this._multiColumnHeader.GetCellRect(visibleColumnIndex: visibleColumnIndex, columnRect),
                    label: new GUIContent(this._testObjects[a].Name),
                    style: nameFieldGUIStyle
                );
            }

            // Health slider field.
            columnIndex = 1;

            if (this._multiColumnHeader.IsColumnVisible(columnIndex: columnIndex))
            {
                int visibleColumnIndex = this._multiColumnHeader.GetVisibleColumnIndex(columnIndex: columnIndex);

                Rect columnRect = this._multiColumnHeader.GetColumnRect(visibleColumnIndex: visibleColumnIndex);

                columnRect.y = rowRect.y;

                this._testObjects[a].Health = EditorGUI.Slider(
                    position: this._multiColumnHeader.GetCellRect(visibleColumnIndex: visibleColumnIndex, columnRect),
                    value: this._testObjects[a].Health,
                    leftValue: 0.0f,
                    rightValue: 100.0f
                );
            }

            // Skin color field.
            columnIndex = 2;

            if (this._multiColumnHeader.IsColumnVisible(columnIndex: columnIndex))
            {
                int visibleColumnIndex = this._multiColumnHeader.GetVisibleColumnIndex(columnIndex: columnIndex);

                Rect columnRect = this._multiColumnHeader.GetColumnRect(visibleColumnIndex: visibleColumnIndex);

                columnRect.y = rowRect.y;

                this._testObjects[a].SkinColor = EditorGUI.ColorField(
                    position: this._multiColumnHeader.GetCellRect(visibleColumnIndex: visibleColumnIndex, columnRect),
                    label: GUIContent.none,
                    value: this._testObjects[a].SkinColor,
                    showEyedropper: true,
                    showAlpha: false,
                    hdr: false
                );
            }
        }

        GUI.EndScrollView(handleScrollWheel: true);
    }

    private void Awake()
    {
        this.Initialize();
    }
}
#endif

```

---

**Result:**
> 2 votes

# Answer
**Why is this a separate answer?**

First - it goes out of the scope of the question bringing more features.

Second - it has a slightly different approach to rendering objects, the object rendered is inherited from `UnityEngine.Object` which enables serialization for it for `SerializedObject`, but it also brings some things that others might not like to have in their architecture.

**Possible issues:**

* You won't be able to assign `GameObject`\[s\] out of the box, since unity doesn't serialize scene objects in `ScriptableObject`. You will have to either serialize a different type of object or implement your own solution, which can be complicated.
* DrawRect is making rows less visible, but I have described in the comments what you can do to achieve the desired result.

**Code:**

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.IMGUI.Controls;

public class MCHEditorWindow : EditorWindow
{
    /// <summary>
    /// This is a test object, just to showcase how this could be used.
    /// </summary>
    [System.Serializable]
    private class Enemy : ScriptableObject
    {
        [SerializeField] private string _name;
        public string Name => this._name;

        [SerializeField] private float _health;
        public float Health => this._health;

        [SerializeField] private Color _skinColor;
        public Color SkinColor => this._skinColor;

        [SerializeField] private List<GameObject> _gameObjects;
        public List<GameObject> GameObjects => this._gameObjects;

        public Enemy(string name, float health, Color skinColor)
        {
            this._name = name;
            this._health = health;
            this._skinColor = skinColor;
        }

        public void Initialize(string name, float health, Color skinColor)
        {
            this._name = name;
            this._health = health;
            this._skinColor = skinColor;
        }

        private void Awake()
        {
            this._name = "Default Name";
            this._health = 34.2f;
            this._skinColor = Color.white;
        }
    }

    [MenuItem(itemName: "Tools/MCH Editor Window")]
    public static MCHEditorWindow Open()
    {
        MCHEditorWindow commentsNotebookEditorWindow = EditorWindow.GetWindow<MCHEditorWindow>(
            title: "MCH Editor Window",
            focus: true
        );

        commentsNotebookEditorWindow.minSize = new Vector2(x: 450.0f, y: 100.0f);

        commentsNotebookEditorWindow.Show();

        return commentsNotebookEditorWindow;
    }

    private MultiColumnHeaderState _multiColumnHeaderState;
    private MultiColumnHeader _multiColumnHeader;

    private MultiColumnHeaderState.Column[] _columns;

    // Create a few test subjects.
    private Enemy[] _testObjects = new Enemy[3];
    //{
    //  new Enemy("Orc", 25.0f, Color.green),
    //  new Enemy("Fairy", 10.0f, Color.cyan),
    //  new Enemy("Mech Golem", 57.0f, Color.grey),
    //};

    private float _multiColumnHeaderWidth;

    private bool _firstOnGUIIterationAfterInitialize;

    private void Initialize()
    {
        this._firstOnGUIIterationAfterInitialize = true;

        this._multiColumnHeaderWidth = this.position.width;

        // We can move these columns into some ScriptableObject or some other data saving object/file to save their properties there, otherwise because of some events these settings will be recreated and state of the window won't be saved as expected.
        this._columns = new MultiColumnHeaderState.Column[]
        {
            new MultiColumnHeaderState.Column()
            {
                allowToggleVisibility = false, // At least one column must be there.
                autoResize = true,
                minWidth = 100.0f,
                maxWidth = 250.0f,
                canSort = true,
                sortingArrowAlignment = TextAlignment.Right,
                headerContent = new GUIContent("Name", "A name of an enemy."),
                headerTextAlignment = TextAlignment.Left,
            },
            new MultiColumnHeaderState.Column()
            {
                allowToggleVisibility = true,
                autoResize = true,
                minWidth = 300.0f,
                canSort = false,
                sortingArrowAlignment = TextAlignment.Right,
                headerContent = new GUIContent("Health", "A health of an enemy."),
                headerTextAlignment = TextAlignment.Center,
            },
            new MultiColumnHeaderState.Column()
            {
                allowToggleVisibility = true,
                autoResize = true,
                minWidth = 125.0f,
                maxWidth = 200.0f,
                canSort = false,
                sortingArrowAlignment = TextAlignment.Right,
                headerContent = new GUIContent("Skin Color", "A color of an enemy skin."),
                headerTextAlignment = TextAlignment.Center,
            },
            new MultiColumnHeaderState.Column()
            {
                allowToggleVisibility = false,
                autoResize = true,
                minWidth = 300.0f,
                canSort = false,
                sortingArrowAlignment = TextAlignment.Right,
                headerContent = new GUIContent("Game Objects", "An array of game objects."),
                headerTextAlignment = TextAlignment.Center,
            },
        };

        this._multiColumnHeaderState = new MultiColumnHeaderState(columns: this._columns);

        this._multiColumnHeader = new MultiColumnHeader(state: this._multiColumnHeaderState);

        // When we chagne visibility of the column we resize columns to fit in the window.
        this._multiColumnHeader.visibleColumnsChanged += (multiColumnHeader) =>
        {
            multiColumnHeader.ResizeToFit();
        };

        // Initial resizing of the content.
        this._multiColumnHeader.ResizeToFit();

        this._testObjects[0] = ScriptableObject.CreateInstance<Enemy>();
        this._testObjects[0].Initialize("Orc", 25.0f, Color.green);

        this._testObjects[1] = ScriptableObject.CreateInstance<Enemy>();
        this._testObjects[1].Initialize("Fairy", 10.0f, Color.cyan);

        this._testObjects[2] = ScriptableObject.CreateInstance<Enemy>();
        //this._testObjects[2].Initialize("Mech Golem", 57.0f, Color.grey);
    }

    private readonly Color _lighterColor = new Color(r: 1.0f, g: 1.0f, b: 1.0f, a: 0.15f);
    private readonly Color _darkerColor = new Color(r: 0.0f, g: 0.0f, b: 0.0f, a: 0.15f);

    private Vector2 _scrollPosition;

    private void OnGUI()
    {
        float columnHeight = EditorGUIUtility.singleLineHeight;

        // Basically we just draw something. Empty space. Which is `FlexibleSpace` here on top of the window.
        // We need this for - `GUILayoutUtility.GetLastRect()` because it needs at least 1 thing to be drawn before it.
        GUILayout.FlexibleSpace();

        // Get automatically aligned rect for our multi column header component.
        Rect windowRect = GUILayoutUtility.GetLastRect();

        // Here we are basically assigning the size of window to our newly positioned `windowRect`.
        windowRect.width = this.position.width;
        windowRect.height = this.position.height;

        // After compilation and some other events data of the window is lost if it's not saved in some kind of container. Usually those containers are ScriptableObject(s).
        if (this._multiColumnHeader == null)
        {
            this.Initialize();
        }

        GUIStyle groupGUIStyle = new GUIStyle(GUI.skin.box)
        {
            //padding = new RectOffset(left: 50, right: 50, top: 50, bottom: 50) // For some reason doesn't work with group.
            //border = new RectOffset(30, 30, 30, 30), // None work.
        };

        //! Here we just basically move around group. It's not really padding, we are just setting position and reducing size.
        Vector2 groupRectPaddingInWindow = new Vector2(20.0f, 20.0f);

        Rect groupRect = new Rect(source: windowRect);

        groupRect.x += groupRectPaddingInWindow.x;
        groupRect.width -= groupRectPaddingInWindow.x * 2;

        groupRect.y += groupRectPaddingInWindow.y;
        groupRect.height -= groupRectPaddingInWindow.y * 2;

        GUI.BeginGroup(position: groupRect, style: groupGUIStyle);
        {   // Group Scope.

            groupRect.x -= groupRectPaddingInWindow.x;
            groupRect.y -= groupRectPaddingInWindow.y;

            Rect positionalRectAreaOfScrollView = new Rect(source: groupRect);

            // Create a `viewRect` since it should be separate from `rect` to avoid circular dependency.
            Rect viewRect = new Rect(source: groupRect)
            {
                width = this._multiColumnHeaderState.widthOfAllVisibleColumns, // Scroll max on X is basically a sum of width of columns.
                //? Do not remove this hegiht. It's compensating for the size of bottom scroll slider when it appears, that is why the right side scroll slider appears.
                //height = groupRect.height - columnHeight, // Remove `columnHeight` - basically size of header.
            };

            groupRect.width += groupRectPaddingInWindow.x * 2;
            groupRect.height += groupRectPaddingInWindow.y * 2;

            this._scrollPosition = GUI.BeginScrollView(
                position: positionalRectAreaOfScrollView,
                scrollPosition: this._scrollPosition,
                viewRect: viewRect,
                alwaysShowHorizontal: false,
                alwaysShowVertical: false
            );
            {   // Scroll View Scope.

                //? After debugging for a few hours - this is the only hack I have found to actually work to aleviate that scaling bug.
                this._multiColumnHeaderWidth = Mathf.Max(positionalRectAreaOfScrollView.width + this._scrollPosition.x, this._multiColumnHeaderWidth);

                // This is a rect for our multi column table.
                Rect columnRectPrototype = new Rect(source: positionalRectAreaOfScrollView)
                {
                    width = this._multiColumnHeaderWidth,
                    height = columnHeight, // This is basically a height of each column including header.
                };

                // Draw header for columns here.
                this._multiColumnHeader.OnGUI(rect: columnRectPrototype, xScroll: 0.0f);

                float heightJump = columnHeight;

                // For each element that we have in object that we are modifying.
                //? I don't have an appropriate object here to modify, but this is just an example. In real world case I would probably use ScriptableObject here.
                for (int a = 0; a < this._testObjects.Length; a++)
                {
                    SerializedObject serializedObject = new SerializedObject(obj: this._testObjects[a]);

                    float calculatedRowHeight = 0.0f;

                    //! We draw each type of field here separately because each column could require a different type of field as seen here.
                    // This can be improved if we want to have a more robust system. Like for example, we could have logic of drawing each field moved to object itself.
                    // Then here we would be able to just iterate through array of these objects and call a draw methods for these fields and use this window for many types of objects.
                    // But example with such a system would be too complicated for gamedev.stackexchange, so I have decided to not overengineer and just use hard coded indices for columns - `columnIndex`.

                    Rect rowRect = new Rect(source: columnRectPrototype);

                    //rowRect.y += columnHeight * (a + 1);

                    // Name field.
                    int columnIndex = 0;

                    if (this._multiColumnHeader.IsColumnVisible(columnIndex: columnIndex))
                    {
                        int visibleColumnIndex = this._multiColumnHeader.GetVisibleColumnIndex(columnIndex: columnIndex);

                        Rect columnRect = this._multiColumnHeader.GetColumnRect(visibleColumnIndex: visibleColumnIndex);

                        // This here basically is a row height, you can make it any value you like. Or you could calculate the max field height here that your object has and store it somewhere then use it here instead of `EditorGUIUtility.singleLineHeight`.
                        // We move position of field on `y` by this height to get correct position.
                        columnRect.y = rowRect.y + heightJump;
                        //columnRect.height += heightJump;

                        GUIStyle nameFieldGUIStyle = new GUIStyle(GUI.skin.label)
                        {
                            padding = new RectOffset(left: 10, right: 10, top: 2, bottom: 2)
                        };

                        EditorGUI.LabelField(
                            position: this._multiColumnHeader.GetCellRect(visibleColumnIndex: visibleColumnIndex, columnRect),
                            label: new GUIContent(this._testObjects[a].Name),
                            style: nameFieldGUIStyle
                        );
                    }

                    // Health slider field.
                    columnIndex = 1;

                    if (this._multiColumnHeader.IsColumnVisible(columnIndex: columnIndex))
                    {
                        int visibleColumnIndex = this._multiColumnHeader.GetVisibleColumnIndex(columnIndex: columnIndex);

                        Rect columnRect = this._multiColumnHeader.GetColumnRect(visibleColumnIndex: visibleColumnIndex);

                        columnRect.y = rowRect.y + heightJump;
                        //columnRect.height += heightJump;

                        SerializedProperty serializedProperty = serializedObject.FindProperty(propertyPath: "_health");

                        calculatedRowHeight = Mathf.Max(calculatedRowHeight, EditorGUI.GetPropertyHeight(property: serializedProperty, includeChildren: true));

                        EditorGUI.Slider(
                            position: this._multiColumnHeader.GetCellRect(visibleColumnIndex: visibleColumnIndex, columnRect),
                            property: serializedProperty,
                            leftValue: 0.0f,
                            rightValue: 100.0f,
                            label: GUIContent.none
                        );
                    }

                    // Skin color field.
                    columnIndex = 2;

                    if (this._multiColumnHeader.IsColumnVisible(columnIndex: columnIndex))
                    {
                        int visibleColumnIndex = this._multiColumnHeader.GetVisibleColumnIndex(columnIndex: columnIndex);

                        Rect columnRect = this._multiColumnHeader.GetColumnRect(visibleColumnIndex: visibleColumnIndex);

                        columnRect.y = rowRect.y + heightJump;
                        //columnRect.height += heightJump;

                        SerializedProperty serializedProperty = serializedObject.FindProperty(propertyPath: "_skinColor");

                        calculatedRowHeight = Mathf.Max(calculatedRowHeight, EditorGUI.GetPropertyHeight(property: serializedProperty, includeChildren: true));

                        EditorGUI.PropertyField(
                            position: this._multiColumnHeader.GetCellRect(visibleColumnIndex: visibleColumnIndex, columnRect),
                            property: serializedProperty,
                            label: GUIContent.none
                        );
                    }

                    // Skin color field.
                    columnIndex = 3;

                    if (this._multiColumnHeader.IsColumnVisible(columnIndex: columnIndex))
                    {
                        int visibleColumnIndex = this._multiColumnHeader.GetVisibleColumnIndex(columnIndex: columnIndex);

                        Rect columnRect = this._multiColumnHeader.GetColumnRect(visibleColumnIndex: visibleColumnIndex);

                        columnRect.y = rowRect.y + heightJump;
                        //columnRect.height += heightJump;

                        SerializedProperty serializedProperty = serializedObject.FindProperty(propertyPath: "_gameObjects");

                        calculatedRowHeight = Mathf.Max(calculatedRowHeight, EditorGUI.GetPropertyHeight(property: serializedProperty, includeChildren: true));

                        EditorGUI.PropertyField(
                            position: this._multiColumnHeader.GetCellRect(visibleColumnIndex: visibleColumnIndex, columnRect),
                            property: serializedProperty,
                            includeChildren: true
                        );
                    }

                    // The problem of it drawing here is that it draws over fields instead of under them.
                    //? The soultion could be to cache height for each row after 1 OnGUI and use it instead, upading it each time it reaches the end.
                    Rect backgroundColorRect = new Rect(source: rowRect)
                    {
                        y = rowRect.y + heightJump,
                        height = calculatedRowHeight
                    };

                    // Draw a texture before drawing each of the fields for the whole row.
                    if (a % 2 == 0)
                        EditorGUI.DrawRect(rect: backgroundColorRect, color: this._darkerColor);
                    else
                        EditorGUI.DrawRect(rect: backgroundColorRect, color: this._lighterColor);

                    heightJump += calculatedRowHeight;
                }
            }
            GUI.EndScrollView(handleScrollWheel: true);
        }
        GUI.EndGroup();

        if (!this._firstOnGUIIterationAfterInitialize)
        {
            //! Uncomment this if you want to have appropriate ResizeToFit(). It brings jaggedness which I didn't like, so I have removed it knowing the implications.

            //float difference = 50.0f;

            ////! Magic number `difference` is just a number to ensure that this width won't be exceeded by this auto scale bug. Lowering this number could cause it to reappear.
            ////? If you don't mind resizing to fit to sometimes overscale columns then just remove these next 2 lines of code.
            //if (this._multiColumnHeaderWidth - this._multiColumnHeaderState.widthOfAllVisibleColumns > difference)
            //  this._multiColumnHeaderWidth -= difference;
        }

        this._firstOnGUIIterationAfterInitialize = false;
    }

    private void Awake()
    {
        this.Initialize();
    }
}
#endif

```

**Result:**
> 0 votes

---
Tags: unity
---


# Question
Title: Why are there no dynamic shadows in UE4?
So my problem is that other than for static objects which have baked shadows from building lighting, there are no shadows for movable objects, like those cubes. Neither from the Light source actor, which is stationary, nor from Point lights that are either static or moveable.

I may be wrong but I think it used to have dynamic shadows (or I didn't notice the lack of them until recently). So any ideas how to get dynamic shadows? Thank you

# Answer
> 1 votes
You will need to configure your lighting for your project as well as for your objects when you want dynamic shadows. I suggest taking a look at this lighting section for UE4: Lighting and Shadows Reference

Also, check your In-Editor Graphics quality as well as the buffer you are rendering in the Editor.

# Answer
> 0 votes
I changed my Directional Light from Stationary to Moveable and this fixed my issue, which was similar to yours.

Select your Directional Light and under the Details Tab you'll see the Transform drop down. Under the coordinates, there are 3 options, Moveable being one. Select that and, fingers crossed, it'll be the fix.

---
Tags: lighting, shadows, unreal-4, unreal
---


# Question
Title: Cant get all children using foreach and getcomponent
I am trying to get the component `CheckPointEnemy` from each child object from an array of transforms, and then add those components to a list of CheckBehaviours. However I am only receiving the first component from the first child from the array of transforms:

```
public Transform[] enemies;
public List<CheckPointEnemy> enemiesToTrigger;

foreach (Transform child in enemies)
    {
       enemiesToTrigger.Add(child.GetComponentInChildren<CheckPointEnemy>);
    }

```

I imagine I should be using GetComponentsInChildren but I can not get the syntax correct. Thank you for any help.

# Answer
> 0 votes
Did you try reading the documentation?

It's not completely clear from your code what you are trying to accomplish. It would help if you explained where this code is located and why you're doing it this way. How does the `enemies` array get populated?

1. If you're trying to get the `CheckPointEnemy` components from all children of a particular component, use:

`CheckPointEnemy[] enemiesToTrigger = GetComponentsInChildren<CheckPointEnemy>();`
2. If you're trying to find all `CheckPointEnemy` instances in the scene, use

`CheckPointEnemy[] enemiesToTrigger = GameObject.FindObjectsOfType<CheckPointEnemy>();`
3. If each child in the `enemies` list has multiple `CheckPointEnemy` children, use

```
foreach (Transform child in enemies)
{
   enemiesToTrigger.AddRange(child.GetComponentsInChildren<CheckPointEnemy>());
}

```
4. If each transform in the `enemies` array has exactly one `CheckPointEnemy` component, and you're populating the `enemies` array from the Inspector, what you are doing is pointless. You can populate `enemiesToTrigger` in the Inspector instead.

---
Tags: unity
---


title: Asset opening wrong unity version

text:
# Question
Title: Asset opening wrong unity version
I'm trying to open one of my assets in unity via my browser, but when I click open in unity it opens the 2017 version, when I want to add it to my newest one. How do i get this to work? (I need the 2017 version, so deleting it is not an option.)

# Answer
I assume you are talking about browsing the Asset Store, in which case do it within Unity, not via web browser. Go to the Window top menu, and select Asset Store.

EDIT: I was just informed in comments that the Asset Store window was removed from Unity 2020; I'm still using 2019.4 so I didn't know that.

Asset store bundles are showing up in Package Manager now, so instead of Window \> Asset Store, go to Window \> Package Manager. In the Package Manager window, there's a menu right above the list of packages that you can switch to My Assets.
> 1 votes

---
Tags: unity
---


title: Accessing enum value in other scripts

text:
# Question
Title: Accessing enum value in other scripts
I am attempting to make a global `MaterialAssign` script that I can assign to anything and have an `enum` selector in the inspector to assign a material type. This would then drive hitFX and soundFX variation in other scripts.

My selector script MaterialAssign.cs:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MaterialAssign : MonoBehaviour
{
    public enum MatSelection
    {
        defaultMat,
        metalEnemy,
        metalWall,
        dirtWall
    }
    public static MatSelection currentMat;
}

```

Attempt at usage in another script:

```
if (MaterialAssign.currentMat == MaterialAssign.MatSelection.metalEnemy)
{
    selectedHitFX = bulletMetalEnemyFX;
}
else if (MaterialAssign.currentMat == MaterialAssign.MatSelection.metalWall)
{
    selectedHitFX = bulletMetalWallFX;
}

```

I have no errors in the console BUT the enum selector doesn't show up in the inspector, so I'm assuming no value is ever passed. I read that enums can't have a static value, but not sure how to handle that.

Any assistance would be most appreciated or alternate approaches welcome! I'm purposely trying to stay away from tags, but can go down that path if needed.

# Answer
> 1 votes
> the enum selector doesn't show up in the inspector

That's because `currentMat` is a static field. Static fields never show in the inspector, because they are not associated with a specific class instance.

---
Tags: unity, c#
---


# Question
Title: How can I draw lines in editor between waypoints when creating the waypoints?
```
public List<Vector3> destinations = new List<Vector3>();
    public int numberOfDestionations;
    public float moveSpeed = 5f;
    public bool loop = false;
    public bool moveBack = false;
    public Text textCounter;

    private Coroutine movementCoroutine;
    private bool pause = false;
    private bool coroutineRunning = false;
    private Vector3 startPosition;
    private int countDestionations;

    private void Start()
    {
        for (int i = 0; i < numberOfDestionations; i++)
        {
            destinations.Add(new Vector3(UnityEngine.Random.Range(-300, 25), -1f, 0));//25, -1f, 0);
            if(i > 0)
            {
                Gizmos.DrawLine(destinations[i], destinations[i + 1]);
            }
        }

```

I'm trying to use gizmos but getting exception :

```
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

```

On line 33 :

```
Gizmos.DrawLine(destinations[i], destinations[i + 1]);

```

I want that while it's creating the vectors draw lines from the current created vector destination and the next one. A line from index 0 to index 1 to index 2 and so on. So when running the game I will see a net of all the lines connected between the vectors destinations.

# Answer
Try something like this instead. You can still initialize your destinations list in `Start`, but draw it in `OnDrawGizmos`, and make sure your index never reaches the list's current `.Count`.

```
void OnDrawGizmos() {
    // Skip drawing if we don't have at least two points to connect.
    if (destinations == null || destinations.Count < 2)
        return;

    for (int i = 1; i < destinations.Count; i++) {
        Gizmos.DrawLine(destinations[i - 1], destinations[i]);
    }
}

```
> 0 votes

---
Tags: unity, c#
---


# Question
Title: How to Change an Icon based on what Collider the Player Hits
So I have a 2D platform game where a player goes around collecting fruit but currently I only have one icon. Currently I use an image on a canvas to display the fruit image. How can I make the UI image change based on what fruit the player collects?

# Answer
First, let's make a simple data container to put on our fruit items. For now, this will contain just the image we want to display when we collect it.

```
public class Collectable : MonoBehaviour {
    public Sprite sprite;

    public void Collect() {
        // Here you can spawn a collection effect or play a sound, etc.
        Destroy(gameObject);
    }
}

```

You could expand this to contain an `enum` of the different fruit types so you can react differently to them, or maybe make a `ScriptableObject` to hold the fruit's properties and gameplay effects, and hold a reference to that (ie. the Type Object pattern).

Next we'll make a script that detects when we've collided with a collectable. Put this on your player character.

```
public class Collector : MonoBehaviour {

    // Here I assume you're using Unity 2020 or higher.
    public UnityEvent<Sprite> onCollect;
    // On older versions, declare public class CollectionEvent : UnityEvent<Sprite>{}
    // then make this a public CollectionEvent onCollect;

    void OnTriggerEnter2D(Collider2D collider) {

        // Ignore any trigger collisions that aren't collectables.
        if (!collider.TryGetComponent(out Collectable item))
            return;

        // If anyone is listening to our collection event,
        // tell them what we collected.
        if (onCollect != null) { onCollect.Invoke(item.sprite); }

        // Collect the item so it disappears.
        item.Collect();
    }
}

```

Lastly, we can have an inventory script that tracks what collectable(s) you're carrying and updates the UI accordingly.

```
public class PlayerInventory : MonoBehaviour {

    public Image itemSlot;

    public void AddItemToInventory(Sprite sprite) {
        itemSlot.sprite = sprite;

        // Do other things you need to do with the collectable,
        // like applying gameplay effects or updating a counter.
    }
}

```

This can sit in your HUD. In the `Collector` script's Inspector, set the `onCollect` event to call the `PlayerInventory` script's `AddItemToInventory()` method. Or you can wire up this link after (re)spawning the player character with `collector.onCollect.AddListener()`.

If different items have different properties, then you might want to send the `Collectable` itself through this event instead of a `Sprite`, or a `CollectableType` data structure that has the properties you need.
> 0 votes

---
Tags: unity, 2d, platform
---


# Question
Title: Set-up Android SDK path to make Android remote work in Unity
I am using the **Unity 2019.1.12**. If I go to **Edit** \> **Preferences...** \> **External Tools** it says that the **Android SDK Tools Installed with Unity (recommended)**.

Now I downloaded the **Unity Remote 5** to my Android device and try to debug a game in Editor.

But when I run the game I see the output in the Unity console which tells:

> Set-up Android SDK path to make Android remote work

So, should I unchek the check near the **Android SDK Tools Installed with Unity (recommended)**, download the Android SDK myself and provide the path to it?

Are there any other ways to fix it? Because the Unity simplified the process of the installation of the SDK and it seems very sad that I can not use the Unity Hub for this purpose.

Thank you.

So, I went to the **Unity\2019.1.12f1\modules.json** file, found the path to the Unity SDK in the file. And provided the path manually. That solved the issue. But I do not like the solution, since it is supposed by the Unity Hub that the path to the SDK will be provided automatically.

# Answer
I had the same issue, I needed to manually specify the Android SDK Tools (second checkbox). My Path is: E:\Program Files\Unity\2019.1.0f2\Editor\Data\PlaybackEngines\AndroidPlayer\SDK

Once I changed I closed out of the editor, opened Remote Player on phone (While attached to PC) and then opened my project again and it worked.

> > > > just unchecked sdk checkbox save your project close editor open unity remote to your phone open editor and run your project
> 3 votes

# Answer
I also got an issue like this, it took 2 days to solve this issue for me, but the solution is very simple,

Edit -\> Preferences -\> External tools uncheck the "Android SDK installed with unity" and then set the path to the Android SDK path manually.
> 0 votes

---
Tags: unity, android, debugging
---


# Question
Title: How to continue Lego microgame tutorial?
I was passing Lego microgame tutorial. I closed it and quit Unity. Now, how can I continue it from the same place? If I opening it's project, I am getting just silent `Unity` project, without any guidance.

# Answer
> 2 votes
As far as I can tell, **Unity tutorials doesn’t use a save/load system, or a restart system**. As Benjamin Danger Johnson said in the comments, these projects are very short and are supposed to be completed in one sitting. You will just have to start from the beginning of the chapter you were the closest in progress to. (I found some similar advice here.)

---
Tags: unity
---


# Question
Title: How to change a variable in the spawnpoint from another prefab
I refer the website for proper way of referencing the script How to call a public function from another script in Unity? but it does not work, still return a nullreference exception in the example below. Not sure how to fix it.Apart from that I also consider using

```
 int a;
public int A
{ get; set; }

```

and in HPscript using spawnpoint.A = spawnpoint.A - 1; but it come out the content is for read only.

Below is the codes I using.

I attach this code to a capsule gameobject that is use to spawn prefab gameobject,drag and drop prefab to the enemy GameObject inspector window, this part working correctly.

```
using System;
using UnityEngine;

public class Spawnpoint: MonoBehaviour
{ public GameObject Enemy;

  public int a;
  int currentstate = 0;
  int previousstate = 0;

   void Counting()
{//the below if statement is to ensure the Gameobject only spawn once when condition become true
 //in every 10seconds
    var d = DateTime.Now.Second % 10;
    if(d==0)
    {
        currentstate = 1;

    }
    else
    {
        currentstate = 0;
    }
}

void Spawn()
{//Stop spawning when Gameobject equal 5

    if (d==0&&currentstate!=previousstate)
        if(a<5)
    {
        Instantiate(Enemy, new Vector3(UnityEngine.Random.Range(0, 4), 1, UnityEngine.Random.Range(0, 4)),Quaternion.identity);
        a = a+1;
    }
}

 void Update()
{
    Counting();
    Spawn();
    previousstate = currentstate;
}

```

}

The script below is not working. I want the HPscript to deduct the value "a",in Spawnpoint script so the script will continue spawn enemy when number less than 5.This script is attached to the prefab gameobject that is place in asset folder.

```
 using System;
 using UnityEngine;

public class HPScript : MonoBehaviour
{ Spawnpoint spawnpoint;

void Start()
{
    spawnpoint = GetComponent<Spawnpoint>();
}
public void counting()
{

    var c = DateTime.Now.Second % 30;
    if(c==0)

    {

        spawnpoint.a = spawnpoint.a - 1;

        Destroy(gameObject); }
}

void Update()
{
    counting();

}

```

}

# Answer
There are a few things that can be improved, first the updated scripts. The Spawner is responsible creating new enemies. As long as you have less than 5, it spawns one every 10seconds.

```
public class Spawner : MonoBehaviour
{
    public GameObject enemy;
    public int currentlySpawned;
    [SerializeField] private int maxSpawnable = 5;
    [SerializeField] private float spawnInterval = 10f;

    void Start()
    {
        //Each spawnInterval we just call Spawn()
        InvokeRepeating("Spawn", 0f, spawnInterval);
    }

    //make this public if you want to trigger Spawning from somewhere else as well
    void Spawn() {
        if (currentlySpawned < maxSpawnable)
        {
            currentlySpawned++;
            Vector3 spawnPosition = new Vector3(Random.Range(0, 5), Random.Range(0, 5));
            //The last transform is used to put all enemies under the Spawner in the inspector for better organization
            Instantiate(enemy, spawnPosition, Quaternion.identity, transform);
        }
    }
}

```

The `Enemy` script is the same as your HPScript. It should go on the enemy prefab you have. I interpreted your script as that the enemy should die after 30sec.

```
public class Enemy : MonoBehaviour
{
    private Spawner spawner;

    void Start()
    {
       //if you have only one spawner in the scene
       spawner = FindObjectOfType<Spawner>();
       //if there are more and you want to find a specific one
       //the first `Spawner` is the name of the GameObject in the inspector where your script is on
       //spawner = GameObject.Find("Spawner").GetComponent<Spawner>();
       Invoke("SelfDestruct", 30f);
    }

    void SelfDestruct()
    {
        //short for spawner.currentlySpawned = spawner.currentlySpawned - 1;
        //other short version could be spawner.currentlySpawned -= 1;
        spawner.currentlySpawned--;
        Destroy(gameObject);
    }
}

```

Keep in mind you will always only have 3 enemies this way (since they die after 30sec and you spawn only one each 10sec), by the time you spawn the 4th, the first is dead.
> 1 votes

---
Tags: unity, c#
---


title: Isometric tilemap circle around object

text:
# Question
Title: Isometric tilemap circle around object
I am developing an isometric game like Anno 1602. I have an isometric tilemap. The default tilesize is 64x31.

My goal is to show the area a building has influence to. For that I want to show a **circle in isometric style** around that building. Look at the picture below:

I need to find an algorithm which turns information about a building (**width, height, radius in tiles**) into a polygon containing screen coordinates of the outer parts of the dark area (see picture, **I want the red points**). For example, the data for the picture above would be:

w = 2; h = 2; r = 3

I tried creating circles with midpoint algorithm for each tile of the building. Merging all points together and running concave hull algorithm to get the outer most points. But this did not yield nice results.

What could be an approach to get points to **create a polygon which resembles an isometric area around an object**.

# Answer
The best way to approach this is to get the values of the coordinates to the x axis around the object, then generate the y coordinate using some simple math.

```
function genCircle(x,y,radius,precision){ // x and y are coordinates of object
  let arr=[];
  for(let i=-radius;i<=radius;i+=precision){
    let ty=(radius**2-(i)**2)/(y);
    arr.push([i+x,ty-y]); // One half of the circle
    arr.push([i+x,-ty-y]); // Get the negative coordinates for the other
  }
  return arr; // Return an array of x and y values
}

```

The function above takes in x and y offset values, the radius of the circle, and the precision of the measurements. Simply apply this to your program and adjust the output accordingly, depending on how you process coordinates you may want to scale them to fit with the isometric perspective.
> 0 votes

---
Tags: javascript, algorithm, tilemap, isometric, phaser
---


# Question
Title: How can I efficiently load huge volumes of star systems?
I am working on a space exploration and combat game, and I can create galaxies, nebulas, solar systems, and load and unload them procedurally as needed. Meaning the stars that the player can see are exactly where they are. I have a coordinate system set up with meter-precision, meaning it's sufficient to map quite several galaxies, but also tiny missiles.

For now, I created a galaxy with 10.000.000 solar systems, and my SQLite database reached 5gb. It takes ~30 minutes to generate it, and I notice a slow-down as the size of the database increases in loading times. I did a lot of optimization, and while everything is running fine and well now, I seek to reach 200-300m solar systems if possible. The database would be stored locally on the user's drive, rather than downloaded from a server. I use a GlobalX/Y/Z (int64) and LocalX/Y/Z (double) for coordinates, and only the GlobalX/Y/Z is used to find large objects like stars and planets (I also use multiple chunk systems).

Elite Dangerous manages to store the data of 400 *billion* solar systems and has no issues with loading times, somehow. How can they display many stars in the background? How do they manage to store a lot more data than I already do?

For now, my data is quite minimalistic and comparatively minuscule in number, but they must have quite a lot of data for each stellar object even. What technical "tricks" can I employ to solve this problem in my game?

# Answer
> 32 votes
The trick Elite likely uses is that they don't pre-generate the whole galaxy and store it in a database. They likely generate most of the galaxy at runtime when it is needed.

I would do this using a pseudorandom but deterministic algorithm which can generate the properties of every object in the galaxy at runtime just from its position.

So when a player zooms into a section of the galaxy, then the galaxy chunk generation algorithm is run, which takes the chunk coordinates as input and outputs a list of stars with position, color and size. Same input always results in the same output, so when another player zooms into the same chunk later, they get the same results. You might have different algorithms for different zoom levels which each take the output of the previous algorithm into account and add more detail to it. So the algorithm on the lowest zoom factor only generates the largest stars (so you can quickly generate a view which shows the whole galaxy at once), and the closer the player zooms into any part of the galaxy, the more additional small stars get generated in that area.

Then, when the player clicks on any of these stars to zoom into its star system, the star system generation algorithm is run. Its input are color, size and galactic position of the star. Its output is a list of planets with their types, sizes and orbital parameters. It too is a deterministic algorithm so it always generates the same planets for the same star.

And then you can do the same thing with planet surfaces, cities on the planet surfaces, houses in those cities and rooms in those houses. So you end up with a galaxy with a level of detail which would take an exorbitant amount of data to store all at once. But you don't need to store it all, because any of that data can be re-calculated on demand.

A really neat tool for procedural generation algorithms like that are noise pattern algorithms like Simplex Noise or Worley Noise. You can sample them at arbitrary locations to get reproducible results. Another are standard pseudorandom number generators which can be initialized with a seed value and then always generate the same sequence of numbers for the same seed value.

All you really need to store in a database is data which can not actually be re-generated on demand:

* Parts of the galaxy which you want to design by hand
* Changes to the galaxy which are the result of player actions

First you check if any such datasets exist in your database for the requested data, and when they don't, you generate the data using the algorithms.

\__

Now you just need to come up with algorithms which generate interesting and varied results and then with game mechanics which provide an engaging and interesting game experience which benefits from all that content variety. I am looking forward to playing what you will come up with.

# Answer
> 2 votes
In addition to the points that have been made about not actually generating all the data there's another factor: You can't actually draw 10,000,000 stars. Nobody has a display that can handle it. Therefore, there's no need to have 10,000,000 stars loaded.

Select X, Y, Brightness, Color, ID from StarTable Where X \> CurrentX - 200ly And X \< CurrentX + 200ly And Y \> CurrentY - 200ly And Y \< CurrentY + 200ly.

Select X, Y, Brightness, Color, ID from BrightStarTable Where X \> CurrentX - 2000ly And X \< CurrentX + 2000ly And Y \> CurrentY - 2000ly And Y \< CurrentY + 2000ly.

That will be a tiny fraction of your total stars, but it is sufficient to draw anything you can see out the window of your starship. I would store all the details on the stars in a separate table accessed by the StarID as you only need those details when examining a particular star.

You can cut the loaded data down even more by having a DimStarTable with an even shorter query range. Most stars will be in this table.

Another option also comes to mind: Define a new variable: Sector. Sector = (int)(x/100ly) + (int)(y/100ly) * 10000. You load the sector you are in and the 8 adjoining sectors. The select would run faster. (Likewise, the bright star table would have 1000ly sectors.)

# Answer
> 1 votes
Philipp already gave a great answer, but I'll address your question about how Elite Dangerous operates their database.

> Elite Dangerous manages to store the data of 400 billion solar systems and has no issues with loading times, somehow. How can they display many stars in the background? How do they manage to store a lot more data than I already do?

1. Elite Dangerous stores the star map data that isn't procedurally generated on a server, not locally. They presumably have one or more very powerful servers, optimized for big data, with the database always loaded and running. When the player scrolls around the map or visits a new star system, the game client sends a request to the server, the server queries relevant data from the database and sends it back to the game client. Because the database is on a server, it could potentially be many terabytes in size without causing any issues for the players. They probably have very big and expensive servers developed over years by backend specialists, so this approach is unlikely to be feasible for an indie team.
2. Elite Dangerous absolutely has loading times, they just cleverly mask it with in-game mechanics. This is educated guesswork, but based on my play experience I think it works like this:

1. When you activate the hyperdrive, there's a progress bar while the hyperdrive warms up. I think this is the stage when the game client sends the request for data for the system you're about to jump to. Occasionally, this takes much longer than normal for no explicable reason - probably because the server was slow to respond to the query.
    2. During the actual hyperspace jump, the game is loading/procedurally generating the next star system, including the background skybox, based on the data it received from the server. The animation you see of your ship hurtling through hyperspace is just a very fancy loading screen.

# Answer
> -6 votes
If you have a deterministic algorithm that uses a seed, like how PRNG's work, you can store almost nothing and generate the star's positions on the fly, only keeping those that you currently need. Think how demoscene demos work.

---
Tags: unity, architecture, performance, databases, loading
---


title: What is "pixel art"?

text:
# Question
Title: What is "pixel art"?
I'm interested in working as an artist in the game industry. Many job postings contain the phrase "pixel art". **What exactly is pixel art?**

# Answer
> 13 votes
This is the kind of question that's better answered with google. Pixel art is game art that is very restricted - you are literally using pixels to draw something, so they end up having a very boxy look. (Though a lot of pixel art now is done on a much larger scale and then made to look like it's been edited pixel by pixel.)

Example:

You can see in the bottom right of this image the actual size of the art, and then the larger left portion what it looks like zoomed in. Lines and shading are implied by individual pixels put in a particular colour. (An outline, for example, is achieved by making all the pixels along the outside edge black.)

# Answer
> 6 votes
As a quick search will tell you, pixel art is digital artwork that is created by drawing individual pixels in an image rather than say, rendering a 3D model. It commonly refers to clean, cartoonish graphics reminiscent of old 2D video games.

# Answer
> 4 votes
This forum is a pretty good place to get a good idea, because they also have a forum for "low spec art", which you can compare to their "pixel art" forum and see the difference.

http://www.wayofthepixel.net/pixelation/index.php

# Answer
> 2 votes
For loads of examples, links to resources and tutorials, a thriving, friendly, no-nonsense community, pixel-art-related news, and weekly challenges, check out PixelJoint and your perspective will be forever changed.

# Answer
> 0 votes
According to Wikipedia,

> Pixel art is a form of digital art, created through the use of software, where images are edited on the pixel level. The aesthetic for this kind of graphics comes from **8-bit and 16-bit computers** and video game consoles, in addition to other limited systems such as graphing calculators. In most pixel art, the **color palette used is extremely limited in size**, with some pixel art using only two colors.

In further detail, most pixel art creators are trying to imitate the look of video games from the 80's, because it gives a "retro" feel, due to consoles of the day only being able to render images in small sizes, such as 8x8 tiles. Additionally, some pixel artists limit the amount of colors in their assets, in order to imitate the color limitations of old technology, as stated in Wikipedia.

---
Tags: art, game-industry
---


# Question
Title: Renaming Texture 2D nodes in Unity's shader graph?
I am new here so thanks for having me. I have a query regarding renaming the Texture 2D nodes I have created in my first Shader graph.

I have setup a shader graph with a normal map, base colour, smoothness and ao. These are showing up as exposed parameters which is just what I wanted so I can drag and drop new texture maps for the other materials easily (please see screen shot attached).

I would love to be able to name each of those Texture 2D maps accordingly so it is clear where each map from the assets folder needs to be dragged.

E.g The Texture node that contains the normal map is simply called 'Normal' instead of 'Texture 2D', the base colour map named 'base colour' etc. Atm I have 4 exposed parameters all called Texture 2D.

Not the most serious of issues I would agree, but I feel like I must be missing something. No sign of a 'rename' option for those nodes.

Any help very much appreciated.

Cheers

Nick

# Answer
> 1 votes
Inside the shader graph editor, there's a panel where you configure the material properties.

Double-click on the label on a property to edit its name shown in the Inspector.

In code, it will be referred to by the string in the "Reference" box below that.

# Answer
> 1 votes
My issue here was that I was adding my textures into the Shader Graph in the wrong way. I was loading each texture as a Sample Texture 2d Node and just plugging that into the Main Fragment node with the texture inputs as shown here:

Although this did display the output correctly, I was not able to drag and drop different textures into these sample nodes and access any properties for them in the blackboard. This was because I needed to create a 'Texture 2d Asset' node for each of the textures, load the textures into those and plug them into the sample texture nodes. I was then able to select 'Covert\>To Property' for the Asset nodes and therefore expose them as parameters and rename them as I initially set out to do, as shown here:

Thanks for the assistance DMGregory.

---
Tags: textures, unity-shader-graph
---


# Question
Title: How can I make OnDrawGizmos and OnDrawGizmosSelected functions to run the code inside with a button click?
```
using UnityEngine;
using System.Collections;

public class CurvedLinePoint : MonoBehaviour
{
    [HideInInspector] public bool showGizmo = true;
    [HideInInspector] public float gizmoSize = 0.1f;
    [HideInInspector] public Color gizmoColor = new Color(1, 0, 0, 0.5f);

    void OnDrawGizmos()
    {
        if (ResetLineRendererPositions.hasReseted == false)
        {
            if (showGizmo == true)
            {
                Gizmos.color = gizmoColor;

                Gizmos.DrawSphere(this.transform.position, gizmoSize);
            }
        }
    }

    //update parent line when this point moved
    void OnDrawGizmosSelected()
    {
        if (ResetLineRendererPositions.hasReseted == false)
        {
            CurvedLineRenderer curvedLine = this.transform.parent.GetComponent<CurvedLineRenderer>();

            if (curvedLine != null)
            {
                curvedLine.Update();
            }
        }
    }
}

```

Then I created two scripts one is editor type with two buttons. One to reset the linerenderer positions and one to generate the positions :

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ResetLineRendererPositions : MonoBehaviour
{
    public LineRenderer lineRenderer;
    public static bool hasReseted = false;

    public void ResetLinerendererPositions()
    {
        lineRenderer.positionCount = 0;
        hasReseted = true;
    }

    public void GenerateLineRendererPositions()
    {
        hasReseted = false;
    }
}

```

And

```
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(ResetLineRendererPositions))]
public class ResetLineRendererPositionsButton : Editor
{
    public override void OnInspectorGUI()
    {
        ResetLineRendererPositions myScript = (ResetLineRendererPositions)target;
        if (GUILayout.Button("Reset Linerenderer Positions"))
        {
            myScript.ResetLinerendererPositions();
        }

        GUILayout.Space(30);

        if (GUILayout.Button("Generate Linerenderer Positions"))
        {
            myScript.GenerateLineRendererPositions();
        }
    }
}

```

The buttons are working the problem is when I click on the button "Generate Linerenderer Positions" then I have to select the linerenderer object in the hierarchy to make it take affect and draw the gizmos.

I want that when I click the "Generate Linerenderer Positions" button it will automatic run the code in the OnDrawGizmos and OnDrawGizmosSelected functions.

# Answer
> 2 votes
> The buttons are working the problem is when I click on the button "Generate Linerenderer Positions" then I have to select the linerenderer object in the hierarchy to make it take affect and draw the gizmos.

`OnDrawGizmosSelected()` is only called by the Editor when you select that object or one of its parents. Although you could have your button call `OnDrawGizmosSelected()`, that's not what `OnDrawGizmosSelected()` is for.

Also, `OnDrawGizmos()`/`OnDrawGizmosSelected()` are only intended for drawing Gizmos and other Unity Editor markup. You should not be calling other code, such as `curvedLine.Update()`, from within either of these functions.

It seems like you should have the GUI button call `curvedLine.Update()`, rather than involving `OnDrawGizmosSelected()`.

---
Tags: unity, c#
---


# Question
Title: How to make an application architecture a global strategy game?
I am doing a global libgdx strategy, how can I properly design the architecture? So far, I'm in some kind of chaos, because there are different events that need to be shown to the player in the form of widgets.

For example, one problem is that I need to understand how the Province class will display a message that there is a hunger problem. Should it:

* immediately inside itself display a message?
* send event data to the main class of the game, which processes the data and, depending on the event, display the message or take some other action?
* do something else entirely?

I had the idea to make a separate class of events and so that all game objects create this object and pass it to the main class of the game, which handles them and decides what to do with it, and if necessary, pass it to the players.

And I read about the fact that there is a class `java.util.EventObject`. Is it worth implementing it with the help of it, or should it be implemented like that yourself? Or maybe it should be done in a completely different way?

The game is turn-based. There are separate provinces and the units move from one province to the neighboring one in 1 turn.

At the beginning of each turn, a series of windows appear in turn, notifying of certain events, for example, famine in a province or enemy troops attacked a province, etc.

There are classes of the province, the player, various UI - windows, which display information about events.

# Answer
There are many ways to get to this, and you might need several iterations over the architecture before getting it right. Because of this, this answer will be quite broad.

You could consider your game from three different points of view:

* the simulation, i.e. what happens in the game
* the 3d render of the game, i.e. the display of how is your world organized
* the UI, i.e. the actual information about what happens in the game

As such, you might want to split those three aspects of the game, and create precise communication channels between those. Let a single entry point handle the events and treat them all once per frame. This way, your UI is homogeneous (e.g. you don't want Province A concern itself to decide if it should display a non-important UI element over Province B's important UI element; you don't want to have two UI pop-ups over each other requesting user input, etc..). This way you can separate the concerns and reduce the WTFs and spaghetti code.

Using events to communicate between those layers is a good idea. The exact way you'll do this is up to you, whatever works the best for your style and your game.

So in your specific case, during the simulation step, the Province "decides" it has "hunger", then raises an event and queues it for the UI to ask it to display it to the player, and queues it to the 3d rendering to ask it to display a specific icon, or change the texture over the province. Then the UI can decide to not display the hunger message *yet* because an invasion has just happened the frame before and the Player is still being notified about it.
> 1 votes

---
Tags: libgdx, architecture, events, strategy
---


# Question
Title: How can I make transform to rotate facing the next waypoint each time reaching a waypoint?
```
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class MoveOnCurvedLines : MonoBehaviour
{
    public LineRenderer lineRenderer;
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;

    private Vector3[] positions;
    private Vector3[] pos;
    private int index = 0;
    private bool goForward = true;
    private List<GameObject> curvedLinePoints = new List<GameObject>();

    // Start is called before the first frame update
    void Start()
    {
        curvedLinePoints = GameObject.FindGameObjectsWithTag("Curved Line Point").ToList();
        transform.rotation = curvedLinePoints[1].transform.rotation;

        pos = GetLinePointsInWorldSpace();

        if (moveToFirstPositionOnStart == true)
        {
            transform.position = pos[index];
        }
    }

    Vector3[] GetLinePointsInWorldSpace()
    {
        positions = new Vector3[lineRenderer.positionCount];
        //Get the positions which are shown in the inspector
        lineRenderer.GetPositions(positions);

        //the points returned are in world space
        return positions;
    }

    // Update is called once per frame
    void Update()
    {
        if (go == true)
        {
            Move();
        }
    }

    int counter = 1;
    void Move()
    {
        Vector3 newPos = transform.position;
        float distanceToTravel = speed * Time.deltaTime;

        bool stillTraveling = true;
        while (stillTraveling)
        {
            Vector3 oldPos = newPos;
            newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);
            distanceToTravel -= Vector3.Distance(newPos, oldPos);
            if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
            {
                // when you hit a waypoint:
                if (goForward)
                {
                    bool atLastOne = index >= pos.Length - 1;
                    if (!atLastOne) index++;
                    else { index--; goForward = false; }
                }
                else
                { // going backwards:
                    bool atFirstOne = index <= 0;
                    if (!atFirstOne) index--;
                    else { index++; goForward = true; }
                }
            }
            else
            {
                stillTraveling = false;
            }
        }

        transform.position = newPos;

        counter++;
        transform.rotation = curvedLinePoints[counter].transform.rotation;
    }
}

```

There are 12 waypoints I called the List variable as curvedLinePoints. The positions array are positions between the curvedLinePoints but I want the transform to rotate facing each next curvedLinePoints point and there are 12 like this.

The way I did it with the counter is wrong and also give exception out of bound index. and I should not doing it in the Update at this place.

In the Start I tried to make the transform to point the next waypoint :

```
transform.rotation = curvedLinePoints[1].transform.rotation;

```

Not sure if it's the right way.

And I also want later to do that it will rotate smooth to the next waypoint and not just rotate at once but first how to make it rotating looking the next waypoint ?

Update, This is what I tried :

```
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class MoveOnCurvedLines : MonoBehaviour
{
    public LineRenderer lineRenderer;
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;
    public float rotSpeed;

    private Vector3[] positions;
    private Vector3[] pos;
    private int index = 0;
    private bool goForward = true;
    private List<GameObject> curvedLinePoints = new List<GameObject>();
    private int numofposbetweenpoints;

    // Start is called before the first frame update
    void Start()
    {
        curvedLinePoints = GameObject.FindGameObjectsWithTag("Curved Line Point").ToList();
        transform.rotation = curvedLinePoints[1].transform.rotation;

        pos = GetLinePointsInWorldSpace();

        numofposbetweenpoints = pos.Length / curvedLinePoints.Count;

        if (moveToFirstPositionOnStart == true)
        {
            transform.position = pos[index];
        }
    }

    Vector3[] GetLinePointsInWorldSpace()
    {
        positions = new Vector3[lineRenderer.positionCount];
        //Get the positions which are shown in the inspector
        lineRenderer.GetPositions(positions);

        //the points returned are in world space
        return positions;
    }

    // Update is called once per frame
    void Update()
    {
        if (go == true)
        {
            Move();
        }
    }

    int counter = 0;
    int c = 1;
    void Move()
    {
        Vector3 newPos = transform.position;
        float distanceToTravel = speed * Time.deltaTime;

        bool stillTraveling = true;
        while (stillTraveling)
        {
            Vector3 oldPos = newPos;
            newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);
            distanceToTravel -= Vector3.Distance(newPos, oldPos);
            if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
            {
                // when you hit a waypoint:
                if (goForward)
                {
                    bool atLastOne = index >= pos.Length - 1;
                    if (!atLastOne)
                    {
                        index++;
                        counter++;
                        if (counter == numofposbetweenpoints)
                        {
                            c++;
                            Vector3 targetDirection = (curvedLinePoints[c].transform.position - transform.position).normalized;
                            curvedLinePoints[c].transform.rotation = Quaternion.LookRotation(targetDirection);
                            transform.rotation = Quaternion.RotateTowards(transform.rotation, curvedLinePoints[c].transform.rotation, Time.deltaTime);

                            counter = 0;
                        }
                        if (c == curvedLinePoints.Count - 1)
                        {
                            c = 0;
                        }
                    }
                    else { index--; goForward = false; }
                }
                else
                { // going backwards:
                    bool atFirstOne = index <= 0;
                    if (!atFirstOne) index--;
                    else { index++; goForward = true; }
                }
            }
            else
            {
                stillTraveling = false;
            }
        }

        transform.position = newPos;
    }
}

```

but the rotation part is not working good.

This part not making the transform to rotate smooth facing the next waypoint :

```
Vector3 targetDirection = (curvedLinePoints[c].transform.position - transform.position).normalized;
curvedLinePoints[c].transform.rotation = Quaternion.LookRotation(targetDirection);
transform.rotation = Quaternion.RotateTowards(transform.rotation, curvedLinePoints[c].transform.rotation, Time.deltaTime);

```

If I'm just making LookAt it will face the next waypoint but not smooth with speed factor just will cut rotating facing the next waypoint :

```
transform.LookAt(curvedLinePoints[c].transform, Vector3.up);

```

And I want it to rotate nicer smooth with speed.

# Answer
To immediately look directly at a target, you want Transform.LookAt()

```
transform.LookAt(curvedLinePoints[index], Vector3.Up);

```

For smooth rotation, it's a little more complicated:

```
Quaternion targetRotation = Quaternion.LookRotation(curvedLinePoints[index] - transform.position, Vector3.up);
float rotateSpeed = 90; //degrees per second, adjust as needed
Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, rotateSpeed * Time.deltaTime);
transform.rotation = newRotation;

```

Both of these things should have been easy to find through web searches and by reading the documentation.
> 1 votes

---
Tags: unity, c#
---


# Question
Title: Should a server run all maps in one loop, or a thread/game loop per map?
I'm working on a real time multiplayer browser-based game.

The game is top down on variable size tile based maps. There is no central map where all players come together, the entire game plays out in multiple maps. (Player chooses one on login, but has the ability to switch whenever they want). Let's take the following loop that runs on the server side of things:

```
let tick_time = Duration::from_millis(500); // e.g. Tick 2 times per second.
let mut next_tick = Instant::now();

loop {
    let now = Instant::now();

    if now >= next_tick {
        // Parse user input
        // Update state
        // Update to state to users in map

        next_tick += tick_time;
    } else {
        let wait_time = next_tick - now;
        sleep(wait_time - Duration::from_millis(1)).await;
    }
}

```

In my 'map based' gameplay scenario, would it make sense to spawn a thread for every map where one of these loops runs? Or would it be recommended to have only a singular thread with a singular game loop that updates every map? Or is there perhaps a better, already existing, pattern for this?

# Answer
> 2 votes
To ensure you don't schedule too much work in a single thread, I'd recommend using a server-side thread pool for this. Otherwise you may overrun your time budget per "tick".

Threads in the thread pool are assigned to calculate one "tick" of each client's map. Let's say you have 4 threads and 10 clients. The thread pool starts off this server "cycle" (let's call it a game turn, for all players/clients) with 4 available threads. These 4 are immediately each assigned a map to work on (say maps \[0\]-\[3\]).

As each client's map \[0\]-\[3\] completes, its associated thread is returned to the thread pool, i.e. it is now considered freed up for use. A trigger / event / callback fires that notifies that the thread pool has just gained an free thread. Your code subscribes to that event and uses it to assign that free thread to the next client map that needs processing, say for example map \[4\]. This will happen out of order, as and when each of threads \[0\]-\[3\] complete. This goes on until all client maps have been processed for this game turn, and by this point all threads are returned to the pool, ready for the next game turn to begin.

**Timing**

This depends very much on your setup, which only you will know all the details of.

Note that the above is not a loop, but a single cycle of a loop. You will repeat this sequence either based on a a loop in your own code that only does processing every x fractions of a second (sleeps or delays in between), or it may be run by an event loop running on the server (such as via `setInterval` in Node.js).

In a **lockstep** game server OTOH, you would actually do nothing at all until every single client has signalled (replied) to the server, saying that they have received the map data and that it checks out OK. Maybe they will also need to report their transformations to the map, to the server, meaning they will need to do their own processing phase first, and return their changes to the server. Only at this stage, can the server run the next tick.

---
Tags: software-engineering, game-loop, server, multithreading, rust
---


# Question
Title: How do mipmapping, anti-aliasing and anisotropic filtering contribute to rendering quality?
To my understanding, mipmaps exist to save on computations and memory when textures are far away. In an ideal world, we wouldn't want them. We'd just use the same high quality textures far away and not care about wasted resources.

But in reality, we need anisotropic filtering to smooth the disconnect between varying LOD mipmaps (or so I think).

However, do images using mipmaps with anisotropic filtering look better than no mipmaps without anisotropic filtering? See here (the first image looks worse than the third even though the first has no mipmaps). Is it because anisotropic filtering has anti-aliasing built in? And if we didn't have mipmaps, but added anti-aliasing, would the resulting image look better?

# Answer
Firstly, texture filtering and anti aliasing are two different ways of improving image quality. You can apply them both independently.

Anti aliasing is primarily done to smooth the joins where two separate triangles overlap. Depending on how it's done it can also benefit texturing quality indirectly too.

Texture filtering is done to improve the image quality inside each triangle.

Mip mapping is done to make texture filtering efficient. To take it to extremes let's say you had a GPU that could filter textures perfectly without mip maps. If you had a square textured with a 1024x1024 texture that occupied a single pixel on screen, that theoretical GPU would have to read all of the 1,048,576 pixels in the texture to work out the colour of that one pixel on screen. With a mip map it can read one pixel from the smallest mip level to do the same thing and get the same result.

Of course in reality without mip maps a GPU will actually only look at a very small number of pixels in the texture it's sampling (four of them with bilinear filtering, one with point filtering). This generally causes the result to be very noisy, and also gives a performance hit because of cache misses as those pixels are scattered all over the texture. The only places where it can be sensible not to use mip maps are for things like 2D sprites where you don't scale the image significantly.

The cost of adding a mip map to a texture is that it gets about 33% bigger, which is a relatively low memory overhead given the benefits.

Anisotropic filtering kicks in if instead of one pixel in that previous example it was say a 1x8 pixel square. What happens if you use the 1x1 mip level is that the result has no detail and looks blurry. However the 8x8 mip level has 64 pixels in it, which need to map to 8 pixels on screen. With anisotropic filtering the GPU will read some extra pixels from a bigger mip level to make the result less blurry. Reading those extra pixels has a performance cost compared to bilinear or trilinear filtering.

In a more realistic scene the anisotropic filtering makes things that aren't square on to the camera like floors less blurry.

Image is from http://en.wikipedia.org/wiki/Anisotropic\_filtering
> 13 votes

# Answer
> In an ideal world, we wouldn't want them. We'd just use the same high quality textures far away and not care about wasted resources.

Not really. If we forget about wasted resources and use fast enough machines, simple sampling of the textures, with e.g. bilinear filtering, will result in what is known as aliasing. In particular, this will look like noise in the areas where the texture is effectively downsampled. See e.g. faraway part of the pavement in the following scene (click to see in 100% scale to avoid blurring):

This noise will also flicker badly on slightest motion of the camera.

In a *really* ideal world we would fight this problem of texture aliasing (and all other aliasing problems, e.g. jagged edges of polygons) with supersampling applied to the full scene. With this technique applied, the scene above would look like this:

Now, our world is not *really* ideal. Moreover, it's not even *slightly* ideal :) In particular, supersampling is very demanding on GPU. It basically means rendering the same scene N times, where N is the number of samples per pixel (usually N=16 is a good enough figure for polygon edges, not so good for textures).

Mip mapping is a technique that aims to *approximate* the ideal result of supersampling by downsampling the textures in steps, reducing their size 2× at a time, and then sampling from the closest mip level (or using weighted average of two closest, via linear interpolation). When generating the mip map, each downsampling step is done in a high-quality way, avoiding aliasing. This reduces noise and generally works satisfactorily for objects whose sides don't differ too much in level of detail.

But in computer games and some other kinds of graphics software, inclined surfaces like e.g. roads appear quite often. The result is that, although in one dimension the texture is squeezed, its other dimension's squeezing coefficient is much smaller. The result is that the above scene gets approximated poorly. The noise does get removed, but blurriness is excessive:

Anisotropic filtering is a modification of mip mapping, where sizes of each mip level get applied separately to width and to height of the image, yielding combinations of different widths and heights in the resulting mip map. This takes considerably more space than normal mip map (up to 4× the original texture), but the result is a drastic increase of image quality. The texture rendering becomes comparable to the supersampled result:
> 5 votes

---
Tags: graphics, antialiasing, mipmaps, filtering
---


# Question
Title: Unity3D: Download multiple files and implement a callback
```
IEnumerator GetFileRequest(List<String> urlList, Action<List<UnityWebRequest>> callback)
{
    List<UnityWebRequest> reqList = new List<UnityWebRequest>();
    for (int i = 0; i < urlList.Count; i++)
    {
        using (UnityWebRequest req = UnityWebRequest.Get(urlList[i]))
        {
            req.downloadHandler = new DownloadHandlerFile(GetFilePath(urlList[i]));
            reqList.Add(req);
        }
    }
        yield return reqList;

    callback(reqList);
}

```

I'm using this code, all files get downloaded, but they seem to be corrupted ( I guess it's not completely downloaded). How do I complete the download without files getting corrupted?

# Answer
> 1 votes
You can use this class to easily download multiple files at a time.

Below is an example of using this downloader (which uses UnityWebRequest) to download multiple files with callbacks. A full example is at the repo provided above:

```
GroupDownloader downloader = new GroupDownloader();

downloader.PendingURLS.Add("www.google.com/image/someimage.jpg");
downloader.OnURIToFilename["www.google.com/image/someimage.jpg"] = "myimage.jpg";
downloader.AbandonOnFailure = false;

downloader.OnDownloadSuccess += (bool completed, string uri, string fileResultPath) => {

                       Debug.Log("Success! " + (completed ? "COMPLETED : "INCOMPLETE") + ");
                       Debug.Log( "URI=" + uri + ", filePath=" + fileResultPath");
              }

downloader.OnDownloadFail += (bool completed, string uri, string fileResultPath) => {

                       Debug.Log("Done downloading: " + completed");
                       Debug.Log("Failure. URI=" + uri + ", fileResultIfDownloaded=" + fileResultPath");
              }

/* Starts the download*/
downloader.Download();

```

---
Tags: unity, c#, networking, coroutines, callbacks
---


# Question
Title: Is it possible to use nav-mesh in 2d game in Unity?
I'm working on game that needs navigation and obstacle avoidance. I've used nav-mesh on 3d project before but now I'm trying to use it in 2d sprite game but it seems like it doesn't work.

I want to know if really it doesn't work and, if it doesn't, what would be a good replacement for a 2d project for the navigation of entities.

I'm looking for free tools.

# Answer
You cannot use the Unity Navmesh in 2D, you would have to write your own. As far as I know, there are no free nav mesh tools available.

Alternatively, you could use a Nodal Pathfinding approach, as detailed here:

http://www.jgallant.com/nodal-pathfinding-in-unity-2d-with-a-in-non-grid-based-games/
> 5 votes

# Answer
In case anyone Googles this later, you CAN use nav meshes in Unity. I'm using unity 2018.2 and set up a navmesh in a purely 2D top down tilemap game I'm working on.

Check this thread in the Unity forum: https://forum.unity.com/threads/2d-navmesh-pathfinding.503596/

Relevant posts start at #14. Fortunately, the poster created a repo for the code on GitHub: https://github.com/h8man/NavMeshPlus

It comes with a PDF Howto explaining how to use the script to bake your NavMesh.

The important part to remember is that the NavMesh works on the XZ based grid, which means that once you've set up the NavMesh and added the NavMeshAgent to the game object acting as an agent, NavMeshAgent will rotate the agent x=90, putting them perpendicular to your 2D XY grid.

The easiest way I found to deal with that is to add an internal object to the agent and set its rotation to x=-90 to negate the NavMeshAgent rotation.

Do NOT try setting the Grid swizzle to anything other than XYZ or the Nav Mesh Surface 2d will not bake correctly.

Once you've adjusted the agent's rotation, using NavMeshAgent's SetDestination works as it should. My agents are happily chasing my player object around in 2D with no issues.
> 13 votes

# Answer
As already answered the navmesh does not work in 2D, but you can fake it by creating a 3D scene with just colliders, set an orthographic camera from above and attaching sprites to the 3D objects.
> 3 votes

# Answer
Bake the Navmesh onto your scene (xz) and emit all things to 2D (xy).
ref: Navmesh2D concept
> 2 votes

# Answer
I know this thread is a bit dated, but I thought I'd pass this information as it helped me. NavMesh2d works great. I've used it in previous projects and even am using it now.

You can find it at: https://github.com/h8man/NavMeshPlus

This dude does a great job explaining how to set it up https://www.youtube.com/watch?v=W-NIYi1t16Q
> 1 votes

---
Tags: unity, path-finding, navmesh
---


# Question
Title: How to convert Unreal Engine 4 spline to a bezier curve?
I have read the source code of `USplineComponent` and found that for a curve in Unreal, the result is calculated via `FMath::CubicInterp`:

```

/**
 * Performs a cubic interpolation
 *
 * @param  P - end points
 * @param  T - tangent directions at end points
 * @param  Alpha - distance along spline
 *
 * @return  Interpolated value
 */
template< class T, class U >
static FORCEINLINE_DEBUGGABLE T CubicInterp( const T& P0, const T& T0, const T& P1, const T& T1, const U& A )
{
    const float A2 = A  * A;
    const float A3 = A2 * A;

    return (T)
           (((2*A3)-(3*A2)+1) * P0)
         + ((A3-(2*A2)+A) * T0)
         + ((A3-A2) * T1)
         + (((-2*A3)+(3*A2)) * P1);
}

```

You can follow the logic in USplineComponent::Draw to be convinced.

And the calculation approach above is the same as the cubic hermite spline:

$$ \boldsymbol{p}(t) = (2t^3-3t^2+1)\boldsymbol{p}\_0 + (t^3-2t^2+t)\boldsymbol{m}\_0 + (-2t^3+3t^2)\boldsymbol{p}\_1 +(t^3-t^2)\boldsymbol{m}\_1 $$

Then the problem becomes how to convert a *cubic hermite spline* to a *bezier curve*.

I have tried several conversion methods on SO:

https://stackoverflow.com/a/1099357/3427520
https://stackoverflow.com/a/42587252/3427520
https://stackoverflow.com/a/42590480/3427520

But all failed to get a correct bezier curve as USD that can be correctly rendered by Houdini.

But what I have been worrying most is that `USplineComponet` is not a cubic hermite spline. I'm not sure since I knew few about curve math, even after reading some introduction of curve wiki, PDFs and articles.

The bezier curve data to USD bezier-basis curve procedure may also fail, I don't have a solution to verify converted bezier curve is correct (can generate the same shape in UE4) or not.

# Answer
All you need to do is rearrange the formula:

$$\begin{align} P(t) &= (2t^3 - 3t^2 + 1) P\_0 \\ &+ (t^3 - 2t^2 + t) T\_0 \\ &+ (t^3 - t^2) T\_1 \\ &+ (-2t^3 + 3t^2)P\_1 \\ \\ &= (-t^3 + 3t^2 - 3t + 1) P\_0 + (3t^3 - 6t^2 + 3t) P\_0 \\ &+ (3t^3 - 6t^2 + 3t) \frac 1 3 T\_0 \\ &+ (-3t^3 + 3t^2) \frac {-1} 3 T\_1\\ &+ (t^3) P\_1 + (-3t^3 + 3t^2) P\_1\\ \\ &= (-t^3 + 3t^2 - 3t + 1) P\_0 \\ &+ (3t^3 - 6t^2 + 3t)(P\_0 + \frac 1 3 T\_0) \\ &+ (-3t^3 + 3t^2)(P\_1 - \frac 1 3 T\_1) \\ &+ (t^3) P\_1 \\ \\ &= (1 - t)^3 P\_0 \\ &+ 3(1 - t)^2 t (P\_0 + \frac 1 3 T\_0) \\ &+ 3(1 - t)t^2(P\_1 - \frac 1 3 T\_1) \\ &+ t^3 P\_1 \\ \end{align}$$

Now we have it in cubic Bézier form.

So your four control points are:

$$\begin{align} A &= P\_0\\ B &= P\_0 + \frac 1 3 T\_0\\ C &= P\_1 - \frac 1 3 T\_1\\ D &= P\_1 \end{align}$$
> 1 votes

# Answer
As RFairey mentioned, I found the handles in UE4 one-third the length of the Bezier equivalents in other programs like Photoshop and Inkscape. This meant by making them three times longer, the curves would match. This is shown below in all but the bottom right of the image where I intentionally left the handles the same length to show the mismatch.

**Edit** (19 Feb 21): I found a Editor preference called "Spline Tangent Scale" which defaults to 1, so dropping that to 0.33 now has the spline handle lengths matching.
> 1 votes

---
Tags: unreal-4, curves, beziers
---