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鍵即可分別生成對應的貨物

 

 

 

 

 

 

 

 

 

 

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