【唐老狮】Unity实现RTS游戏阵型功能
使用资源
【唐老狮】Unity实现 即时战略游戏 阵型功能 - 泰课在线
预制体设置
烘焙
给场景选择烘焙静态
设置模型预制体
用添加父物体的方式解决模型朝向问题
添加胶囊碰撞器,设置为触发器
添加寻路组件
添加脚底光圈特效,调整到位
重新为Hero创建动画状态机
只需要移动和待命动画
为其他模型进行同样的处理
士兵脚本编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| using System; using UnityEngine; using UnityEngine.AI;
namespace ObjectManager { public class SoldierObj : MonoBehaviour { private Animator _animator; private NavMeshAgent _agent;
private GameObject _footEffect; private void Start() { _animator = this.GetComponentInChildren<Animator>(); _agent = this.GetComponent<NavMeshAgent>(); _footEffect = this.transform.Find("FootEffect").gameObject; SetSelSelf(false); }
private void Update() { _animator.SetBool("IsMove", _agent.velocity.magnitude > 0); }
public void Move(Vector3 pos) { _agent.SetDestination(pos); } public void SetSelSelf(bool isSel) { _footEffect.SetActive(isSel); } } }
|
选择框逻辑实现
在场景中添加空物体Controller,添加LineRenderer组件,更改组件细节
为LineRenderer添加绿色的UI材质球,勾选Loop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| using System; using UnityEngine;
namespace Control { public class Controller : MonoBehaviour { private bool _isMouseDown;
private LineRenderer _line;
private Vector3 _leftUpInputPos,_rightUpPoint,_rightDownPoint,_leftDownPoint;
private void Start() { _line = GetComponent<LineRenderer>(); }
private void Update() { if (Input.GetMouseButtonDown(0)) { _leftUpInputPos = Input.mousePosition; _isMouseDown = true; } else if (Input.GetMouseButtonUp(0)) { _isMouseDown = false; _line.positionCount = 0; } if (_isMouseDown) { _line.positionCount = 4; _leftUpInputPos.z = 5; _rightDownPoint = Input.mousePosition; _rightDownPoint.z = 5; _rightUpPoint = new Vector3(_rightDownPoint.x, _leftUpInputPos.y,5); _leftDownPoint = new Vector3(_leftUpInputPos.x, _rightDownPoint.y, 5); _line.SetPosition(0,Camera.main.ScreenToWorldPoint(_leftUpInputPos)); _line.SetPosition(1,Camera.main.ScreenToWorldPoint(_rightUpPoint)); _line.SetPosition(2,Camera.main.ScreenToWorldPoint(_rightDownPoint)); _line.SetPosition(3,Camera.main.ScreenToWorldPoint(_leftDownPoint)); } } } }
|
选择士兵
三种办法:
1.射线检测+范围检测:射线击中地面,在范围中心点进行碰撞器检测
2.世界坐标转屏幕坐标
3.射线检测+位置判断
添加新LayOut层Ground
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| using System; using System.Collections.Generic; using ObjectManager; using UnityEngine;
namespace Control { public class Controller : MonoBehaviour { private bool _isMouseDown;
private LineRenderer _line;
private Vector3 _leftUpInputPos,_rightUpPoint,_rightDownPoint,_leftDownPoint;
private RaycastHit _hitInfo; private Vector3 _beginWorldPoint;
private List<SoldierObj> _soldierObjs = new(); private void Start() { _line = GetComponent<LineRenderer>(); }
private void Update() { if (Input.GetMouseButtonDown(0)) { _leftUpInputPos = Input.mousePosition; _isMouseDown = true; if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out _hitInfo, 1000, LayerMask.NameToLayer("Ground"))) _beginWorldPoint = _hitInfo.point; } else if (Input.GetMouseButtonUp(0)) { _isMouseDown = false; _line.positionCount = 0; foreach (var t in _soldierObjs) { t.SetSelSelf(false); } _soldierObjs.Clear();
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out _hitInfo, 1000, LayerMask.NameToLayer("Ground"))) { var center = new Vector3((_hitInfo.point.x + _beginWorldPoint.x) / 2, 1, (_hitInfo.point.z + _beginWorldPoint.z) / 2); var halfExtents = new Vector3(Math.Abs(_hitInfo.point.x - _beginWorldPoint.x) / 2, 1, Mathf.Abs(_hitInfo.point.x - _beginWorldPoint.x) / 2);
var colliders = Physics.OverlapBox(center, halfExtents); for (int i = 0; i < colliders.Length; i++) { var obj = colliders[i].GetComponent<SoldierObj>(); if (obj is not null) { obj.SetSelSelf(true); _soldierObjs.Add(obj); } } } } if (_isMouseDown) { _line.positionCount = 4; _leftUpInputPos.z = 5; _rightDownPoint = Input.mousePosition; _rightDownPoint.z = 5; _rightUpPoint = new Vector3(_rightDownPoint.x, _leftUpInputPos.y,5); _leftDownPoint = new Vector3(_leftUpInputPos.x, _rightDownPoint.y, 5); _line.SetPosition(0,Camera.main.ScreenToWorldPoint(_leftUpInputPos)); _line.SetPosition(1,Camera.main.ScreenToWorldPoint(_rightUpPoint)); _line.SetPosition(2,Camera.main.ScreenToWorldPoint(_rightDownPoint)); _line.SetPosition(3,Camera.main.ScreenToWorldPoint(_leftDownPoint)); } } } }
|
阵型功能分析
魔兽争霸中最多只能选择12个单位
如果只选择了一个单位,鼠标指哪单位去哪
如果选择了两个单位,两个单位会分立鼠标两侧
以此类推
我们可以制定一个规则,将阵列中两个单位之间的距离设置为定值
我们不用总结一个通用的算法,而是可以通过选中的单位数分类讨论
通过两次鼠标点击位置,计算移动的方向向量,从而确定阵列的方向(右方向)
前往阵型目标点逻辑实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
| using System; using System.Collections.Generic; using ObjectManager; using UnityEngine;
namespace Control { public class Controller : MonoBehaviour { private bool _isMouseDown; private LineRenderer _line; private Vector3 _leftUpInputPos,_rightUpPoint,_rightDownPoint,_leftDownPoint; private RaycastHit _hitInfo; private Vector3 _beginWorldPoint;
private List<SoldierObj> _soldierObjs = new();
private Vector3 _frontPos;
[SerializeField]private float soldierOffset; private void Start() { _line = GetComponent<LineRenderer>(); }
private void Update() { SelSoldiers(); ControlSoldierMove(); }
private void SelSoldiers() { if (Input.GetMouseButtonDown(0)) { _leftUpInputPos = Input.mousePosition; _isMouseDown = true; if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out _hitInfo, 1000, LayerMask.NameToLayer("Ground"))) _beginWorldPoint = _hitInfo.point; } else if (Input.GetMouseButtonUp(0)) { _isMouseDown = false; _line.positionCount = 0; _frontPos = Vector3.zero; foreach (var t in _soldierObjs) { t.SetSelSelf(false); } _soldierObjs.Clear(); if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out _hitInfo, 1000, LayerMask.NameToLayer("Ground"))) { var center = new Vector3((_hitInfo.point.x + _beginWorldPoint.x) / 2, 1, (_hitInfo.point.z + _beginWorldPoint.z) / 2); var halfExtents = new Vector3(Math.Abs(_hitInfo.point.x - _beginWorldPoint.x) / 2, 1, Mathf.Abs(_hitInfo.point.x - _beginWorldPoint.x) / 2); var colliders = Physics.OverlapBox(center, halfExtents); for (int i = 0; i < colliders.Length&&_soldierObjs.Count<12; i++) { var obj = colliders[i].GetComponent<SoldierObj>(); if (obj is not null) { obj.SetSelSelf(true); _soldierObjs.Add(obj); } } } } if (_isMouseDown) { _line.positionCount = 4; _leftUpInputPos.z = 5; _rightDownPoint = Input.mousePosition; _rightDownPoint.z = 5; _rightUpPoint = new Vector3(_rightDownPoint.x, _leftUpInputPos.y,5); _leftDownPoint = new Vector3(_leftUpInputPos.x, _rightDownPoint.y, 5); _line.SetPosition(0,Camera.main.ScreenToWorldPoint(_leftUpInputPos)); _line.SetPosition(1,Camera.main.ScreenToWorldPoint(_rightUpPoint)); _line.SetPosition(2,Camera.main.ScreenToWorldPoint(_rightDownPoint)); _line.SetPosition(3,Camera.main.ScreenToWorldPoint(_leftDownPoint)); } }
private void ControlSoldierMove() { if (Input.GetMouseButtonDown(1)) { if (_soldierObjs.Count<=0) { return; }
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out _hitInfo, 1000,1<<LayerMask.NameToLayer("Ground"))) { List<Vector3> targetsPos = GetTargetPos(_hitInfo.point); for (int i = 0; i < _soldierObjs.Count; i++) { _soldierObjs[i].Move(targetsPos[i]); } } } }
private List<Vector3> GetTargetPos(Vector3 targetPos) { var nowForward = Vector3.zero; var nowRight = Vector3.zero; if (_frontPos != Vector3.zero) { nowForward = (targetPos - _frontPos).normalized; } else { nowForward = (targetPos - _soldierObjs[0].transform.position).normalized; } nowRight = Quaternion.Euler(0, 90, 0) * nowForward;
var targetsPos = new List<Vector3>(); switch (_soldierObjs.Count) { case 1: targetsPos.Add(targetPos); break; case 2: targetsPos.Add(targetPos+nowRight*soldierOffset/2); targetsPos.Add(targetPos-nowRight*soldierOffset/2); break; case 3: targetsPos.Add(targetPos); targetsPos.Add(targetPos+nowRight*soldierOffset); targetsPos.Add(targetPos-nowRight*soldierOffset); break; case 4: targetsPos.Add(targetPos + nowForward*soldierOffset/2 - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset/2 + nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowForward*soldierOffset/2 - nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowForward*soldierOffset/2 + nowRight*soldierOffset/2); break; case 5: targetsPos.Add(targetPos + nowForward* soldierOffset/2); targetsPos.Add(targetPos + nowForward* soldierOffset/2-nowRight*soldierOffset); targetsPos.Add(targetPos + nowForward* soldierOffset/2+nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2-nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2+nowRight*soldierOffset); break; case 6: targetsPos.Add(targetPos + nowForward* soldierOffset/2); targetsPos.Add(targetPos + nowForward* soldierOffset/2-nowRight*soldierOffset); targetsPos.Add(targetPos + nowForward* soldierOffset/2+nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2-nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2+nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2); break; case 7: targetsPos.Add(targetPos+nowForward*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset+nowRight*soldierOffset); targetsPos.Add(targetPos+nowRight*soldierOffset); targetsPos.Add(targetPos-nowRight*soldierOffset); targetsPos.Add(targetPos); targetsPos.Add(targetPos-nowForward*soldierOffset); break; case 8: targetsPos.Add(targetPos+nowForward*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset+nowRight*soldierOffset); targetsPos.Add(targetPos+nowRight*soldierOffset); targetsPos.Add(targetPos-nowRight*soldierOffset); targetsPos.Add(targetPos); targetsPos.Add(targetPos-nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos-nowForward*soldierOffset+nowRight*soldierOffset); break; case 9: targetsPos.Add(targetPos+nowForward*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset+nowRight*soldierOffset); targetsPos.Add(targetPos+nowRight*soldierOffset); targetsPos.Add(targetPos-nowRight*soldierOffset); targetsPos.Add(targetPos); targetsPos.Add(targetPos-nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos-nowForward*soldierOffset+nowRight*soldierOffset); targetsPos.Add(targetPos-nowForward*soldierOffset); break; case 10: targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset + nowRight*soldierOffset*1.5f); break; case 11: targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos-nowForward*soldierOffset); break; case 12: targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset - nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowForward*soldierOffset + nowRight*soldierOffset/2); break; } _frontPos = targetPos; return targetsPos; } } }
|
阵型布局优化
游戏设计师可能会希望将肉盾放在阵列前面,ADC放在阵列后面
Controller中添加点的位置有一定的顺序,前排先添加,后排后添加
将士兵列表按类型排序,即可符合肉盾放在阵列前面,ADC放在阵列后面的要求
更改SoldierObj
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| using UnityEngine; using UnityEngine.AI;
namespace ObjectManager {
public enum SoldierType { Hero,Warrior,Archer,Magician,Loong } public class SoldierObj : MonoBehaviour { private Animator _animator; private NavMeshAgent _agent;
private GameObject _footEffect;
public SoldierType type; private void Start() { _animator = this.GetComponentInChildren<Animator>(); _agent = this.GetComponent<NavMeshAgent>(); _footEffect = this.transform.Find("FootEffect").gameObject; SetSelSelf(false); }
private void Update() { _animator.SetBool("IsMove", _agent.velocity.magnitude > 0); }
public void Move(Vector3 pos) { _agent.SetDestination(pos); } public void SetSelSelf(bool isSel) { _footEffect.SetActive(isSel); } } }
|
更改Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
_soldierObjs.Sort((a, b) => { if (a.type<b.type) { return -1; } else if(a.type == b.type) { return 0; } else { return 1; } });
|
寻路优化
使用现在的算法,当两次位置转角过大时,单位会出现左右相互穿插
我们可以更改排序算法,先用兵种排序,如果队伍转角过大,再用单位与对应索引位置的距离排序
以下是最终的Controller脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
| using System; using System.Collections.Generic; using ObjectManager; using UnityEngine;
namespace Control { public class Controller : MonoBehaviour { private bool _isMouseDown; private LineRenderer _line; private Vector3 _leftUpInputPos,_rightUpPoint,_rightDownPoint,_leftDownPoint; private RaycastHit _hitInfo; private Vector3 _beginWorldPoint;
private List<SoldierObj> _soldierObjs = new();
private Vector3 _frontPos;
[SerializeField]private float soldierOffset; private void Start() { _line = GetComponent<LineRenderer>(); }
private void Update() { SelSoldiers(); ControlSoldierMove(); }
private void SelSoldiers() { if (Input.GetMouseButtonDown(0)) { _leftUpInputPos = Input.mousePosition; _isMouseDown = true; if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out _hitInfo, 1000, LayerMask.NameToLayer("Ground"))) _beginWorldPoint = _hitInfo.point; } else if (Input.GetMouseButtonUp(0)) { _isMouseDown = false; _line.positionCount = 0; _frontPos = Vector3.zero; foreach (var t in _soldierObjs) { t.SetSelSelf(false); } _soldierObjs.Clear(); if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out _hitInfo, 1000, LayerMask.NameToLayer("Ground"))) { var center = new Vector3((_hitInfo.point.x + _beginWorldPoint.x) / 2, 1, (_hitInfo.point.z + _beginWorldPoint.z) / 2); var halfExtents = new Vector3(Math.Abs(_hitInfo.point.x - _beginWorldPoint.x) / 2, 1, Mathf.Abs(_hitInfo.point.x - _beginWorldPoint.x) / 2); var colliders = Physics.OverlapBox(center, halfExtents); for (int i = 0; i < colliders.Length&&_soldierObjs.Count<12; i++) { var obj = colliders[i].GetComponent<SoldierObj>(); if (obj is not null) { obj.SetSelSelf(true); _soldierObjs.Add(obj); } } _soldierObjs.Sort((a, b) => { if (a.type<b.type) { return -1; } else if(a.type == b.type) { return 0; } else { return 1; } }); } } if (_isMouseDown) { _line.positionCount = 4; _leftUpInputPos.z = 5; _rightDownPoint = Input.mousePosition; _rightDownPoint.z = 5; _rightUpPoint = new Vector3(_rightDownPoint.x, _leftUpInputPos.y,5); _leftDownPoint = new Vector3(_leftUpInputPos.x, _rightDownPoint.y, 5); _line.SetPosition(0,Camera.main.ScreenToWorldPoint(_leftUpInputPos)); _line.SetPosition(1,Camera.main.ScreenToWorldPoint(_rightUpPoint)); _line.SetPosition(2,Camera.main.ScreenToWorldPoint(_rightDownPoint)); _line.SetPosition(3,Camera.main.ScreenToWorldPoint(_leftDownPoint)); } }
private void ControlSoldierMove() { if (Input.GetMouseButtonDown(1)) { if (_soldierObjs.Count<=0) { return; }
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out _hitInfo, 1000,1<<LayerMask.NameToLayer("Ground"))) { if (Vector3.Angle((_hitInfo.point - _soldierObjs[0].transform.position).normalized,_soldierObjs[0].transform.forward)>60) { _soldierObjs.Sort((a, b) => { if (a.type<b.type) { return -1; } else if(a.type == b.type) { if (Vector3.Distance(a.transform.position,_hitInfo.point)<=Vector3.Distance(b.transform.position,_hitInfo.point)) { return -1; } else { return 1; } } else { return 1; } }); } List<Vector3> targetsPos = GetTargetPos(_hitInfo.point); for (int i = 0; i < _soldierObjs.Count; i++) { _soldierObjs[i].Move(targetsPos[i]); } } } }
private List<Vector3> GetTargetPos(Vector3 targetPos) { var nowForward = Vector3.zero; var nowRight = Vector3.zero; if (_frontPos != Vector3.zero) { nowForward = (targetPos - _frontPos).normalized; } else { nowForward = (targetPos - _soldierObjs[0].transform.position).normalized; } nowRight = Quaternion.Euler(0, 90, 0) * nowForward;
var targetsPos = new List<Vector3>(); switch (_soldierObjs.Count) { case 1: targetsPos.Add(targetPos); break; case 2: targetsPos.Add(targetPos+nowRight*soldierOffset/2); targetsPos.Add(targetPos-nowRight*soldierOffset/2); break; case 3: targetsPos.Add(targetPos); targetsPos.Add(targetPos+nowRight*soldierOffset); targetsPos.Add(targetPos-nowRight*soldierOffset); break; case 4: targetsPos.Add(targetPos + nowForward*soldierOffset/2 - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset/2 + nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowForward*soldierOffset/2 - nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowForward*soldierOffset/2 + nowRight*soldierOffset/2); break; case 5: targetsPos.Add(targetPos + nowForward* soldierOffset/2); targetsPos.Add(targetPos + nowForward* soldierOffset/2-nowRight*soldierOffset); targetsPos.Add(targetPos + nowForward* soldierOffset/2+nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2-nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2+nowRight*soldierOffset); break; case 6: targetsPos.Add(targetPos + nowForward* soldierOffset/2); targetsPos.Add(targetPos + nowForward* soldierOffset/2-nowRight*soldierOffset); targetsPos.Add(targetPos + nowForward* soldierOffset/2+nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2-nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2+nowRight*soldierOffset); targetsPos.Add(targetPos - nowForward* soldierOffset/2); break; case 7: targetsPos.Add(targetPos+nowForward*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset+nowRight*soldierOffset); targetsPos.Add(targetPos+nowRight*soldierOffset); targetsPos.Add(targetPos-nowRight*soldierOffset); targetsPos.Add(targetPos); targetsPos.Add(targetPos-nowForward*soldierOffset); break; case 8: targetsPos.Add(targetPos+nowForward*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset+nowRight*soldierOffset); targetsPos.Add(targetPos+nowRight*soldierOffset); targetsPos.Add(targetPos-nowRight*soldierOffset); targetsPos.Add(targetPos); targetsPos.Add(targetPos-nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos-nowForward*soldierOffset+nowRight*soldierOffset); break; case 9: targetsPos.Add(targetPos+nowForward*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos+nowForward*soldierOffset+nowRight*soldierOffset); targetsPos.Add(targetPos+nowRight*soldierOffset); targetsPos.Add(targetPos-nowRight*soldierOffset); targetsPos.Add(targetPos); targetsPos.Add(targetPos-nowForward*soldierOffset-nowRight*soldierOffset); targetsPos.Add(targetPos-nowForward*soldierOffset+nowRight*soldierOffset); targetsPos.Add(targetPos-nowForward*soldierOffset); break; case 10: targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset + nowRight*soldierOffset*1.5f); break; case 11: targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos-nowForward*soldierOffset); break; case 12: targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowRight*soldierOffset/2); targetsPos.Add(targetPos + nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset - nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset + nowRight*soldierOffset*1.5f); targetsPos.Add(targetPos - nowForward*soldierOffset - nowRight*soldierOffset/2); targetsPos.Add(targetPos - nowForward*soldierOffset + nowRight*soldierOffset/2); break; } _frontPos = targetPos; return targetsPos; }
|