Unity实现给货架自动填充货物

一、需求分析

①需要实现给货架按照每列填充货物,一直填满整个货架。

②每个货架上的货物都有指定的唯一编号:比如我们现在的是01货架(一个货架分为左右两边,其中左边的部分的货架为01右边的货架为02;有一个货架深度默认为01;货物按照层列摆放,从下往上数分别为0001层、0002层、0003层以此类推;列从外向里分别为0001列、0002列、0003列【注意关于层与列的数字一位时前面有3个0,两位为2个0,三位为1个0依次类推】);比如01货架左边部分有深度第一层第一列的编号为【01010100010001】。

③每个生成的货物都是作为货架这个物体的子物体。

二、思路设计

①我们首先需要有一个初始的货物作为相对的货物生成位置参考;

②需要计算出每层、每列货物的间隔是多少;

③得到初始的货物然后其他的货物就是每次都实例化一个该货物出来,且指定对应的位置和名称即可;

①我们先以生成1层为例进行测试,然后在以1列生成为例进行测试;

②合并起来同时生成多层和多列内容;

三、代码实现

项目工程地址:货物自动生成到货架上项目工程

①核心逻辑代码

/***
*	Title: 三维可视化
*	主题 : 自动生成货格
*	Description: 
*	功能 : 
*	      1、实现根据初始的货格物体自动生成所有的货格物体
*	      2、实现给所有自动生成的货格物体自动根据规则编号
*	      3、可以根据货格的名称查找到对应的货格
*	Date:  2020-04-10
*	Version:  1.2
*	Author:  Coffee
*	Modify Recoder:  
*/

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

namespace Control
{
	public class AutoGenerateGoodsGrid : MonoBehaviour
	{

        #region   基础参数

        //需要生成的货格
        [Header("需要生成的货格物体")]
        public Transform goodsGrid;
        //需要生成物体的父物体
        [Header("需要生成物体的父物体")]
        public Transform parentObj;

        //生成货格的间距
        [Header("生成货格的间距")]
        public Vector3 goodsSpace = new Vector3(-3.5f, 2.1f,-2.2f);

        /*货架规格*/
        [Header("层")]
        public int row = 11;
        [Header("列")]
        public int col = 39;

        /*货物生成的轴向*/
        [Header("层对应的生成轴向")]
        public Axis rowAxis = Axis.Z;
        [Header("列对应的生成轴向")]
        public Axis colAxis = Axis.Y;
        [Header("对面货架生成轴向")]
        public Axis oppositeSelfAxis = Axis.X;

        /*初始定位物体的基础信息*/
        private Vector3 _InitObjPosition;
        private Quaternion _InitObjRotation;
        private Vector3 _InitObjScale;

        /*生成的所有货格*/
        private List<Transform> allGoodsCell = new List<Transform>();
        //测试使用
        [Header("当前需要查询的货格名称")]
        public string curGoodsCellName = "";

        #endregion


        #region   Unity自带方法

        private void Start()
        {
            //获取到初始货物的位置信息
            GetInitObjPos(goodsGrid);
        }

        private void Update()
        {
            //生成物体
            if (Input.GetKeyDown(KeyCode.P))
            {
                Debug.Log("开始生成物体【按层生成】");
                GenarateOneRowObj(goodsGrid,parentObj, rowAxis, col, goodsSpace.z);
            }

            //生成物体
            if (Input.GetKeyDown(KeyCode.O))
            {
                Debug.Log("开始生成物体【按列生成】");
                GenarateOneColObj(goodsGrid, parentObj, colAxis, row, goodsSpace.y);
            }

            if (Input.GetKeyDown(KeyCode.I))
            {
                Debug.Log("生成整个货架的物体");
                string strTunnelName = GenarateTunnelName(1,Direction.Left,1);
                GenarateGoodsshelvesObj(goodsGrid, parentObj, strTunnelName, oppositeSelfAxis,0, rowAxis, col, goodsSpace.z,colAxis, row, goodsSpace.y);
            }

            if (Input.GetKeyDown(KeyCode.U))
            {
                Debug.Log("生成整个货架的物体");
                GenarateGoodsshelvesObj(goodsGrid, parentObj, col, goodsSpace.z, row, goodsSpace.y);
            }

            if (Input.GetKeyDown(KeyCode.Y))
            {
                Debug.Log("生成对面货架的物体");
                GenarateOneObj_X(goodsGrid, parentObj, oppositeSelfAxis, goodsSpace.x);
            }

            if (Input.GetKeyDown(KeyCode.T))
            {
                Debug.Log("生成对面货架的所有货物物体");
                string strTunnelName = GenarateTunnelName(1, Direction.Right, 1);
                GenarateGoodsshelvesObj(goodsGrid, parentObj, strTunnelName, oppositeSelfAxis, goodsSpace.x, rowAxis, col, goodsSpace.z, colAxis, row, goodsSpace.y);
            }


            if (Input.GetKeyDown(KeyCode.Q))
            {
                Transform str =  QueryGoodsCellOfName(curGoodsCellName);
                Debug.Log("当前为查询的货格为:"+str.name);
                str.gameObject.SetActive(false);

                //打印所有的货物
                if (allGoodsCell != null && allGoodsCell.Count > 0)
                {
                    Debug.Log("总共有货格:" + allGoodsCell.Count + " 个");
                    foreach (var item in allGoodsCell)
                    {
                        Debug.Log(item.name);
                    }
                }
            }

        }

        #endregion

        #region   公有方法

        //给货架生成所有的货格
        public void GenarateAllGoodsCell()
        {
            Debug.Log("生成【左侧】货架的所有货物物体");
            string leftTunnelName = GenarateTunnelName(1, Direction.Left, 1);
            GenarateGoodsshelvesObj(goodsGrid, parentObj, leftTunnelName, oppositeSelfAxis, 0, rowAxis, col, goodsSpace.z, colAxis, row, goodsSpace.y);

            Debug.Log("生成【右侧】货架的所有货物物体");
            string rightTunnelName = GenarateTunnelName(1, Direction.Right, 1);
            GenarateGoodsshelvesObj(goodsGrid, parentObj, rightTunnelName, oppositeSelfAxis, goodsSpace.x, rowAxis, col, goodsSpace.z, colAxis, row, goodsSpace.y);
        }

        /// <summary>
        /// 根据货格名称查找货格
        /// </summary>
        /// <param name="CurGoodsCellName">当前货格名称</param>
        /// <returns>返回当前的货格</returns>
        public Transform QueryGoodsCellOfName(string CurGoodsCellName)
        {
            Transform tra = null;
            if (!string.IsNullOrEmpty(CurGoodsCellName) &&
                allGoodsCell!=null && allGoodsCell.Count>0)
            {
                foreach (var item in allGoodsCell)
                {
                    if (item.name.Equals(CurGoodsCellName))
                    {
                        tra = item;
                        break;
                    }

                }
            }
            return tra;
        }

        #endregion


        #region   私有方法

        /// <summary>
        /// 1-获取到初始物体的位置信息
        /// </summary>
        /// <param name="obj">初始定位的物体</param>
        private void GetInitObjPos(Transform obj)
        {
            if (obj != null)
            {
                _InitObjPosition = obj.transform.position;
                Debug.LogFormat("X:{0}Y:{1}Z:{2}", _InitObjPosition.x, _InitObjPosition.y, _InitObjPosition.z);
                _InitObjRotation = obj.transform.rotation;
                Debug.LogFormat("X:{0},Y:{1},Z:{2},W:{3}", _InitObjRotation.x, _InitObjRotation.y, _InitObjRotation.z, _InitObjRotation.w);
                _InitObjScale = obj.transform.localScale;
                Debug.LogFormat("X:{0}Y:{1}Z:{2}", _InitObjScale.x, _InitObjScale.y, _InitObjScale.z);

                //禁用该物体
                obj.gameObject.SetActive(false);
            }
            else
            {
                Debug.LogError(GetType()+ "/GetInitObjPos()/获取到初始货物的位置信息失败!请检查初始定位物体是否为空");
            }
        }


        /// <summary>
        /// 2-生成货物
        /// </summary>
        /// <param name="needGenerateObj">需要生成的物体预设</param>
        /// <param name="generateObjParent">需要生成物体的父物体</param>
        /// <returns></returns>
        private Transform GenerateObj(Transform needGenerateObj, Transform generateObjParent)
        {
            Transform tra = null;
            if (needGenerateObj!=null && generateObjParent!=null)
            {
                //1-实例化物体
                tra = Instantiate(needGenerateObj);
                //2-指定实例化物体的父物体
                tra.transform.parent = generateObjParent;
                //3-给生成的物体指定位置
                tra.position = _InitObjPosition;
                tra.rotation = _InitObjRotation;
                tra.localScale = _InitObjScale;
                //激活该物体
                tra.gameObject.SetActive(true);
            }
            return tra;
        }

        /// <summary>
        /// 3-根据轴向生成物体【单个轴向】
        /// </summary>
        /// <param name="needGenerateObj">需要生成的物体预设</param>
        /// <param name="generateObjParent">需要生成物体的父物体</param>
        /// <param name="axis">物体生成的轴向</param>
        /// <param name="space">物体生成的间隔</param>
        private void GenarateObjOfAxis(Transform needGenerateObj, Transform generateObjParent,Axis axis,float space)
        {
            Transform tra = null;
            switch (axis)
            {
                case Axis.X:
                    tra = GenerateObj(needGenerateObj, generateObjParent);
                    tra.position = new Vector3(tra.position.x + space, tra.position.y, tra.position.z);
                    break;
                case Axis.Y:
                    tra = GenerateObj(needGenerateObj, generateObjParent);
                    tra.position = new Vector3(tra.position.x, tra.position.y + space, tra.position.z );
                    break;
                case Axis.Z:
                    tra = GenerateObj(needGenerateObj,generateObjParent);
                    tra.position =new Vector3(tra.position.x,tra.position.y,tra.position.z + space);
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 4-根据轴向生成物体【第一个轴向是指定货物生成在那边货架】【第二、三个轴向是指定货物生成在货架层、列的轴向】
        /// </summary>
        /// <param name="needGenerateObj">需要生成的物体预设</param>
        /// <param name="generateObjParent">需要生成物体的父物体</param>
        /// <param name="oppositeSelfAxis">物体生成在那边货架的轴向</param>
        /// <param name="oppositeSelfSpace">物体生成在指定货架的间隔</param>
        /// <param name="rowAxis">物体生成的【层轴向】</param>
        /// <param name="rowSpace">物体生成的【层间隔】</param>
        /// <param name="colAxis">物体生成的【列轴向】</param>
        /// <param name="colSpace">物体生成的【列间隔】</param>
        private Transform GenarateObjOfAxis(Transform needGenerateObj, Transform generateObjParent, Axis oppositeSelfAxis,float oppositeSelfSpace, Axis rowAxis, float rowSpace,Axis colAxis,float colSpace)
        {
            Transform tra = GenerateObj(needGenerateObj, generateObjParent);

            float oppositeSelfAxisValue=0;
            switch (oppositeSelfAxis)
            {
                case Axis.X:
                    oppositeSelfAxisValue= tra.position.x + oppositeSelfSpace;
                    break;
                case Axis.Y:
                    oppositeSelfAxisValue = tra.position.y + oppositeSelfSpace;
                    break;
                case Axis.Z:
                    oppositeSelfAxisValue = tra.position.z + oppositeSelfSpace;
                    break;
                default:
                    break;
            }
            float rowValue=0;
            switch (rowAxis)
            {
                case Axis.X:
                    //待验证
                    //rowValue = tra.position.x + rowSpace;
                    break;
                case Axis.Y:
                    //待验证
                    //rowValue = tra.position.y + rowSpace;
                    break;
                case Axis.Z:
                    rowValue = tra.position.z + rowSpace;
                    break;
                default:
                    break;
            }
            float colValue=0;
            switch (colAxis)
            {
                case Axis.X:
                    //待验证
                    //colValue = tra.position.x + colSpace;
                    break;
                case Axis.Y:
                    colValue = tra.position.y + colSpace;
                    break;
                case Axis.Z:
                    //待验证
                    //colValue = tra.position.z + colSpace;
                    break;
                default:
                    break;
            }

            //根据情况组合【比如这里层是Z轴向且数值越来越小,列是Y轴向且数值越来越大】
            tra.position = new Vector3(oppositeSelfAxisValue, colValue, rowValue);
            return tra;
        }

        /// <summary>
        /// 5-生成整个货架的物体【按列顺序生成】
        /// </summary>
        /// <param name="needGenerateObj">需要生成的物体预设</param>
        /// <param name="generateObjParent">需要生成物体的父物体</param>
        /// <param name="tunnelNumber">巷道编号(【010101】01表示第一巷道01表示左边01表示深度(默认01))</param>
        /// <param name="oppositeSelfAxis">物体生成在那边货架的轴向</param>
        /// <param name="oppositeSelfSpace">物体生成在指定货架的间隔</param>
        /// <param name="rowAxis">物体生成的【层轴向】</param>
        /// <param name="rowNum">货架层的数量</param>
        /// <param name="rowSpace">物体生成的【层间隔】</param>
        /// <param name="colAxis">物体生成的【列轴向】</param>
        /// <param name="colNum">货架列的数量</param>
        /// <param name="colSpace">物体生成的【列间隔】</param>
        private void GenarateGoodsshelvesObj(Transform needGenerateObj, Transform generateObjParent,string tunnelNumber, Axis oppositeSelfAxis, float oppositeSelfSpace, Axis rowAxis, int rowNum, float rowSpace, Axis colAxis, int colNum, float colSpace)
        {
            if (needGenerateObj!=null && generateObjParent!=null &&
                !string.IsNullOrEmpty(tunnelNumber)&&
                rowNum > 0 && Mathf.Abs(rowSpace) > 0 &&
                colNum > 0 && Mathf.Abs(colSpace) > 0)
            {
                float rowObjSpace = 0, colObjSpace = 0;

                for (int i = 0; i < rowNum; i++)
                {
                    //colObjSpace = i * colSpace;
                    rowObjSpace = i * rowSpace;
                    for (int j = 0; j < colNum; j++)
                    {
                        //rowObjSpace = j * rowSpace;
                        colObjSpace = j * colSpace;

                        Transform tra = GenarateObjOfAxis(needGenerateObj,generateObjParent, oppositeSelfAxis, oppositeSelfSpace,rowAxis, rowObjSpace, colAxis, colObjSpace);
                        //设置生成货物的名称
                        int colNumber = (i + 1);
                        int rowNumber = (j + 1);
                        tra.name = GenarateGoodsName(tunnelNumber, rowNumber,colNumber);

                        //添加所有的货格
                        allGoodsCell.Add(tra);
                    }

                }

            }
        }

        /// <summary>
        /// 6-通用货物名称生成规则
        /// </summary>
        /// <param name="number">序号</param>
        /// <returns></returns>
        private string CommonGenarateObjName(int number)
        {
            string strTmp=null;
            if (number >= 1 && number < 10)
            {
                strTmp = "000" + number;
            }
            else if (number < 100)
            {
                strTmp = "00" + number;
            }
            else if (number < 1000)
            {
                strTmp = number.ToString();
            }
            return strTmp;
        }

        /// <summary>
        /// 7-具体的货物名称生成
        /// </summary>
        /// <param name="tunnelNumber">巷道编号(【010101】01表示第一巷道01表示左边01表示深度(都默认01))</param>
        /// <param name="rowNumber">货架层的编号</param>
        /// <param name="colNumber">货架列的编号</param>
        /// <returns></returns>
        private string GenarateGoodsName(string tunnelNumber, int rowNumber,int colNumber)
        {
            string name = tunnelNumber + CommonGenarateObjName(rowNumber) + CommonGenarateObjName(colNumber);
            return name;
        }

        /// <summary>
        /// 8-通用巷道名称生成规则
        /// </summary>
        /// <param name="number">序号</param>
        /// <returns></returns>
        private string CommonTunnelObjName(int number)
        {
            string strTmp = null;
            if (number >= 1 && number < 10)
            {
                strTmp = "0" + number;
            }
            else if (number < 100)
            {
                strTmp = number.ToString();
            }
            return strTmp;
        }


        /// <summary>
        /// 9-生成巷道名称
        /// </summary>
        /// <param name="tunnelNumber">巷道编号(1-16)</param>
        /// <param name="dir">巷道方向(分为左、右两边)</param>
        /// <param name="depthNumber">深度(默认为1)</param>
        /// <returns></returns>
        private string GenarateTunnelName(int tunnelNumber, Direction dir,int depthNumber=1)
        {
            string strTmp = null;

            string strTunnelNum = CommonTunnelObjName(tunnelNumber);

            string strDirNum = null;
            switch (dir)
            {
                case Direction.Left:
                    strDirNum = "01";
                    break;
                case Direction.Right:
                    strDirNum = "02";
                    break;
                default:
                    break;
            }

            string strDepthNum = CommonTunnelObjName(depthNumber);

            strTmp = strTunnelNum + strDirNum + strDepthNum;
            return strTmp;
        }


        /// <summary>
        /// 生成整个货架的物体【按层顺序生成】
        /// </summary>
        /// <param name="needGenerateObj"></param>
        /// <param name="generateObjParent"></param>
        /// <param name="rowNum"></param>
        /// <param name="rowSpace"></param>
        /// <param name="colNum"></param>
        /// <param name="colSpace"></param>
        private void GenarateGoodsshelvesObj(Transform needGenerateObj, Transform generateObjParent, int rowNum, float rowSpace, int colNum, float colSpace)
        {
            if (rowNum > 0 && Mathf.Abs(rowSpace) > 0 &&
                colNum > 0 && Mathf.Abs(colSpace) > 0)
            {
                Transform tra = null;
                float rowObjSpace = 0, colObjSpace=0;

                for (int i = 0; i < colNum; i++)
                {
                    colObjSpace = i * colSpace;
                    for (int j = 0; j < rowNum; j++)
                    {
                        rowObjSpace = j * rowSpace;

                        tra = GenerateObj(needGenerateObj, generateObjParent);
                        tra.position = new Vector3(tra.position.x, tra.position.y + colObjSpace, tra.position.z + rowObjSpace);
                        
                    }

                }
                
            }
        }

        //生成一层物体【按层生成】
        private void GenarateOneRowObj(Transform needGenerateObj, Transform generateObjParent, Axis axis,int col,float space)
        {
            if (col>0 && Mathf.Abs(space) >0)
            {
                for (int i = 0; i < col; i++)
                {
                    float objSpace = i * space;
                    GenarateObjOfAxis(needGenerateObj, generateObjParent, axis, objSpace);
                }
            }
        }

        //生成一列物体【按列生成】
        private void GenarateOneColObj(Transform needGenerateObj, Transform generateObjParent, Axis axis, int row, float space)
        {
            if (row > 0 && Mathf.Abs(space) > 0)
            {
                for (int i = 0; i < row; i++)
                {
                    float objSpace = i * space;
                    GenarateObjOfAxis(needGenerateObj, generateObjParent, axis, objSpace);
                }
            }
        }

        //生成一个物体【对面货架的物体生成】
        private void GenarateOneObj_X(Transform needGenerateObj, Transform generateObjParent, Axis axis, float space)
        {
            if (row > 0 && Mathf.Abs(space) > 0)
            {
                GenarateObjOfAxis(needGenerateObj, generateObjParent, axis, space);
            }
        }



        #endregion

        //枚举轴
        public enum Axis
        {
            X,//X轴
            Y,//Y轴
            Z,//Z轴
        }

        //枚举方向
        public enum Direction
        {
            Left,//左
            Right,//右
        }


    }//Class_end
}

②使用方法,创建一个空物体,挂载该核心脚本,然后制定这些对应的参数内容即可

③运行起来进行测试、按下键盘的I键和T键即可分别生成对应的货物

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章