一、需求分析
①需要實現給貨架按照每列填充貨物,一直填滿整個貨架。
②每個貨架上的貨物都有指定的唯一編號:比如我們現在的是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鍵即可分別生成對應的貨物