一、需求分析
①需要实现给货架按照每列填充货物,一直填满整个货架。
②每个货架上的货物都有指定的唯一编号:比如我们现在的是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键即可分别生成对应的货物