SCGridLayoutGroup.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. 
  2. using UnityEngine;
  3. using UnityEditor;
  4. using Unity.Collections;
  5. [ExecuteAlways]//脚本在任意情况下均会运行
  6. public class SCGridLayoutGroup : SCBaseLayoutGroup
  7. {
  8. /// <summary>
  9. /// 组的布局类型
  10. /// </summary>
  11. [SerializeField]
  12. private LayoutTypes layoutType = LayoutTypes.Horizontal;
  13. public LayoutTypes LayoutType
  14. {
  15. get { return layoutType; }
  16. set { layoutType = value; }
  17. }
  18. /// <summary>
  19. /// 不满一行时的子物体对齐方式
  20. /// </summary>
  21. [SerializeField]
  22. private GroupHorizontalAlignment groupHorizontalAlign = GroupHorizontalAlignment.Left;
  23. public GroupHorizontalAlignment GroupHorizontalAlign
  24. {
  25. get { return groupHorizontalAlign; }
  26. set { groupHorizontalAlign = value; }
  27. }
  28. /// <summary>
  29. /// 不满一列时的子物体对齐方式
  30. /// </summary>
  31. [SerializeField]
  32. private GroupVerticalAlignment groupVerticalAlign = GroupVerticalAlignment.Top;
  33. public GroupVerticalAlignment GroupVerticalAlign
  34. {
  35. get { return groupVerticalAlign; }
  36. set { groupVerticalAlign = value; }
  37. }
  38. /// <summary>
  39. /// 子物体的队形类型
  40. /// </summary>
  41. [SerializeField]
  42. private GroupArrayTypes groupArrayType =
  43. GroupArrayTypes.Plane;
  44. public GroupArrayTypes GroupArrayType {
  45. get { return groupArrayType; }
  46. set { groupArrayType = value; }
  47. }
  48. /// <summary>
  49. /// 组锚点相对于基类的位置
  50. /// </summary>
  51. [SerializeField]
  52. private AnchorRelativeBase anchorLayout = AnchorRelativeBase.MiddleCenter;
  53. public AnchorRelativeBase AnchorLayout
  54. {
  55. get { return anchorLayout; }
  56. set { anchorLayout = value; }
  57. }
  58. /// <summary>
  59. /// 各子物体的面向
  60. /// </summary>
  61. [SerializeField]
  62. private ObjFacingTypes facingType = ObjFacingTypes.None;
  63. public ObjFacingTypes FacingType
  64. {
  65. get { return facingType; }
  66. set { facingType = value; }
  67. }
  68. /// <summary>
  69. /// 列数
  70. /// </summary>
  71. [SerializeField]
  72. private int columns = 2;
  73. public int Columns {
  74. get { return columns; }
  75. set {
  76. if (LayoutType == LayoutTypes.Horizontal)
  77. {
  78. return;
  79. }
  80. columns = value; }
  81. }
  82. /// <summary>
  83. /// 行数
  84. /// </summary>
  85. [SerializeField]
  86. private int rows = 2;
  87. public int Rows
  88. {
  89. get { return rows; }
  90. set
  91. {
  92. if (LayoutType == LayoutTypes.Vertical)
  93. {
  94. return;
  95. }
  96. rows = value;
  97. }
  98. }
  99. /// <summary>
  100. /// 横向间距
  101. /// </summary>
  102. [SerializeField]
  103. private float spaceX = 2f;
  104. public float SpaceX {
  105. get { return spaceX; }
  106. set { spaceX = value; }
  107. }
  108. /// <summary>
  109. /// 纵向间距
  110. /// </summary>
  111. [SerializeField]
  112. private float spaceY = 2f;
  113. public float SpaceY
  114. {
  115. get { return spaceY; }
  116. set { spaceY = value; }
  117. }
  118. [SerializeField]
  119. [Range(-100f, 100f)]
  120. private float childOffsetX = 0f;
  121. public float ChildOffsetX
  122. {
  123. get { return childOffsetX; }
  124. set { childOffsetX = value; }
  125. }
  126. [SerializeField]
  127. [Range(-100f, 100f)]
  128. private float childOffsetY= 0f;
  129. public float ChildOffsetY
  130. {
  131. get { return childOffsetY; }
  132. set { childOffsetY = value; }
  133. }
  134. /// <summary>
  135. /// 子物体Z轴相较于基类的位置
  136. /// </summary>
  137. [SerializeField]
  138. [Range(-100f, 100f)]
  139. private float childOffsetZ = 0f;
  140. public float ChildOffsetZ
  141. {
  142. get { return childOffsetZ; }
  143. set { childOffsetZ = value; }
  144. }
  145. /// <summary>
  146. /// 半径
  147. /// </summary>
  148. [SerializeField]
  149. [Range(0.05f,200)]
  150. private float radius = 2f;
  151. public float Radius
  152. {
  153. get { return radius; }
  154. set { radius = value; }
  155. }
  156. /// <summary>
  157. /// 辐射角度
  158. /// </summary>
  159. [SerializeField]
  160. [Range(5f, 360f)]
  161. private float radialRange = 180f;
  162. public float RadialRange {
  163. get { return radialRange; }
  164. set { radialRange = value; }
  165. }
  166. /// <summary>
  167. /// 锚点是否用轴对齐
  168. /// </summary>
  169. [SerializeField]
  170. private bool isAnchorWithAxis = false;
  171. public bool IsAnchorWithAxis
  172. {
  173. get { return isAnchorWithAxis; }
  174. set { isAnchorWithAxis = value; }
  175. }
  176. private GroupObj tempobj;
  177. private Vector3[] childPos;
  178. private Vector3 newPos;
  179. private int objCount;
  180. private int rowMax;
  181. private int colMax;
  182. private float acnhoroffsetX;
  183. private float anchoroffsetY;
  184. private float shortOffsetX;
  185. private float shortOffsetY;
  186. private void Init()//初始化值
  187. {
  188. childPos = new Vector3[ObjList.Count];
  189. newPos = Vector3.zero;
  190. objCount = 0;
  191. rowMax = 0;
  192. colMax = 0;
  193. acnhoroffsetX = 0;
  194. anchoroffsetY = 0;
  195. shortOffsetX = 0;
  196. shortOffsetY = 0;
  197. }
  198. protected override void LayoutChildren()
  199. {
  200. Init();
  201. SetObjPos();
  202. ArrayType();
  203. }
  204. private void Update()
  205. {
  206. }
  207. private void SetObjPos()//子物体的位置
  208. {
  209. switch (LayoutType)
  210. {
  211. case LayoutTypes.Horizontal:
  212. colMax = Columns;
  213. rowMax= Mathf.CeilToInt((float)ObjList.Count / Columns);
  214. break;
  215. case LayoutTypes.Vertical:
  216. rowMax = Rows;
  217. colMax = Mathf.CeilToInt((float)ObjList.Count / Rows);
  218. break;
  219. }
  220. acnhoroffsetX = (colMax * 0.5f * SpaceX);
  221. if (AnchorLayout == AnchorRelativeBase.LowerLeft || AnchorLayout == AnchorRelativeBase.UpperLeft || AnchorLayout == AnchorRelativeBase.MiddleLeft)
  222. {
  223. acnhoroffsetX = IsAnchorWithAxis ? 0.5f * SpaceX : 0;
  224. }
  225. else if (AnchorLayout == AnchorRelativeBase.LowerRight || AnchorLayout == AnchorRelativeBase.UpperRight || AnchorLayout == AnchorRelativeBase.MiddleRight)
  226. {
  227. acnhoroffsetX = IsAnchorWithAxis ? (colMax - 0.5f) * SpaceX : colMax * SpaceX;
  228. }
  229. anchoroffsetY = (rowMax * 0.5f * SpaceY);
  230. if (AnchorLayout == AnchorRelativeBase.UpperLeft || AnchorLayout == AnchorRelativeBase.UpperCenter || AnchorLayout == AnchorRelativeBase.UpperRight)
  231. {
  232. anchoroffsetY = IsAnchorWithAxis ? 0.5f * SpaceY : 0;
  233. }
  234. else if (AnchorLayout == AnchorRelativeBase.LowerLeft || AnchorLayout == AnchorRelativeBase.LowerCenter || AnchorLayout == AnchorRelativeBase.LowerRight)
  235. {
  236. anchoroffsetY = IsAnchorWithAxis ? (rowMax - 0.5f) * SpaceY : rowMax * SpaceY;
  237. }
  238. if (LayoutType == LayoutTypes.Horizontal)
  239. {
  240. for (int i = 0; i < rowMax; i++)
  241. {
  242. for (int j = 0; j < colMax; j++)
  243. {
  244. if (i==rowMax-1)
  245. {
  246. if (GroupHorizontalAlign == GroupHorizontalAlignment.Left)
  247. {
  248. shortOffsetX = 0;
  249. }
  250. else if (GroupHorizontalAlign == GroupHorizontalAlignment.Center)
  251. {
  252. shortOffsetX = SpaceX * ((colMax - (ObjList.Count % colMax)) % colMax) * 0.5f;
  253. }
  254. else if (GroupHorizontalAlign == GroupHorizontalAlignment.Right)
  255. {
  256. shortOffsetX = SpaceX * ((colMax - (ObjList.Count % colMax)) % colMax);
  257. }
  258. }
  259. if (objCount< ObjList.Count)
  260. {
  261. childPos[objCount].Set(0.5f * SpaceX * (1 + 2 * j) - acnhoroffsetX + shortOffsetX+ ChildOffsetX, (0.5f * SpaceY * (-1 - 2 * i)) + anchoroffsetY + shortOffsetY+ChildOffsetY, 0.0f);
  262. }
  263. objCount++;
  264. }
  265. }
  266. }
  267. else
  268. {
  269. for (int i = 0; i < colMax; i++)
  270. {
  271. for (int j = 0; j < rowMax; j++)
  272. {
  273. if (i==colMax-1)
  274. {
  275. if (GroupVerticalAlign == GroupVerticalAlignment.Top)
  276. {
  277. shortOffsetY = 0;
  278. }
  279. else if (GroupVerticalAlign == GroupVerticalAlignment.Middle)
  280. {
  281. shortOffsetY = -SpaceY * ((rowMax - (ObjList.Count % rowMax)) % rowMax) * 0.5f;
  282. }
  283. else if (GroupVerticalAlign == GroupVerticalAlignment.Bottom)
  284. {
  285. shortOffsetY = -SpaceY * ((rowMax - (ObjList.Count % rowMax)) % rowMax);
  286. }
  287. }
  288. if (objCount< ObjList.Count)
  289. {
  290. childPos[objCount].Set(0.5f * SpaceX * (1 + 2 * i )- acnhoroffsetX + shortOffsetX+ ChildOffsetX, (0.5f * SpaceY * ( - 1 - 2 * j))+ anchoroffsetY + shortOffsetY+childOffsetY, 0.0f);
  291. }
  292. objCount++;
  293. }
  294. }
  295. }
  296. }
  297. private void ArrayType()//赋予子物体位置
  298. {
  299. switch (GroupArrayType) {
  300. case GroupArrayTypes.Plane:
  301. for (int i = 0; i < ObjList.Count; i++)
  302. {
  303. tempobj = ObjList[i];
  304. newPos = childPos[i];
  305. newPos.z = ChildOffsetZ;
  306. tempobj.Transform.localPosition = newPos;
  307. ObjFacing(tempobj);
  308. ObjList[i] = tempobj;
  309. }
  310. break;
  311. case GroupArrayTypes.Cylinder:
  312. for (int i = 0; i < ObjList.Count; i++)
  313. {
  314. tempobj = ObjList[i];
  315. newPos = CylinderArray(childPos[i], radius);
  316. tempobj.Transform.localPosition = newPos;
  317. ObjFacing(tempobj);
  318. ObjList[i] = tempobj;
  319. }
  320. break;
  321. case GroupArrayTypes.Radial:
  322. int tempColumn=0;
  323. int tempRow=1;
  324. for (int i = 0; i < ObjList.Count ; i++)
  325. {
  326. tempobj = ObjList[i];
  327. newPos = RadialArray(childPos[i], radius, radialRange, tempRow, rowMax, tempColumn, colMax);
  328. if (tempColumn==columns-1)
  329. {
  330. tempColumn = 0;
  331. tempRow++;
  332. }
  333. else
  334. {
  335. tempColumn++;
  336. }
  337. tempobj.Transform.localPosition = newPos;
  338. ObjFacing(tempobj);
  339. ObjList[i] = tempobj;
  340. }
  341. break;
  342. case GroupArrayTypes.Sphere:
  343. for (int i = 0; i < ObjList.Count ; i++)
  344. {
  345. tempobj = ObjList[i];
  346. newPos = SphereArray(childPos[i], radius);
  347. tempobj.Transform.localPosition = newPos;
  348. ObjFacing(tempobj);
  349. ObjList[i] = tempobj;
  350. }
  351. break;
  352. case GroupArrayTypes.Round:
  353. for (int i = 0; i < ObjList.Count; i++)
  354. {
  355. tempobj = ObjList[i];
  356. newPos = RoundArray( childPos[i],radius, i+1,ObjList.Count);
  357. newPos.Set(newPos.x+ChildOffsetX, newPos.y + ChildOffsetY, newPos.z +ChildOffsetZ);
  358. tempobj.Transform.localPosition = newPos;
  359. ObjFacing(tempobj);
  360. ObjList[i] = tempobj;
  361. }
  362. break;
  363. }
  364. }
  365. private Vector3 CylinderArray(Vector3 objPos,float radius)
  366. {
  367. float circ = 2.0f * Mathf.PI * radius;
  368. float xAngle = (objPos.x / circ) * 360f;
  369. objPos.Set(0.0f, objPos.y, radius);
  370. Quaternion rot = Quaternion.Euler(0.0f, xAngle, 0.0f);
  371. objPos = rot * objPos;
  372. return objPos;
  373. }
  374. private Vector3 SphereArray(Vector3 objPos, float radius)
  375. {
  376. float circ = 2.0f * Mathf.PI * radius;
  377. float XAngle = (objPos.x / circ) * 360f;
  378. float YAngle = -(objPos.y / circ) * 360f;
  379. objPos.Set(0.0f, 0.0f, radius);
  380. Quaternion rot = Quaternion.Euler(YAngle, XAngle, 0.0f);
  381. objPos = rot * objPos;
  382. return objPos;
  383. }
  384. private Vector3 RadialArray(Vector3 objPos, float radius ,float radialRange,int row,int rowMax,int column,int colMax)
  385. {
  386. float radialSpaceAngle = radialRange / colMax;
  387. objPos.Set(0.0f, 0.0f, (radius / rowMax) * row);
  388. float YAngle= radialSpaceAngle * (column - (colMax * 0.5f)) + (radialSpaceAngle * .5f);
  389. Quaternion rot = Quaternion.Euler(0.0f, YAngle, 0.0f);
  390. objPos = rot * objPos;
  391. return objPos;
  392. }
  393. private Vector3 RoundArray(Vector3 objPos , float radius,int i,int totalCount)
  394. {
  395. float angle = (360f *i )/ totalCount;
  396. float x = radius * Mathf.Cos(angle* Mathf.PI / 180f);
  397. float y = radius * Mathf.Sin(angle* Mathf.PI / 180f);
  398. objPos.Set(x,0,y);
  399. return objPos;
  400. }
  401. private void ObjFacing(GroupObj obj)//子物体的面向
  402. {
  403. Vector3 centerPos;
  404. Vector3 FacingNode;
  405. switch (FacingType)
  406. {
  407. case ObjFacingTypes.None:
  408. obj.Transform.transform.localEulerAngles = Vector3.zero;
  409. break;
  410. case ObjFacingTypes.FaceOrigin:
  411. obj.Transform.rotation = Quaternion.LookRotation(obj.Transform.position-transform.position,transform.up);
  412. break;
  413. case ObjFacingTypes.FaceOriginReversed:
  414. obj.Transform.rotation = Quaternion.LookRotation(transform.position- obj.Transform.position,transform.up);
  415. break;
  416. case ObjFacingTypes.FaceCenterAxis:
  417. centerPos = Vector3.Project(obj.Transform.position-transform.position,transform.up);//返回一个向量在指定轴上的投影
  418. FacingNode = transform.position + centerPos;
  419. obj.Transform.rotation = Quaternion.LookRotation(obj.Transform.position - FacingNode, transform.up);
  420. break;
  421. case ObjFacingTypes.FaceCenterAxisReversed:
  422. centerPos = Vector3.Project(obj.Transform.position - transform.position, transform.up);//返回一个向量在指定轴上的投影
  423. FacingNode = transform.position + centerPos;
  424. obj.Transform.rotation = Quaternion.LookRotation(FacingNode- obj.Transform.position , transform.up);
  425. break;
  426. case ObjFacingTypes.FaceParentDown:
  427. obj.Transform.forward = transform.rotation * Vector3.down;
  428. break;
  429. case ObjFacingTypes.FaceParentUp:
  430. obj.Transform.forward = transform.rotation * Vector3.up;
  431. break;
  432. case ObjFacingTypes.FaceParentFoward:
  433. obj.Transform.forward = transform.rotation * Vector3.forward;
  434. break;
  435. case ObjFacingTypes.FaceParentBack:
  436. obj.Transform.forward = transform.rotation * Vector3.back;
  437. break;
  438. }
  439. }
  440. private void setNull()
  441. {
  442. tempobj = null;
  443. childPos = null;
  444. }
  445. private void OnDestroy()
  446. {
  447. setNull();
  448. }
  449. }