今天教大家制作王者荣耀中使用的技能范围指示器
类型包含:区域圆形、小范围圆形、矩形、扇形
参考下图:
代码已写好注释,有不懂的可以留言问我。
技能摇杆代码:
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 |
using UnityEngine; using System.Collections; using UnityEngine.UI; using UnityEngine.EventSystems; using System; public class SkillJoystick : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler { public float outerCircleRadius = 100; Transform innerCircleTrans; Vector2 outerCircleStartWorldPos = Vector2.zero; public Action<Vector2> onJoystickDownEvent; // 按下事件 public Action onJoystickUpEvent; // 抬起事件 public Action<Vector2> onJoystickMoveEvent; // 滑动事件 void Awake() { innerCircleTrans = transform.GetChild(0); } void Start() { outerCircleStartWorldPos = transform.position; } /// <summary> /// 按下 /// </summary> public void OnPointerDown(PointerEventData eventData) { innerCircleTrans.position = eventData.position; if (onJoystickDownEvent != null) onJoystickDownEvent(innerCircleTrans.localPosition / outerCircleRadius); } /// <summary> /// 抬起 /// </summary> public void OnPointerUp(PointerEventData eventData) { innerCircleTrans.localPosition = Vector3.zero; if (onJoystickUpEvent != null) onJoystickUpEvent(); } /// <summary> /// 滑动 /// </summary> public void OnDrag(PointerEventData eventData) { Vector2 touchPos = eventData.position - outerCircleStartWorldPos; if (Vector3.Distance(touchPos, Vector2.zero) < outerCircleRadius) innerCircleTrans.localPosition = touchPos; else innerCircleTrans.localPosition = touchPos.normalized * outerCircleRadius; if (onJoystickMoveEvent != null) onJoystickMoveEvent(innerCircleTrans.localPosition / outerCircleRadius); } } |
技能范围指示器代码:
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 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
using UnityEngine; using System.Collections; using System.Collections.Generic; public enum SkillAreaType { OuterCircle = 0, OuterCircle_InnerCube = 1, OuterCircle_InnerSector = 2, OuterCircle_InnerCircle = 3, } public class SkillArea : MonoBehaviour { enum SKillAreaElement { OuterCircle, // 外圆 InnerCircle, // 内圆 Cube, // 矩形 Sector60, // 扇形 Sector120, // 扇形 } SkillJoystick joystick; public GameObject player; public SkillAreaType areaType; // 设置指示器类型 Vector3 deltaVec; float outerRadius = 6; // 外圆半径 float innerRadius = 2f; // 内圆半径 float cubeWidth = 2f; // 矩形宽度 (矩形长度使用的外圆半径) int angle = 60; // 扇形角度 bool isPressed = false; string path = "Effect/Prefabs/Hero_skillarea/"; // 路径 string circle = "quan_hero"; // 圆形 string cube = "chang_hero"; // 矩形 string sector60 = "shan_hero_60"; // 扇形60度 string sector120 = "shan_hero_120"; // 扇形120度 Dictionary<SKillAreaElement, string> allElementPath; Dictionary<SKillAreaElement, Transform> allElementTrans; // Use this for initialization void Start() { joystick = GetComponent<SkillJoystick>(); joystick.onJoystickDownEvent += OnJoystickDownEvent; joystick.onJoystickMoveEvent += OnJoystickMoveEvent; joystick.onJoystickUpEvent += OnJoystickUpEvent; InitSkillAreaType(); } void OnDestroy() { joystick.onJoystickDownEvent -= OnJoystickDownEvent; joystick.onJoystickMoveEvent -= OnJoystickMoveEvent; joystick.onJoystickUpEvent -= OnJoystickUpEvent; } void InitSkillAreaType() { allElementPath = new Dictionary<SKillAreaElement, string>(); allElementPath.Add(SKillAreaElement.OuterCircle, circle); allElementPath.Add(SKillAreaElement.InnerCircle, circle); allElementPath.Add(SKillAreaElement.Cube, cube); allElementPath.Add(SKillAreaElement.Sector60, sector60); allElementPath.Add(SKillAreaElement.Sector120, sector120); allElementTrans = new Dictionary<SKillAreaElement, Transform>(); allElementTrans.Add(SKillAreaElement.OuterCircle, null); allElementTrans.Add(SKillAreaElement.InnerCircle, null); allElementTrans.Add(SKillAreaElement.Cube, null); allElementTrans.Add(SKillAreaElement.Sector60, null); allElementTrans.Add(SKillAreaElement.Sector120, null); } void OnJoystickDownEvent(Vector2 deltaVec) { isPressed = true; this.deltaVec = new Vector3(deltaVec.x, 0, deltaVec.y); CreateSkillArea(); } void OnJoystickUpEvent() { isPressed = false; HideElements(); } void OnJoystickMoveEvent(Vector2 deltaVec) { this.deltaVec = new Vector3(deltaVec.x, 0, deltaVec.y); } void LateUpdate() { if(isPressed) UpdateElement(); } /// <summary> /// 创建技能区域展示 /// </summary> void CreateSkillArea() { switch (areaType) { case SkillAreaType.OuterCircle: CreateElement(SKillAreaElement.OuterCircle); break; case SkillAreaType.OuterCircle_InnerCube: CreateElement(SKillAreaElement.OuterCircle); CreateElement(SKillAreaElement.Cube); break; case SkillAreaType.OuterCircle_InnerSector: CreateElement(SKillAreaElement.OuterCircle); switch (angle) { case 60: CreateElement(SKillAreaElement.Sector60); break; case 120: CreateElement(SKillAreaElement.Sector120); break; default: break; } break; case SkillAreaType.OuterCircle_InnerCircle: CreateElement(SKillAreaElement.OuterCircle); CreateElement(SKillAreaElement.InnerCircle); break; default: break; } } /// <summary> /// 创建技能区域展示元素 /// </summary> /// <param name="element"></param> void CreateElement(SKillAreaElement element) { Transform elementTrans = GetElement(element); if (elementTrans == null) return; allElementTrans[element] = elementTrans; switch (element) { case SKillAreaElement.OuterCircle: elementTrans.localScale = new Vector3(outerRadius * 2, 1, outerRadius * 2) / player.transform.localScale.x; elementTrans.gameObject.SetActive(true); break; case SKillAreaElement.InnerCircle: elementTrans.localScale = new Vector3(innerRadius * 2, 1, innerRadius * 2) / player.transform.localScale.x; break; case SKillAreaElement.Cube: elementTrans.localScale = new Vector3(cubeWidth, 1, outerRadius) / player.transform.localScale.x; break; case SKillAreaElement.Sector60: case SKillAreaElement.Sector120: elementTrans.localScale = new Vector3(outerRadius, 1, outerRadius) / player.transform.localScale.x; break; default: break; } } Transform elementParent; /// <summary> /// 获取元素的父对象 /// </summary> /// <returns></returns> Transform GetParent() { if (elementParent == null) { elementParent = player.transform.FindChild("SkillArea"); } if (elementParent == null) { elementParent = new GameObject("SkillArea").transform; elementParent.parent = player.transform; elementParent.localEulerAngles = Vector3.zero; elementParent.localPosition = Vector3.zero; elementParent.localScale = Vector3.one; } return elementParent; } /// <summary> /// 获取元素物体 /// </summary> Transform GetElement(SKillAreaElement element) { if (player == null) return null; string name = element.ToString(); Transform parent = GetParent(); Transform elementTrans = parent.Find(name); if (elementTrans == null) { GameObject elementGo = Instantiate(Resources.Load(path + allElementPath[element])) as GameObject; elementGo.transform.parent = parent; elementGo.gameObject.SetActive(false); elementGo.name = name; elementTrans = elementGo.transform; } elementTrans.localEulerAngles = Vector3.zero; elementTrans.localPosition = Vector3.zero; elementTrans.localScale = Vector3.one; return elementTrans; } /// <summary> /// 隐藏所有元素 /// </summary> void HideElements() { if (player == null) return; Transform parent = GetParent(); for (int i = 0, length = parent.childCount; i < length; i++) { parent.GetChild(i).gameObject.SetActive(false); } } /// <summary> /// 隐藏指定元素 /// </summary> /// <param name="element"></param> void HideElement(SKillAreaElement element) { if (player == null) return; Transform parent = GetParent(); Transform elementTrans = parent.Find(element.ToString()); if (elementTrans != null) elementTrans.gameObject.SetActive(false); } /// <summary> /// 每帧更新元素 /// </summary> void UpdateElement() { switch (areaType) { case SkillAreaType.OuterCircle: break; case SkillAreaType.OuterCircle_InnerCube: UpdateElementPosition(SKillAreaElement.Cube); break; case SkillAreaType.OuterCircle_InnerSector: switch (angle) { case 60: UpdateElementPosition(SKillAreaElement.Sector60); break; case 120: UpdateElementPosition(SKillAreaElement.Sector120); break; default: break; } break; case SkillAreaType.OuterCircle_InnerCircle: UpdateElementPosition(SKillAreaElement.InnerCircle); break; default: break; } } /// <summary> /// 每帧更新元素位置 /// </summary> /// <param name="element"></param> void UpdateElementPosition(SKillAreaElement element) { if (allElementTrans[element] == null) return; switch (element) { case SKillAreaElement.OuterCircle: break; case SKillAreaElement.InnerCircle: allElementTrans[element].transform.position = GetCirclePosition(outerRadius); break; case SKillAreaElement.Cube: case SKillAreaElement.Sector60: case SKillAreaElement.Sector120: allElementTrans[element].transform.LookAt(GetCubeSectorLookAt()); break; default: break; } if (!allElementTrans[element].gameObject.activeSelf) allElementTrans[element].gameObject.SetActive(true); } /// <summary> /// 获取InnerCircle元素位置 /// </summary> /// <returns></returns> Vector3 GetCirclePosition(float dist) { if (player == null) return Vector3.zero; Vector3 targetDir = deltaVec * dist; float y = Camera.main.transform.rotation.eulerAngles.y; targetDir = Quaternion.Euler(0, y, 0) * targetDir; return targetDir + player.transform.position; } /// <summary> /// 获取Cube、Sector元素朝向 /// </summary> /// <returns></returns> Vector3 GetCubeSectorLookAt() { if (player == null) return Vector3.zero; Vector3 targetDir = deltaVec; float y = Camera.main.transform.rotation.eulerAngles.y; targetDir = Quaternion.Euler(0, y, 0) * targetDir; return targetDir + player.transform.position; } } |
效果展示:
项目使用版本:Unity5.3.4 GitHub下载地址:
https://github.com/654306663/SkillAreaDisplay.git
- 本文固定链接: http://www.u3d8.com/?p=1256
- 转载请注明: 网虫虫 在 u3d8.com 发表过
《制作王者荣耀技能范围指示器》有 18 条评论