825 lines
31 KiB
C#
825 lines
31 KiB
C#
|
using Thousandto.Code.Logic;
|
|||
|
using Thousandto.Code.Logic.WarningField;
|
|||
|
using Thousandto.Core.Asset;
|
|||
|
using Thousandto.Core.Base;
|
|||
|
using Thousandto.Core.PostEffect;
|
|||
|
using Thousandto.Plugins.Common.UniScene;
|
|||
|
using Thousandto.SkillEditor;
|
|||
|
using Thousandto.SkillEditor.DIY;
|
|||
|
using Thousandto.SkillEditor.Support;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.IO;
|
|||
|
using System.Text.RegularExpressions;
|
|||
|
using UnityEditor;
|
|||
|
using UnityEditor.SceneManagement;
|
|||
|
using UnityEngine;
|
|||
|
using UnityEngine.SceneManagement;
|
|||
|
|
|||
|
namespace Thousandto.SkillEditor.DIY
|
|||
|
{
|
|||
|
//技能编辑器预览场景
|
|||
|
public class SkillEditorScene
|
|||
|
{
|
|||
|
#region//私有变量
|
|||
|
private static bool _isLoad = false;
|
|||
|
//场景摄像机
|
|||
|
private static CameraControl _sceneCamera = null;
|
|||
|
private static Camera _camera = null;
|
|||
|
private static RenderTexture _cameraTarget = null;
|
|||
|
private static Rect _drawRect = new Rect(220, 10, 1420, 700);
|
|||
|
private static bool _isMouseDown = false;
|
|||
|
private static Vector2 _frontMousePos = Vector2.zero;
|
|||
|
//场景地表
|
|||
|
private static GameObject _sceneGround = null;
|
|||
|
//主角根节点
|
|||
|
private static GameObject _localRoot = null;
|
|||
|
//目标根节点
|
|||
|
private static GameObject _targetRoot = null;
|
|||
|
|
|||
|
//主角
|
|||
|
private static EditorEntity _localUser = null;
|
|||
|
//主角目标
|
|||
|
private static EditorEntity _localCurTarget = null;
|
|||
|
//目标列表
|
|||
|
private static List<EditorEntity> _targetList = new List<EditorEntity>();
|
|||
|
private static float _frontUpdateTime = 0f;
|
|||
|
//锁定飞行特效列表
|
|||
|
private static List<EditorLockFlyVfx> _lockFlyVfxList = new List<EditorLockFlyVfx>();
|
|||
|
//简单召唤物列表
|
|||
|
private static List<EditorSimpleSkillObject> _simpleObjList = new List<EditorSimpleSkillObject>();
|
|||
|
//召唤物列表
|
|||
|
private static List<EditorSkillObject> _skillObjList = new List<EditorSkillObject>();
|
|||
|
//链接特效列表
|
|||
|
private static List<EditorLinkDamageEffect> _linkObjList = new List<EditorLinkDamageEffect>();
|
|||
|
#endregion
|
|||
|
|
|||
|
#region//属性
|
|||
|
public static EditorEntity LocalUser
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return _localUser;
|
|||
|
}
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region//函数
|
|||
|
public static void Load()
|
|||
|
{
|
|||
|
if (_isLoad)
|
|||
|
return;
|
|||
|
SceneManager.LoadScene("EditorScene");
|
|||
|
|
|||
|
var cameraRoot = new GameObject("[EditorCameraControl]");
|
|||
|
GameObject.DontDestroyOnLoad(cameraRoot);
|
|||
|
_sceneCamera = cameraRoot.RequireComponent<CameraControl>();
|
|||
|
var cameraGo = new GameObject("Camera");
|
|||
|
cameraGo.transform.parent = _sceneCamera.transform;
|
|||
|
cameraGo.transform.localPosition = Vector3.zero;
|
|||
|
cameraGo.transform.rotation = Quaternion.identity;
|
|||
|
cameraGo.transform.localScale = Vector3.one;
|
|||
|
|
|||
|
_camera = cameraGo.RequireComponent<Camera>();
|
|||
|
_camera.clearFlags = CameraClearFlags.Skybox;
|
|||
|
_camera.renderingPath = RenderingPath.Forward;
|
|||
|
_cameraTarget = RenderTexture.GetTemporary(1420, 700, 32, RenderTextureFormat.RGB565);
|
|||
|
_cameraTarget.name = "RenderTexture80";
|
|||
|
_cameraTarget.anisoLevel = 1;
|
|||
|
_camera.targetTexture = _cameraTarget;
|
|||
|
_localRoot = new GameObject("[EditorLocalRoot]");
|
|||
|
GameObject.DontDestroyOnLoad(_localRoot);
|
|||
|
_targetRoot = new GameObject("[EditorTargetRoot]");
|
|||
|
GameObject.DontDestroyOnLoad(_targetRoot);
|
|||
|
_frontUpdateTime = Time.realtimeSinceStartup;
|
|||
|
|
|||
|
PostEffectManager.Instance.Initialize(_camera,false,true);
|
|||
|
NewWarningFiled.LoadAllResEditor();
|
|||
|
SpawnPoolManager.ShareInstance.Initialize();
|
|||
|
FGameObjectVFXRoot.Initialize();
|
|||
|
_isLoad = true;
|
|||
|
}
|
|||
|
|
|||
|
public static void UnLoad()
|
|||
|
{
|
|||
|
if (!_isLoad)
|
|||
|
return;
|
|||
|
|
|||
|
RenderTexture.ReleaseTemporary(_cameraTarget);
|
|||
|
GameObject.DestroyImmediate(_sceneCamera.gameObject);
|
|||
|
GameObject.DestroyImmediate(_localRoot);
|
|||
|
GameObject.DestroyImmediate(_targetRoot);
|
|||
|
_targetList.Clear();
|
|||
|
_localUser = null;
|
|||
|
_localCurTarget = null;
|
|||
|
_isLoad = false;
|
|||
|
PostEffectManager.Instance.Uninitialize();
|
|||
|
for (int i = _lockFlyVfxList.Count - 1; i >= 0; --i)
|
|||
|
{
|
|||
|
_lockFlyVfxList[i].Stop();
|
|||
|
}
|
|||
|
_lockFlyVfxList.Clear();
|
|||
|
for (int i = 0; i < _simpleObjList.Count; ++i)
|
|||
|
{
|
|||
|
_simpleObjList[i].Stop();
|
|||
|
}
|
|||
|
_simpleObjList.Clear();
|
|||
|
|
|||
|
for (int i = 0; i < _skillObjList.Count; ++i)
|
|||
|
{
|
|||
|
_skillObjList[i].Stop();
|
|||
|
}
|
|||
|
_skillObjList.Clear();
|
|||
|
|
|||
|
for (int i = 0; i < _linkObjList.Count; ++i)
|
|||
|
{
|
|||
|
_linkObjList[i].Stop();
|
|||
|
}
|
|||
|
_linkObjList.Clear();
|
|||
|
SpawnPoolManager.ShareInstance.Uninitialize();
|
|||
|
FGameObjectVFXRoot.UnInitialize();
|
|||
|
}
|
|||
|
|
|||
|
public static bool LoadModel(bool isUser, int type, int modelID, int count = 1, float scale = 1f, float moveSpeed = 6f)
|
|||
|
{
|
|||
|
string resPath = string.Empty;
|
|||
|
Transform rootTrans = null;
|
|||
|
EditorObjType objType = EditorObjType.Monster;
|
|||
|
if (type == 0)
|
|||
|
{
|
|||
|
resPath = AssetUtils.GetModelAssetPath(ModelTypeCode.Player, modelID);
|
|||
|
objType = EditorObjType.Player;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
resPath = AssetUtils.GetModelAssetPath(ModelTypeCode.Monster, modelID);
|
|||
|
objType = EditorObjType.Monster;
|
|||
|
}
|
|||
|
|
|||
|
if (isUser)
|
|||
|
{
|
|||
|
rootTrans = _localRoot.transform;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
rootTrans = _targetRoot.transform;
|
|||
|
}
|
|||
|
|
|||
|
GameObject prefab = ResourcesEx.Load(resPath, typeof(GameObject)) as GameObject;
|
|||
|
if (prefab == null)
|
|||
|
return false;
|
|||
|
for (int i = 0; i < count; ++i)
|
|||
|
{
|
|||
|
GameObject model = (GameObject)GameObject.Instantiate(prefab);
|
|||
|
if (isUser)
|
|||
|
{
|
|||
|
if (rootTrans.childCount > 0)
|
|||
|
{
|
|||
|
while (rootTrans.childCount > 0)
|
|||
|
{
|
|||
|
GameObject.DestroyImmediate(rootTrans.GetChild(0).gameObject);
|
|||
|
}
|
|||
|
}
|
|||
|
_sceneCamera.SetTarget(model.transform);
|
|||
|
UnityUtils.SetLayer(model.transform, LayerUtils.LocalPlayer, true);
|
|||
|
_localUser = new EditorEntity(model, objType, scale, moveSpeed);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Vector3 startPos = Vector3.zero;
|
|||
|
if (_localUser != null)
|
|||
|
{
|
|||
|
startPos = _localUser.RootTrans.position;
|
|||
|
}
|
|||
|
model.transform.forward = new Vector3(UnityEngine.Random.Range(-1f, 1f), 0f, UnityEngine.Random.Range(-1f, 1f));
|
|||
|
var target = new EditorEntity(model, objType, scale, moveSpeed);
|
|||
|
target.RootTrans.position = new Vector3(UnityEngine.Random.Range(-10f, 10f) + startPos.x, 0f, UnityEngine.Random.Range(-10f, 10f) + startPos.y);
|
|||
|
_targetList.Add(target);
|
|||
|
UnityUtils.SetLayer(model.transform, LayerUtils.Monster, true);
|
|||
|
}
|
|||
|
model.transform.parent = rootTrans;
|
|||
|
model.SetActive(true);
|
|||
|
model.transform.localScale = new Vector3(scale, scale, scale);
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
public static void ClearAllMonster()
|
|||
|
{
|
|||
|
GameObject.DestroyImmediate(_targetRoot);
|
|||
|
_targetList.Clear();
|
|||
|
|
|||
|
_localCurTarget = null;
|
|||
|
}
|
|||
|
|
|||
|
static bool wDown = false;
|
|||
|
static bool sDown = false;
|
|||
|
static bool aDown = false;
|
|||
|
static bool dDown = false;
|
|||
|
public static void OnGUI()
|
|||
|
{
|
|||
|
bool isSpaceDown = false;
|
|||
|
switch (Event.current.type)
|
|||
|
{
|
|||
|
case EventType.ScrollWheel:
|
|||
|
{
|
|||
|
if (_drawRect.Contains(Event.current.mousePosition))
|
|||
|
{
|
|||
|
_sceneCamera.CurDis += 0.25f * Event.current.delta.y;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case EventType.MouseDown:
|
|||
|
{
|
|||
|
if (Event.current.button == 0 && _drawRect.Contains(Event.current.mousePosition))
|
|||
|
{
|
|||
|
_isMouseDown = true;
|
|||
|
_frontMousePos = Event.current.mousePosition;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case EventType.MouseUp:
|
|||
|
{
|
|||
|
_isMouseDown = false;
|
|||
|
}
|
|||
|
break;
|
|||
|
case EventType.MouseDrag:
|
|||
|
{
|
|||
|
if (_isMouseDown)
|
|||
|
{
|
|||
|
var dtPos = Event.current.mousePosition - _frontMousePos;
|
|||
|
_sceneCamera.CurPitch += dtPos.y * 0.25f;
|
|||
|
if (_sceneCamera.CurPitch < 1)
|
|||
|
{
|
|||
|
_sceneCamera.CurPitch = 1;
|
|||
|
}
|
|||
|
_sceneCamera.CurYaw += dtPos.x * 0.25f;
|
|||
|
_frontMousePos = Event.current.mousePosition;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case EventType.KeyDown:
|
|||
|
{
|
|||
|
if (Event.current.keyCode == KeyCode.W)
|
|||
|
{
|
|||
|
wDown = true;
|
|||
|
Event.current.Use();
|
|||
|
}
|
|||
|
if (Event.current.keyCode == KeyCode.S)
|
|||
|
{
|
|||
|
sDown = true;
|
|||
|
Event.current.Use();
|
|||
|
}
|
|||
|
if (Event.current.keyCode == KeyCode.A)
|
|||
|
{
|
|||
|
aDown = true;
|
|||
|
Event.current.Use();
|
|||
|
}
|
|||
|
if (Event.current.keyCode == KeyCode.D)
|
|||
|
{
|
|||
|
dDown = true;
|
|||
|
Event.current.Use();
|
|||
|
}
|
|||
|
if (Event.current.keyCode == KeyCode.Space)
|
|||
|
{
|
|||
|
isSpaceDown = true;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case EventType.KeyUp:
|
|||
|
{
|
|||
|
if (Event.current.keyCode == KeyCode.W)
|
|||
|
{
|
|||
|
wDown = false;
|
|||
|
Event.current.Use();
|
|||
|
}
|
|||
|
if (Event.current.keyCode == KeyCode.S)
|
|||
|
{
|
|||
|
sDown = false;
|
|||
|
Event.current.Use();
|
|||
|
}
|
|||
|
if (Event.current.keyCode == KeyCode.A)
|
|||
|
{
|
|||
|
aDown = false;
|
|||
|
Event.current.Use();
|
|||
|
}
|
|||
|
if (Event.current.keyCode == KeyCode.D)
|
|||
|
{
|
|||
|
dDown = false;
|
|||
|
Event.current.Use();
|
|||
|
}
|
|||
|
|
|||
|
if (Event.current.keyCode == KeyCode.Tab)
|
|||
|
{
|
|||
|
if (_localCurTarget != null)
|
|||
|
{
|
|||
|
_localCurTarget = null;
|
|||
|
}
|
|||
|
else if (_localUser != null)
|
|||
|
{
|
|||
|
float dis = -1f;
|
|||
|
for (int i = 0; i < _targetList.Count; ++i)
|
|||
|
{
|
|||
|
var curDis = Vector3.SqrMagnitude(_targetList[i].RootTrans.position - _localUser.RootTrans.position);
|
|||
|
if (curDis < dis || dis < 0f)
|
|||
|
{
|
|||
|
dis = curDis;
|
|||
|
_localCurTarget = _targetList[i];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
Event.current.Use();
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
GUI.Box(_drawRect, _cameraTarget);
|
|||
|
if (_localUser != null)
|
|||
|
{
|
|||
|
if (wDown || sDown || aDown || dDown)
|
|||
|
{
|
|||
|
var frontDir = _localUser.RootTrans.position - _sceneCamera.transform.position;
|
|||
|
frontDir.y = 0;
|
|||
|
frontDir = frontDir.normalized;
|
|||
|
float angle = 0f;
|
|||
|
if (wDown && aDown)
|
|||
|
{
|
|||
|
angle = -45f;
|
|||
|
}
|
|||
|
else if (wDown && dDown)
|
|||
|
{
|
|||
|
angle = 45f;
|
|||
|
}
|
|||
|
else if (sDown && aDown)
|
|||
|
{
|
|||
|
angle = -135f;
|
|||
|
}
|
|||
|
else if (sDown && dDown)
|
|||
|
{
|
|||
|
angle = 135f;
|
|||
|
}
|
|||
|
else if (wDown)
|
|||
|
{
|
|||
|
angle = 0f;
|
|||
|
}
|
|||
|
else if (sDown)
|
|||
|
{
|
|||
|
angle = 180f;
|
|||
|
}
|
|||
|
else if (aDown)
|
|||
|
{
|
|||
|
angle = -90f;
|
|||
|
}
|
|||
|
else if (dDown)
|
|||
|
{
|
|||
|
angle = 90f;
|
|||
|
}
|
|||
|
var moveDir = (Quaternion.AngleAxis(angle, Vector3.up) * frontDir).normalized;
|
|||
|
if (isSpaceDown)
|
|||
|
{
|
|||
|
_localUser.JumpTo(moveDir);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_localUser.MoveTo(moveDir, _localCurTarget);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (isSpaceDown)
|
|||
|
{
|
|||
|
_localUser.JumpTo(Vector3.zero);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_localUser.StopSate();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void Update()
|
|||
|
{
|
|||
|
float dt = Time.realtimeSinceStartup - _frontUpdateTime;
|
|||
|
_frontUpdateTime = Time.realtimeSinceStartup;
|
|||
|
dt *= Time.timeScale;
|
|||
|
|
|||
|
_camera.Render();
|
|||
|
PostEffectManager.Instance.Update(dt);
|
|||
|
ResourcesEx.Update(dt);
|
|||
|
FGameObjectVFXRoot.Update();
|
|||
|
|
|||
|
if (_localUser != null)
|
|||
|
{
|
|||
|
_localUser.Update(dt);
|
|||
|
}
|
|||
|
for (int i = _lockFlyVfxList.Count - 1; i >= 0; --i)
|
|||
|
{
|
|||
|
_lockFlyVfxList[i].Update(dt);
|
|||
|
if (_lockFlyVfxList[i].IsFinish)
|
|||
|
{
|
|||
|
_lockFlyVfxList.RemoveAt(i);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (int i = _simpleObjList.Count - 1; i >= 0; --i)
|
|||
|
{
|
|||
|
_simpleObjList[i].Update(dt);
|
|||
|
if (_simpleObjList[i].IsFinish)
|
|||
|
{
|
|||
|
_simpleObjList.RemoveAt(i);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (int i = _skillObjList.Count - 1; i >= 0; --i)
|
|||
|
{
|
|||
|
_skillObjList[i].Update(dt);
|
|||
|
if (_skillObjList[i].IsFinish)
|
|||
|
{
|
|||
|
_skillObjList.RemoveAt(i);
|
|||
|
}
|
|||
|
}
|
|||
|
for (int i = _linkObjList.Count - 1; i >= 0; --i)
|
|||
|
{
|
|||
|
_linkObjList[i].Update(dt);
|
|||
|
if (_linkObjList[i].IsFinish)
|
|||
|
{
|
|||
|
_linkObjList.RemoveAt(i);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i < _targetList.Count; ++i)
|
|||
|
{
|
|||
|
_targetList[i].Update(dt);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void UseSkill(SkillVisualInfo skill)
|
|||
|
{
|
|||
|
if (_localUser != null)
|
|||
|
{
|
|||
|
_localUser.UseSkill(skill);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void DoPauseAnim(SkillVisualInfo skill, int frame, bool showPauseContrast)
|
|||
|
{
|
|||
|
if (_localUser != null)
|
|||
|
{
|
|||
|
_localUser.DoPauseAnim(skill, frame, showPauseContrast);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void PlayHitEvent(EditorBaseObject user, PlayHitEventInfo eventInfo)
|
|||
|
{
|
|||
|
var targetList = FindTargets(user, eventInfo.FindInfo);
|
|||
|
if (targetList.Count > 0)
|
|||
|
{
|
|||
|
EditorEntity mainTarget = null;
|
|||
|
if (targetList.Contains(_localCurTarget))
|
|||
|
{
|
|||
|
mainTarget = _localCurTarget;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
mainTarget = targetList[0];
|
|||
|
_localCurTarget = mainTarget;
|
|||
|
}
|
|||
|
var mainDir = mainTarget.RootTrans.position - user.RootTrans.position;
|
|||
|
mainDir.y = 0f;
|
|||
|
mainDir = mainDir.normalized;
|
|||
|
|
|||
|
for (int i = 0; i < targetList.Count; ++i)
|
|||
|
{
|
|||
|
var target = targetList[i];
|
|||
|
target.DoHitEffect(user, mainDir, eventInfo.HitInfo);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void PlayLinkEffect(EditorEntity user, PlayLinkDamageEventInfo eventInfo)
|
|||
|
{
|
|||
|
var targetList = FindLinkDamageTargets(user, eventInfo.FindInfo);
|
|||
|
if (targetList.Count > 0)
|
|||
|
{
|
|||
|
EditorEntity mainTarget = null;
|
|||
|
if (targetList.Contains(_localCurTarget))
|
|||
|
{
|
|||
|
mainTarget = _localCurTarget;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
mainTarget = targetList[0];
|
|||
|
_localCurTarget = mainTarget;
|
|||
|
}
|
|||
|
var mainDir = mainTarget.RootTrans.position - user.RootTrans.position;
|
|||
|
mainDir.y = 0f;
|
|||
|
mainDir = mainDir.normalized;
|
|||
|
|
|||
|
var effect = new EditorLinkDamageEffect(user, eventInfo, targetList);
|
|||
|
_linkObjList.Add(effect);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void PlaySimpleSkillObject(EditorEntity user, PlaySimpleSkillObjectEventInfo eventInfo)
|
|||
|
{
|
|||
|
if (user == null)
|
|||
|
return;
|
|||
|
|
|||
|
var simpleObj = new EditorSimpleSkillObject(user, eventInfo);
|
|||
|
simpleObj.Start();
|
|||
|
_simpleObjList.Add(simpleObj);
|
|||
|
}
|
|||
|
|
|||
|
public static void PlaySkillObject(EditorEntity user, PlaySkillObjectEventInfo eventInfo)
|
|||
|
{
|
|||
|
if (user == null)
|
|||
|
return;
|
|||
|
var skillObj = new EditorSkillObject(user, eventInfo);
|
|||
|
skillObj.Start();
|
|||
|
_skillObjList.Add(skillObj);
|
|||
|
}
|
|||
|
public static void PlayHitEvent(EditorSimpleSkillObject user)
|
|||
|
{
|
|||
|
var targetList = FindTargets(user, user.EventInfo.FindInfo);
|
|||
|
if (targetList.Count > 0)
|
|||
|
{
|
|||
|
EditorEntity mainTarget = targetList[0]; ;
|
|||
|
var mainDir = mainTarget.RootTrans.position - user.RootTrans.position;
|
|||
|
mainDir.y = 0f;
|
|||
|
mainDir = mainDir.normalized;
|
|||
|
|
|||
|
int maxCount = user.EventInfo.FindInfo.MaxTargetCount;
|
|||
|
int targetIndex = 0;
|
|||
|
for (int i = 0; i < maxCount; ++i)
|
|||
|
{
|
|||
|
var target = targetList[targetIndex];
|
|||
|
target.DoHitEffect(user, mainDir, user.EventInfo.HitInfo);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void PlayLockFlyVfx(EditorEntity user, PlayLockTrajectoryEventInfo eventInfo)
|
|||
|
{
|
|||
|
var slotTrans = SlotUtils.GetSlotTransform(user.RootTrans, eventInfo.StartSlot);
|
|||
|
var resPath = AssetUtils.GetModelAssetPath(ModelTypeCode.SkillVFX, eventInfo.VfxID);
|
|||
|
var targetList = FindTargets(user, eventInfo.FindInfo);
|
|||
|
if (targetList.Count > 0)
|
|||
|
{
|
|||
|
int maxCount = eventInfo.FindInfo.MaxTargetCount;
|
|||
|
int targetIndex = 0;
|
|||
|
for (int i = 0; i < maxCount; ++i)
|
|||
|
{
|
|||
|
var target = targetList[targetIndex];
|
|||
|
var vfxGo = EditorVFXPlayer.Instance.PlayVFX(resPath, null);
|
|||
|
if (vfxGo == null)
|
|||
|
continue;
|
|||
|
|
|||
|
UnityUtils.SetLayer(vfxGo.transform, LayerUtils.LocalPlayer, true);
|
|||
|
vfxGo.transform.position = slotTrans.position;
|
|||
|
var flyVfx = new EditorLockFlyVfx(vfxGo.gameObject, target, eventInfo);
|
|||
|
_lockFlyVfxList.Add(flyVfx);
|
|||
|
|
|||
|
++targetIndex;
|
|||
|
if (targetIndex >= targetList.Count)
|
|||
|
{
|
|||
|
if (eventInfo.CanHitRepeatTarget != 0)
|
|||
|
{
|
|||
|
targetIndex = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
struct EditorSearchTargetInfo
|
|||
|
{
|
|||
|
public EditorEntity target;
|
|||
|
public float distanceSq;
|
|||
|
public EditorSearchTargetInfo(EditorEntity target, float distanceSq)
|
|||
|
{
|
|||
|
this.target = target;
|
|||
|
this.distanceSq = distanceSq;
|
|||
|
}
|
|||
|
}
|
|||
|
public static EditorEntity FindMainTarget(EditorEntity user)
|
|||
|
{
|
|||
|
if (_localCurTarget != null)
|
|||
|
return _localCurTarget;
|
|||
|
Vector2 userPos = new Vector2(user.RootTrans.position.x, user.RootTrans.position.z);
|
|||
|
|
|||
|
List<EditorSearchTargetInfo> searchCache = new List<EditorSearchTargetInfo>(32);
|
|||
|
for (int i = 0; i < _targetList.Count; ++i)
|
|||
|
{
|
|||
|
var c = _targetList[i];
|
|||
|
var tPos = new Vector2(c.RootTrans.position.x, c.RootTrans.position.z);
|
|||
|
float disSq = (userPos - tPos).sqrMagnitude;
|
|||
|
searchCache.Add(new EditorSearchTargetInfo(c, disSq));
|
|||
|
}
|
|||
|
if (searchCache.Count > 0)
|
|||
|
{
|
|||
|
searchCache.Sort(
|
|||
|
(left, right) =>
|
|||
|
{
|
|||
|
return left.distanceSq.CompareTo(right.distanceSq);
|
|||
|
}
|
|||
|
);
|
|||
|
|
|||
|
return searchCache[0].target;
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
public static List<EditorEntity> FindTargets(EditorBaseObject user, FindTargetInfo findInfo)
|
|||
|
{
|
|||
|
Vector2 userPos = new Vector2(user.RootTrans.position.x, user.RootTrans.position.z);
|
|||
|
Vector2 userDir = new Vector2(user.RootTrans.forward.x, user.RootTrans.forward.z);
|
|||
|
|
|||
|
List<EditorSearchTargetInfo> searchCache = new List<EditorSearchTargetInfo>(32);
|
|||
|
switch (findInfo.AreaType)
|
|||
|
{
|
|||
|
case SkillTargetArea.Rectangle: //矩形
|
|||
|
{
|
|||
|
float width = findInfo.RectWidth;
|
|||
|
float height = findInfo.RectHeight;
|
|||
|
|
|||
|
var skillAreaShape = new Math2d.Obb(userPos, userDir, width / 2, height, 0);
|
|||
|
|
|||
|
for (int i = 0; i < _targetList.Count; ++i)
|
|||
|
{
|
|||
|
var c = _targetList[i];
|
|||
|
var tPos = new Vector2(c.RootTrans.position.x, c.RootTrans.position.z);
|
|||
|
var tarCircle = new Math2d.Circle(tPos, 1f);
|
|||
|
if (Math2d.CollisionTest(skillAreaShape, tarCircle))
|
|||
|
{
|
|||
|
float disSq = (userPos - tPos).sqrMagnitude;
|
|||
|
searchCache.Add(new EditorSearchTargetInfo(c, disSq));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case SkillTargetArea.FanShaped: //扇形
|
|||
|
{
|
|||
|
int angle = (int)findInfo.SectorAngle;
|
|||
|
float radius = findInfo.SectorRadius;
|
|||
|
|
|||
|
var skillAreaShape = new Math2d.Sector(userPos, radius, userDir, angle * Mathf.Deg2Rad * 0.5f);
|
|||
|
for (int i = 0; i < _targetList.Count; ++i)
|
|||
|
{
|
|||
|
var c = _targetList[i];
|
|||
|
var tPos = new Vector2(c.RootTrans.position.x, c.RootTrans.position.z);
|
|||
|
var tarCircle = new Math2d.Circle(tPos, 1f);
|
|||
|
if (Math2d.CollisionTest(ref skillAreaShape, ref tarCircle))
|
|||
|
{
|
|||
|
float disSq = (userPos - tPos).sqrMagnitude;
|
|||
|
searchCache.Add(new EditorSearchTargetInfo(c, disSq));
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case SkillTargetArea.Round: //圆形
|
|||
|
{
|
|||
|
float radius = findInfo.RoundRadius;
|
|||
|
var skillCircle = new Math2d.Circle(userPos, radius);
|
|||
|
for (int i = 0; i < _targetList.Count; ++i)
|
|||
|
{
|
|||
|
var c = _targetList[i];
|
|||
|
var tPos = new Vector2(c.RootTrans.position.x, c.RootTrans.position.z);
|
|||
|
var tarCircle = new Math2d.Circle(tPos, 1f);
|
|||
|
if (Math2d.CollisionTest(ref skillCircle, ref tarCircle))
|
|||
|
{
|
|||
|
float disSq = (userPos - tPos).sqrMagnitude;
|
|||
|
searchCache.Add(new EditorSearchTargetInfo(c, disSq));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
List<EditorEntity> result = new List<EditorEntity>();
|
|||
|
if (searchCache.Count > 0)
|
|||
|
{
|
|||
|
searchCache.Sort(
|
|||
|
(left, right) =>
|
|||
|
{
|
|||
|
return left.distanceSq.CompareTo(right.distanceSq);
|
|||
|
}
|
|||
|
);
|
|||
|
|
|||
|
for (int i = 0; i < findInfo.MaxTargetCount && i < searchCache.Count; ++i)
|
|||
|
{
|
|||
|
result.Add(searchCache[i].target);
|
|||
|
}
|
|||
|
searchCache.Clear();
|
|||
|
return result;
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public static List<EditorEntity> FindLinkDamageTargets(EditorBaseObject user, FindTargetInfo findInfo)
|
|||
|
{
|
|||
|
Vector2 userPos = new Vector2(user.RootTrans.position.x, user.RootTrans.position.z);
|
|||
|
Vector2 userDir = new Vector2(user.RootTrans.forward.x, user.RootTrans.forward.z);
|
|||
|
|
|||
|
List<EditorSearchTargetInfo> searchCache = new List<EditorSearchTargetInfo>(32);
|
|||
|
switch (findInfo.AreaType)
|
|||
|
{
|
|||
|
case SkillTargetArea.Rectangle: //矩形
|
|||
|
{
|
|||
|
float width = findInfo.RectWidth;
|
|||
|
float height = findInfo.RectHeight;
|
|||
|
|
|||
|
var skillAreaShape = new Math2d.Obb(userPos, userDir, width / 2, height, 0);
|
|||
|
|
|||
|
for (int i = 0; i < _targetList.Count; ++i)
|
|||
|
{
|
|||
|
var c = _targetList[i];
|
|||
|
var tPos = new Vector2(c.RootTrans.position.x, c.RootTrans.position.z);
|
|||
|
var tarCircle = new Math2d.Circle(tPos, 1f);
|
|||
|
if (Math2d.CollisionTest(skillAreaShape, tarCircle))
|
|||
|
{
|
|||
|
float disSq = VectorAngle(tPos - userPos, new Vector2(user.RootTrans.forward.x, user.RootTrans.forward.z));
|
|||
|
searchCache.Add(new EditorSearchTargetInfo(c, disSq));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case SkillTargetArea.FanShaped: //扇形
|
|||
|
{
|
|||
|
int angle = (int)findInfo.SectorAngle;
|
|||
|
float radius = findInfo.SectorRadius;
|
|||
|
|
|||
|
var skillAreaShape = new Math2d.Sector(userPos, radius, userDir, angle * Mathf.Deg2Rad * 0.5f);
|
|||
|
for (int i = 0; i < _targetList.Count; ++i)
|
|||
|
{
|
|||
|
var c = _targetList[i];
|
|||
|
var tPos = new Vector2(c.RootTrans.position.x, c.RootTrans.position.z);
|
|||
|
var tarCircle = new Math2d.Circle(tPos, 1f);
|
|||
|
if (Math2d.CollisionTest(ref skillAreaShape, ref tarCircle))
|
|||
|
{
|
|||
|
float disSq = VectorAngle(tPos - userPos, new Vector2(user.RootTrans.forward.x, user.RootTrans.forward.z));
|
|||
|
searchCache.Add(new EditorSearchTargetInfo(c, disSq));
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case SkillTargetArea.Round: //圆形
|
|||
|
{
|
|||
|
float radius = findInfo.RoundRadius;
|
|||
|
var skillCircle = new Math2d.Circle(userPos, radius);
|
|||
|
for (int i = 0; i < _targetList.Count; ++i)
|
|||
|
{
|
|||
|
var c = _targetList[i];
|
|||
|
var tPos = new Vector2(c.RootTrans.position.x, c.RootTrans.position.z);
|
|||
|
var tarCircle = new Math2d.Circle(tPos, 1f);
|
|||
|
if (Math2d.CollisionTest(ref skillCircle, ref tarCircle))
|
|||
|
{
|
|||
|
float disSq = VectorAngle(tPos - userPos, new Vector2(user.RootTrans.forward.x, user.RootTrans.forward.z));
|
|||
|
searchCache.Add(new EditorSearchTargetInfo(c, disSq));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
List<EditorEntity> result = new List<EditorEntity>();
|
|||
|
if (searchCache.Count > 0)
|
|||
|
{
|
|||
|
searchCache.Sort(
|
|||
|
(left, right) =>
|
|||
|
{
|
|||
|
return left.distanceSq.CompareTo(right.distanceSq);
|
|||
|
}
|
|||
|
);
|
|||
|
|
|||
|
for (int i = 0; i < findInfo.MaxTargetCount && i < searchCache.Count; ++i)
|
|||
|
{
|
|||
|
result.Add(searchCache[i].target);
|
|||
|
}
|
|||
|
searchCache.Clear();
|
|||
|
return result;
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
public static float VectorAngle(Vector2 from, Vector2 to)
|
|||
|
{
|
|||
|
float angle;
|
|||
|
|
|||
|
Vector3 cross = Vector3.Cross(from, to);
|
|||
|
angle = Vector2.Angle(from, to);
|
|||
|
return cross.z > 0 ? -angle : angle;
|
|||
|
}
|
|||
|
#endregion
|
|||
|
}
|
|||
|
}
|