Files
Main/Assets/Editor/DIY/SkillEditor/SkillEditorScene.cs

825 lines
31 KiB
C#
Raw Permalink Normal View History

2025-01-25 04:38:09 +08:00
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
}
}