当前位置:   article > 正文

Unity开发-SLG实时战斗头像自适应算法_unity实时头像

unity实时头像

目前参与一款在研SLG研发,目前在开发实时战斗部分的表现,今天要分享的是实时战斗头像自动排布算法的实现。


需求分析

  1. 部队头像的自动跟随、
  2. 自动监测碰撞以避免头像重叠、
  3. 需要满足一定性能要求,不能产生过多的DrawCall和其他CPU开销、
  4. 参考效果为万国觉醒实时战斗表现,当前方案基本实现相同效果。

设计思路

  1. 建立Root Canvas空间下的屏幕空间映射,进行虚拟网格拆分,作为基础Map<mapIndex,Area>,和单个头像图标的坐标系。
  2. 提供1所建立的坐标系的注册和反注册,用来记录改空间内网格的占用信息。
  3. 周期性进行Available检测,不满足则进行头像位置变换。
  4. Available算法基于对象和Root的Relative Bounds 进行索引变换,查询Area占用情况。
  5. 每个对象内置固定个数的Available Points,运行时根据部队朝向进行最优排序,周期选取最优点为对象跟随点。

实现方案要点

  • 建立Map<Index,Area>空间索引映射关系,作为坐标系管理和查询的基础
  • 可以直接通过Bounds和AreaSize计算对应坐标,近似Hash算法的查询复杂度
  • 周期性的Available检测,避免高并发的运算
  • Vector.Dot对AvailablePoints进行排序
  • 使用缓存变量避免GC Alloc

PotraitBoard 可以放在UI任意节点,指定好控制参数,即可在Enable Disable时自动注册和反注册

PotraitManager挂载于场景常驻节点

PotraitManager._root需要为UI节点下AnchorPreset为Strench/Strench(铺满全屏)

PotraitManager.areasCount为屏幕空间拆分的行列数

代码略长,不过注释充分,直接贴上了……

 

  1. using System.Collections.Generic;
  2. using System.Text;
  3. using DG.Tweening;
  4. using UnityEngine;
  5. using XLua;
  6. public class PotraitBoard : MonoBehaviour
  7. {
  8. [LuaCallCSharp]
  9. public enum DefaultPos
  10. {
  11. Left = 1,
  12. Right = 2,
  13. }
  14. /// <summary>
  15. /// controll target
  16. /// </summary>
  17. public RectTransform target;
  18. /// <summary>
  19. /// available points
  20. /// </summary>
  21. public List<RectTransform> availablePoints = new List<RectTransform>();
  22. /// <summary>
  23. /// best sort of points
  24. /// </summary>
  25. public List<int> bestSortOfPoints = new List<int>();
  26. /// <summary>
  27. /// position illegle check duration
  28. /// </summary>
  29. private float checkDuration = 2f;
  30. /// <summary>
  31. /// pos of potrait sets
  32. /// </summary>
  33. private int curPos = 0;
  34. /// <summary>
  35. /// pos of potrait sets
  36. /// </summary>
  37. private int curIndex = 0;
  38. /// <summary>
  39. /// troop`s direction
  40. /// </summary>
  41. private Vector2 direction = Vector2.left;
  42. /// <summary>
  43. /// move to next pos
  44. /// </summary>
  45. /// <param name="nextPos"></param>
  46. private void MoveToNext(int nextPos)
  47. {
  48. target.DOLocalMove(availablePoints[nextPos].localPosition, 0.5f).SetEase(Ease.OutQuad);
  49. }
  50. /// <summary>
  51. /// move to next available point in availablePoints in default sequence, if cur is not available
  52. /// </summary>
  53. private void MoveToNextIfNotAvailable()
  54. {
  55. if (PotraitBoardManager.Instance.IsPointAvailable(availablePoints[curPos]))
  56. return;
  57. int sign = curPos;
  58. while (!PotraitBoardManager.Instance.IsPointAvailable(availablePoints[curPos]))
  59. {
  60. curPos++;
  61. curPos = curPos % availablePoints.Count;
  62. if (sign == curPos)
  63. return;
  64. }
  65. //Debug.Log("PotraitBoard MoveToNextIfNotAvailable Move From [" + sign + "] To Pos: [" + curPos + "]");
  66. PotraitBoardManager.Instance.UnRegisterPotrait(curIndex,availablePoints[sign]);
  67. curIndex = PotraitBoardManager.Instance.RegisterPotrait(availablePoints[curPos]);
  68. MoveToNext(curPos);
  69. }
  70. /// <summary>
  71. /// move to next best point available
  72. /// </summary>
  73. private void MoveToNextBestAvailable()
  74. {
  75. if (bestSortOfPoints.Count <= 0)
  76. ReSortPoints();
  77. int pIndex = 0;
  78. for (int i = 0; i < bestSortOfPoints.Count; i++)
  79. {
  80. if (Potra
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/636968
推荐阅读
相关标签
  

闽ICP备14008679号