/// <summary>
        /// Add a new command with names separated by folders/namespaces, last is command name, others are holders.
        /// These will be made as required
        /// during the add.
        /// </summary>
        /// <param name="names">separated command name e.g. Physics.gravity is now {"Physics","gravity"}</param>
        /// <param name="callback">action of the command to add</param>
        /// <param name="helpText">help text to show to user about the command</param>
        /// <param name="command_index">used in the recursion, indicates current depth in names array</param>
        public void Add(string[] names, Console.CommandCallback callback, string helpText, int command_index = 0)
        {
            if (names.Length == command_index)
            {
                Command = new ConsoleCommandData {
                    localName = names.Last(), callback = callback, help = helpText
                };
                return;
            }

            string token      = names[command_index];
            string lowerToken = token.ToLowerInvariant();

            if (!subCommandsLookUp.ContainsKey(lowerToken))
            {
                ConsoleCommandData data = new ConsoleCommandData
                {
                    localName = token
                };
                subCommandsLookUp[lowerToken] = new ConsoleCommandTreeNode(this, data);
            }
            subCommandsLookUp[lowerToken].Add(names, callback, helpText, command_index + 1);
        }
        /// <summary>
        /// Check for compatibility with the variable in question, generate and add the closure. If no params are given it will act as a get,
        /// if params are given it will attempt to use them as a set.
        ///
        /// Wrap the functionality that is DAMN NEAR identical for fields and properties so we don't have to maintain two versions in 2 locations
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="field"></param>
        /// <param name="property"></param>
        /// <param name="finalName"></param>
        private static void PropAndFieldInternalHelper(object instance, FieldInfo field, PropertyInfo property, string finalName)
        {
            Type   paramType;
            string name;
            ICustomAttributeProvider attrProv;

            if (field != null)
            {
                paramType = field.FieldType;
                name      = field.Name;
                attrProv  = field;
            }
            else
            {
                paramType = property.PropertyType;
                name      = property.Name;
                attrProv  = property;
            }

            if (!StringToType.IsSupported(paramType))
            {
                OnErrorLogDelegate(string.Format("Cannot generate variable wrapper on {0}, type {1} is not supported.", name, paramType.Name));
                return;
            }

            //fancy wrapper goes here that returns value safely on no params and tries to convert on 1 param
            Console.CommandCallback wrappedFunc = (string stringIn) =>
            {
                //do they want to set
                if (!string.IsNullOrEmpty(stringIn))
                {
                    object parameter = StringToType.TryGetTypeFromString(paramType, stringIn);

                    if (parameter != null)
                    {
                        //use it as a set
                        if (field != null)
                        {
                            field.SetValue(instance, parameter);
                            //log new val
                            Console.Log("=" + field.GetValue(instance).ToString());
                        }
                        else
                        {
                            if (property.CanWrite)
                            {
                                property.SetValue(instance, parameter, null);
                                if (property.CanRead)
                                {
                                    Console.Log("=" + property.GetValue(instance, null).ToString());
                                }
                            }
                            else
                            {
                                Console.Log(property.Name + " cannot be set.");
                            }
                        }
                    }
                }
                else
                {
                    //get only
                    if (field != null)
                    {
                        Console.Log("=" + field.GetValue(instance).ToString());
                    }
                    else
                    {
                        if (property.CanRead)
                        {
                            Console.Log("=" + property.GetValue(instance, null).ToString());
                        }
                        else
                        {
                            Console.Log(property.Name + " cannot be read.");
                        }
                    }
                }
            };

            var attrs = attrProv.GetCustomAttributes(typeof(ConsoleCommandAttribute), false) as ConsoleCommandAttribute[];
            var attr  = attrs.Length > 0 ? attrs[0] : null;

            Console.RegisterCommand(finalName, attr != null ? attr.help : "Expects " + paramType.ToString(), wrappedFunc);
        }