7
Assets/Assets.sln.meta
Normal file
7
Assets/Assets.sln.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 459a7ea4ef65c664482b6377848ac5c3
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -520,15 +520,15 @@ namespace Dreamteck.Splines
|
||||
#endif
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (updateMethod == UpdateMethod.FixedUpdate)
|
||||
{
|
||||
Run();
|
||||
RunUpdate();
|
||||
LateRun();
|
||||
}
|
||||
}
|
||||
// private void FixedUpdate()
|
||||
// {
|
||||
// if (updateMethod == UpdateMethod.FixedUpdate)
|
||||
// {
|
||||
// Run();
|
||||
// RunUpdate();
|
||||
// LateRun();
|
||||
// }
|
||||
// }
|
||||
|
||||
//Update logic for handling threads and rebuilding
|
||||
private void RunUpdate()
|
||||
|
||||
32762
Assets/FR2_Cache.asset
32762
Assets/FR2_Cache.asset
File diff suppressed because it is too large
Load Diff
7
Assets/NLayer/NLayer.csproj.meta
Normal file
7
Assets/NLayer/NLayer.csproj.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6dbdd314784e80440b48088e6357c1ef
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -14,7 +14,7 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class Hold : NoteBase
|
||||
{
|
||||
public static List<Hold> holdingHoldList = new();
|
||||
//public static List<Hold> holdingHoldList = new();
|
||||
|
||||
public float holdEndTime;
|
||||
public float holdingTime;
|
||||
@@ -65,7 +65,6 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
EditorManager.instance.projectManager.notePrefabManager.LoadNotePrefab(hold, GetNoteTypeName(hold) + "_Prefab");
|
||||
}
|
||||
|
||||
return hold;
|
||||
|
||||
}
|
||||
@@ -157,17 +156,24 @@ namespace Ichni.RhythmGame
|
||||
|
||||
public partial class Hold
|
||||
{
|
||||
protected override void Update()
|
||||
// 添加类级别缓存
|
||||
private static HashSet<Hold> holdingHoldSet = new HashSet<Hold>(); // 替换List为HashSet
|
||||
public override void UpdateNote()
|
||||
{
|
||||
if (Keyboard.current.hKey.wasPressedThisFrame)
|
||||
{
|
||||
foreach (KeyValuePair<string, List<EffectBase>> effect in noteVisual.effectSubmodule.effectCollection)
|
||||
// 优化:避免字典枚举和Lambda
|
||||
var effectCollection = noteVisual.effectSubmodule.effectCollection;
|
||||
foreach (var pair in effectCollection)
|
||||
{
|
||||
effect.Value.ForEach(x => x.Disrupt());
|
||||
var effects = pair.Value;
|
||||
for (int i = 0; i < effects.Count; i++)
|
||||
{
|
||||
effects[i].Disrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (holdEndTime < exactJudgeTime)
|
||||
{
|
||||
LogWindow.Log("Hold end time is earlier than exact judge time.", Color.red);
|
||||
@@ -192,7 +198,6 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
isHolding = false;
|
||||
isFinalJudged = true;
|
||||
//noteAudioSubmodule?.PlayNoteJudgeAudios(EditorManager.instance.currentJudgeType);//有待商榷
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,56 +211,74 @@ namespace Ichni.RhythmGame
|
||||
}
|
||||
}
|
||||
|
||||
// 优化:避免LINQ查询
|
||||
if (noteJudgeSubmodule != null && !EditorManager.instance.cameraManager.isSceneCameraActive)
|
||||
{
|
||||
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
|
||||
var judgeUnits = noteJudgeSubmodule.judgeUnitList;
|
||||
for (int i = 0; i < judgeUnits.Count; i++)
|
||||
{
|
||||
unit.UpdateJudge();
|
||||
var unit = judgeUnits[i];
|
||||
if (unit.isShowingJudge)
|
||||
{
|
||||
unit.UpdateJudge();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (noteVisual != null)
|
||||
{
|
||||
noteVisual.effectSubmodule.effectCollection["Generate"].ForEach(e => e.UpdateEffect(exactJudgeTime));
|
||||
noteVisual.effectSubmodule.effectCollection["StartHold"].ForEach(e => e.UpdateEffect(exactJudgeTime));
|
||||
noteVisual.effectSubmodule.effectCollection["Holding"].ForEach(e => e.UpdateEffect(exactJudgeTime));
|
||||
// 优化:缓存常用引用,避免重复字典查找
|
||||
var effectSubmodule = noteVisual.effectSubmodule;
|
||||
var effectColl = effectSubmodule.effectCollection;
|
||||
|
||||
// 优化:手动遍历避免Lambda
|
||||
UpdateEffectList(effectColl["Generate"], exactJudgeTime);
|
||||
UpdateEffectList(effectColl["StartHold"], exactJudgeTime);
|
||||
UpdateEffectList(effectColl["Holding"], exactJudgeTime);
|
||||
UpdateEffectList(effectColl["GeneralJudge"], holdEndTime);
|
||||
UpdateEffectList(effectColl["AfterJudge"], holdEndTime);
|
||||
|
||||
noteVisual.effectSubmodule.effectCollection["GeneralJudge"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
switch (EditorManager.instance.currentJudgeType)
|
||||
// 优化switch语句
|
||||
var judgeType = EditorManager.instance.currentJudgeType;
|
||||
switch (judgeType)
|
||||
{
|
||||
case NoteJudgeType.Perfect:
|
||||
noteVisual.effectSubmodule.effectCollection["Perfect"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
UpdateEffectList(effectColl["Perfect"], holdEndTime);
|
||||
break;
|
||||
case NoteJudgeType.Good:
|
||||
noteVisual.effectSubmodule.effectCollection["Good"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
UpdateEffectList(effectColl["Good"], holdEndTime);
|
||||
break;
|
||||
case NoteJudgeType.Bad:
|
||||
noteVisual.effectSubmodule.effectCollection["Bad"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
UpdateEffectList(effectColl["Bad"], holdEndTime);
|
||||
break;
|
||||
case NoteJudgeType.Miss:
|
||||
noteVisual.effectSubmodule.effectCollection["Miss"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
UpdateEffectList(effectColl["Miss"], holdEndTime);
|
||||
break;
|
||||
}
|
||||
|
||||
noteVisual.effectSubmodule.effectCollection["AfterJudge"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
|
||||
if (EditorManager.instance.cameraManager.haveGameCamera)
|
||||
{
|
||||
noteScreenPosition = EditorManager.instance.cameraManager.gameCamera.gameCamera.WorldToScreenPoint(noteVisual.noteVisualPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// 优化持有列表的添加和移除
|
||||
// 优化:使用HashSet避免Contains的GC
|
||||
if (isHolding)
|
||||
{
|
||||
if (!holdingHoldList.Contains(this))
|
||||
holdingHoldList.Add(this);
|
||||
holdingHoldSet.Add(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (holdingHoldList.Contains(this))
|
||||
holdingHoldList.Remove(this);
|
||||
holdingHoldSet.Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:避免Lambda产生的GC
|
||||
private void UpdateEffectList(List<EffectBase> effects, float time)
|
||||
{
|
||||
for (int i = 0; i < effects.Count; i++)
|
||||
{
|
||||
effects[i].UpdateEffect(time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Ichni.RhythmGame
|
||||
|
||||
[Title("NoteVisual")]
|
||||
public NoteVisualBase noteVisual;
|
||||
public float NoteAppearTime => noteVisual ? noteVisual.NoteAppearTime : -1;
|
||||
|
||||
[Title("Submodules")]
|
||||
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
||||
@@ -33,9 +34,22 @@ namespace Ichni.RhythmGame
|
||||
[FormerlySerializedAs("isJudged")] public bool isFirstJudged;
|
||||
public override int HierarchyPriority => -10;
|
||||
|
||||
|
||||
public override void Initialize(string name, Guid elementGuid, List<string> tags, bool isFirstGenerated, GameElement parentElement)
|
||||
{
|
||||
base.Initialize(name, elementGuid, tags, isFirstGenerated, parentElement);
|
||||
NoteManager.instance.AddNote(this);
|
||||
|
||||
}
|
||||
public override void AfterInitialize()
|
||||
{
|
||||
base.AfterInitialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在MovableTrack上更新Note的位置,注意HoldNote需要重写这个方法
|
||||
/// </summary>
|
||||
|
||||
public virtual void UpdateNoteInMovableTrack()
|
||||
{
|
||||
TrackTimeSubmoduleMovable trackTimeSubmoduleMovable = track.trackTimeSubmodule as TrackTimeSubmoduleMovable;
|
||||
@@ -75,7 +89,7 @@ namespace Ichni.RhythmGame
|
||||
|
||||
foreach (SampleWindow i in SampleWindow.instances.Where(i => i.gameElement)) i.OnceSpawnNote();
|
||||
}
|
||||
protected virtual void Update()
|
||||
public virtual void UpdateNote()
|
||||
{
|
||||
var editor = EditorManager.instance;
|
||||
var cameraManager = editor.cameraManager;
|
||||
@@ -91,13 +105,13 @@ namespace Ichni.RhythmGame
|
||||
if (isFirstJudged && songTime < exactJudgeTime)
|
||||
{
|
||||
isFirstJudged = false;
|
||||
noteVisual.GetComponent<Collider>().enabled = !isFirstJudged;
|
||||
if (noteVisual != null) noteVisual.GetComponent<Collider>().enabled = !isFirstJudged;
|
||||
}
|
||||
else if (!isFirstJudged && songTime >= exactJudgeTime)
|
||||
{
|
||||
noteAudioSubmodule?.PlayNoteJudgeAudios(editor.currentJudgeType);
|
||||
isFirstJudged = true;
|
||||
noteVisual.GetComponent<Collider>().enabled = !isFirstJudged;
|
||||
if (noteVisual != null) noteVisual.GetComponent<Collider>().enabled = !isFirstJudged;
|
||||
}
|
||||
|
||||
// 判定单元更新
|
||||
@@ -235,6 +249,11 @@ namespace Ichni.RhythmGame
|
||||
foreach (SampleWindow i in SampleWindow.instances.Where(i => i.gameElement)) i.OnceSpawnNote();
|
||||
|
||||
}
|
||||
NoteManager.instance.RemoveNote(this);
|
||||
if (noteVisual != null)
|
||||
{
|
||||
noteVisual.OnDelete();
|
||||
}
|
||||
}
|
||||
|
||||
public int CompareTo(NoteBase other)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.Editor;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
@@ -21,7 +23,10 @@ namespace Ichni.RhythmGame
|
||||
public List<GameObject> effectPrefabList;
|
||||
|
||||
public virtual Vector3 noteVisualPosition => noteMain.transform.position;
|
||||
|
||||
|
||||
public NoteGenerateEffect generateEffect;
|
||||
public float NoteAppearTime => generateEffect is null ? note.exactJudgeTime : note.exactJudgeTime - generateEffect.generateTime;
|
||||
|
||||
public EffectSubmodule effectSubmodule { get; set; }
|
||||
public SelectSubmodule selectSubmodule { get; set; }
|
||||
|
||||
@@ -34,8 +39,19 @@ namespace Ichni.RhythmGame
|
||||
noteVisual.isHighlighted = isHighlighted;
|
||||
noteVisual.SetHighlight();
|
||||
noteVisual.SetEditorSubmodules();
|
||||
Observable.NextFrame().Subscribe(_ =>
|
||||
{
|
||||
noteVisual.AfterInitialize();
|
||||
|
||||
});
|
||||
return noteVisual;
|
||||
}
|
||||
public override void AfterInitialize()
|
||||
{
|
||||
base.AfterInitialize();
|
||||
generateEffect ??= effectSubmodule.effectCollection["Generate"].First(i => i is NoteGenerateEffect) as NoteGenerateEffect;
|
||||
if (generateEffect == null) throw new Exception("NoteVisual必须有一个生成特效。");
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
@@ -48,7 +64,7 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
selectSubmodule ??= new SelectSubmodule(this, note);
|
||||
}
|
||||
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
@@ -63,7 +79,7 @@ namespace Ichni.RhythmGame
|
||||
inspector.GenerateToggle(this, settingsSubcontainer, "Highlight", nameof(isHighlighted))
|
||||
.AddListenerFunction(SetHighlight);
|
||||
}
|
||||
|
||||
|
||||
public virtual void Recover()
|
||||
{
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Lean.Pool;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
@@ -19,28 +18,47 @@ namespace Ichni.Editor
|
||||
[Tooltip("指定网格所在的平面:0 = XZ (y=0), 1 = XY (z=0), 2 = YZ (x=0)")]
|
||||
public int gridPlane = 0;
|
||||
|
||||
[Tooltip("网格基础缩放值,单位 1")] public float baseScale = 1f;
|
||||
[Tooltip("网格基础缩放值,单位 1")]
|
||||
public float baseScale = 1f;
|
||||
|
||||
[Tooltip("调整缩放的影响因子,建议值 1~5")] public float scaleMultiplier = 1f;
|
||||
[Tooltip("调整缩放的影响因子,建议值 1~5")]
|
||||
public float scaleMultiplier = 1f;
|
||||
|
||||
[Tooltip("距离因子,用于计算对数缩放(例如距离大于该值时切换到下一级单位)")]
|
||||
public float distanceFactor = 10f;
|
||||
|
||||
[Tooltip("位置文本更新频率(秒)")]
|
||||
public float textUpdateFrequency = 0.1f;
|
||||
|
||||
[FormerlySerializedAs("showPositionText")]
|
||||
public bool canShowPositionText;
|
||||
|
||||
public bool isShowingPositionText;
|
||||
public Transform textContainer;
|
||||
public GameObject positionTextPrefab;
|
||||
|
||||
// 内部缓存材质
|
||||
private Material gridMaterial;
|
||||
public Dictionary<GameObject, Vector3> positionTexts = new Dictionary<GameObject, Vector3>();
|
||||
|
||||
// 对象池相关
|
||||
private Queue<GameObject> textPool = new Queue<GameObject>();
|
||||
private const int POOL_SIZE = 50;
|
||||
|
||||
// 性能优化缓存
|
||||
private float lastTextUpdateTime = 0f;
|
||||
private Vector3 lastCameraPosition;
|
||||
private float lastGridScale;
|
||||
private Plane gridPlaneCache;
|
||||
private Vector2 screenCenter;
|
||||
|
||||
public float logScale;
|
||||
public float gridScale; // 1, 4, 16, 64...
|
||||
|
||||
[FormerlySerializedAs("showPositionText")] public bool canShowPositionText;
|
||||
public bool isShowingPositionText;
|
||||
public Transform textContainer;
|
||||
public GameObject positionTextPrefab;
|
||||
public Dictionary<GameObject, Vector3> positionTexts;
|
||||
|
||||
void Start()
|
||||
{
|
||||
positionTexts = new Dictionary<GameObject, Vector3>();
|
||||
|
||||
InitializeTextPool();
|
||||
|
||||
sceneCamera = EditorManager.instance.cameraManager.sceneCamera.sceneCamera;
|
||||
// 实例化材质,避免修改共享材质
|
||||
@@ -52,6 +70,12 @@ namespace Ichni.Editor
|
||||
float screenWidth = Screen.width;
|
||||
float lineWidth = lineWidthOf3840 * (screenWidth / 3840f);
|
||||
gridMaterial.SetFloat("_LineWidth", lineWidth);
|
||||
|
||||
// 预计算屏幕中心
|
||||
screenCenter = new Vector2(Screen.width / 2f, Screen.height / 2f);
|
||||
|
||||
// 预计算网格平面
|
||||
UpdateGridPlaneCache();
|
||||
}
|
||||
|
||||
void Update()
|
||||
@@ -84,84 +108,266 @@ namespace Ichni.Editor
|
||||
|
||||
if (canShowPositionText && isShowingPositionText)
|
||||
{
|
||||
GetPoints();
|
||||
// 添加更新频率控制
|
||||
bool shouldUpdate = Time.time - lastTextUpdateTime >= textUpdateFrequency ||
|
||||
Vector3.Distance(sceneCamera.transform.position, lastCameraPosition) > gridScale * 0.5f ||
|
||||
Mathf.Abs(gridScale - lastGridScale) > 0.1f;
|
||||
|
||||
foreach (KeyValuePair<GameObject, Vector3> positionText in positionTexts)
|
||||
if (shouldUpdate)
|
||||
{
|
||||
positionText.Key.transform.position = positionText.Value + new Vector3(gridScale / 6, 0, gridScale / 12);
|
||||
float scaleFactor = gridScale * 1.5f;
|
||||
positionText.Key.transform.localScale = new Vector3(scaleFactor, scaleFactor, scaleFactor);
|
||||
Vector3 direction = EditorManager.instance.cameraManager.currentCamera.transform.position - positionText.Key.transform.position;
|
||||
positionText.Key.transform.forward = -direction.normalized;
|
||||
GetPoints();
|
||||
lastTextUpdateTime = Time.time;
|
||||
lastCameraPosition = sceneCamera.transform.position;
|
||||
lastGridScale = gridScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 只更新文本朝向(性能较轻)
|
||||
UpdateTextOrientations();
|
||||
}
|
||||
}
|
||||
else if (isShowingPositionText && !canShowPositionText)
|
||||
{
|
||||
ClearAllTexts();
|
||||
isShowingPositionText = false;
|
||||
}
|
||||
}
|
||||
|
||||
#region 文本显示优化
|
||||
|
||||
private void InitializeTextPool()
|
||||
{
|
||||
for (int i = 0; i < POOL_SIZE; i++)
|
||||
{
|
||||
GameObject textObj = Instantiate(positionTextPrefab, textContainer);
|
||||
textObj.SetActive(false);
|
||||
textPool.Enqueue(textObj);
|
||||
}
|
||||
}
|
||||
|
||||
private GameObject GetTextFromPool()
|
||||
{
|
||||
if (textPool.Count > 0)
|
||||
{
|
||||
GameObject textObj = textPool.Dequeue();
|
||||
textObj.SetActive(true);
|
||||
return textObj;
|
||||
}
|
||||
|
||||
// 如果池子空了,动态创建一个(应该很少发生)
|
||||
GameObject newTextObj = Instantiate(positionTextPrefab, textContainer);
|
||||
return newTextObj;
|
||||
}
|
||||
|
||||
private void ReturnTextToPool(GameObject textObj)
|
||||
{
|
||||
textObj.SetActive(false);
|
||||
textPool.Enqueue(textObj);
|
||||
}
|
||||
|
||||
private void UpdateTextOrientations()
|
||||
{
|
||||
foreach (var textObj in positionTexts.Keys)
|
||||
{
|
||||
if (textObj != null && textObj.activeInHierarchy)
|
||||
{
|
||||
Vector3 direction = sceneCamera.transform.position - textObj.transform.position;
|
||||
textObj.transform.forward = -direction.normalized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearAllTexts()
|
||||
{
|
||||
foreach (var textObj in positionTexts.Keys)
|
||||
{
|
||||
if (textObj != null)
|
||||
{
|
||||
ReturnTextToPool(textObj);
|
||||
}
|
||||
}
|
||||
positionTexts.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 网格点计算优化
|
||||
|
||||
void GetPoints()
|
||||
{
|
||||
Ray sceneCameraRay = sceneCamera.ScreenPointToRay(new Vector2(Screen.width / 2f, Screen.height / 2f));
|
||||
if (Physics.Raycast(sceneCameraRay, out RaycastHit sceneCameraHit, float.MaxValue, LayerMask.GetMask("Grid")))
|
||||
// 使用平面射线检测替代 Physics.Raycast(性能更好)
|
||||
Ray sceneCameraRay = sceneCamera.ScreenPointToRay(screenCenter);
|
||||
|
||||
if (gridPlaneCache.Raycast(sceneCameraRay, out float enter))
|
||||
{
|
||||
if (sceneCameraHit.collider.gameObject == gameObject)
|
||||
Vector3 point = sceneCameraRay.GetPoint(enter);
|
||||
|
||||
// 添加距离检查,太远就不显示文本
|
||||
float distanceToCamera = Vector3.Distance(sceneCamera.transform.position, point);
|
||||
if (distanceToCamera > 50f)
|
||||
{
|
||||
Vector3 point = sceneCameraHit.point;
|
||||
ClearAllTexts();
|
||||
return;
|
||||
}
|
||||
|
||||
float radius = gridScale * 16f;
|
||||
float step = gridScale * 4f;
|
||||
float radius = gridScale * 16f;
|
||||
float step = gridScale * 4f;
|
||||
|
||||
float minX = point.x - radius;
|
||||
float maxX = point.x + radius;
|
||||
float minZ = point.z - radius;
|
||||
float maxZ = point.z + radius;
|
||||
// 计算可见区域边界
|
||||
Vector2Int minMaxX = CalculateBounds(point.x, radius, step);
|
||||
Vector2Int minMaxZ = CalculateBounds(point.z, radius, step);
|
||||
|
||||
// 对于 X 与 Z 方向,根据网格间距取整,确保从整点开始
|
||||
minX = Mathf.Floor(minX / step) * step;
|
||||
maxX = Mathf.Ceil(maxX / step) * step;
|
||||
minZ = Mathf.Floor(minZ / step) * step;
|
||||
maxZ = Mathf.Ceil(maxZ / step) * step;
|
||||
// 使用 HashSet 来跟踪需要显示的位置(避免重复计算)
|
||||
HashSet<Vector3> requiredPositions = new HashSet<Vector3>();
|
||||
|
||||
List<Vector3> newPositions = new List<Vector3>();
|
||||
|
||||
// 添加距离检测逻辑
|
||||
bool withinDistance = Vector3.Distance(sceneCamera.transform.position, point) <= 50f;
|
||||
|
||||
for (float x = minX; x <= maxX; x += step)
|
||||
for (int x = minMaxX.x; x <= minMaxX.y; x++)
|
||||
{
|
||||
for (int z = minMaxZ.x; z <= minMaxZ.y; z++)
|
||||
{
|
||||
for (float z = minZ; z <= maxZ; z += step)
|
||||
{
|
||||
Vector3 position = new Vector3(x, 0, z);
|
||||
|
||||
if (withinDistance && !positionTexts.ContainsValue(position))
|
||||
{
|
||||
GameObject posText = LeanPool.Spawn(positionTextPrefab);
|
||||
posText.transform.position = position + new Vector3(gridScale / 8, 0, gridScale / 16);
|
||||
posText.transform.forward = -transform.up;
|
||||
posText.GetComponent<TMP_Text>().text = $"({Mathf.RoundToInt(position.x)}, {Mathf.RoundToInt(position.z)})";
|
||||
posText.transform.SetParent(textContainer);
|
||||
positionTexts.Add(posText, position);
|
||||
}
|
||||
|
||||
newPositions.Add(new Vector3(x, 0, z));
|
||||
}
|
||||
Vector3 position = new Vector3(x * step, 0, z * step);
|
||||
requiredPositions.Add(position);
|
||||
}
|
||||
}
|
||||
|
||||
List<GameObject> toRemove = new List<GameObject>();
|
||||
// 清除不在新范围内的Text
|
||||
foreach (KeyValuePair<GameObject, Vector3> positionText in positionTexts)
|
||||
{
|
||||
if (!newPositions.Contains(positionText.Value))
|
||||
{
|
||||
LeanPool.Despawn(positionText.Key);
|
||||
toRemove.Add(positionText.Key);
|
||||
}
|
||||
}
|
||||
UpdateTextDisplay(requiredPositions);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GameObject text in toRemove)
|
||||
{
|
||||
positionTexts.Remove(text);
|
||||
}
|
||||
// 辅助方法:计算边界(避免重复的数学运算)
|
||||
private Vector2Int CalculateBounds(float center, float radius, float step)
|
||||
{
|
||||
int min = Mathf.FloorToInt((center - radius) / step);
|
||||
int max = Mathf.CeilToInt((center + radius) / step);
|
||||
return new Vector2Int(min, max);
|
||||
}
|
||||
|
||||
// 更新网格平面缓存
|
||||
private void UpdateGridPlaneCache()
|
||||
{
|
||||
gridPlaneCache = gridPlane switch
|
||||
{
|
||||
0 => new Plane(Vector3.up, transform.position), // XZ
|
||||
1 => new Plane(Vector3.forward, transform.position), // XY
|
||||
2 => new Plane(Vector3.right, transform.position), // YZ
|
||||
_ => new Plane(Vector3.up, transform.position)
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdateTextDisplay(HashSet<Vector3> requiredPositions)
|
||||
{
|
||||
// 第一步:移除不再需要的位置文本
|
||||
List<GameObject> toRemove = new List<GameObject>();
|
||||
foreach (var kvp in positionTexts)
|
||||
{
|
||||
if (!requiredPositions.Contains(kvp.Value))
|
||||
{
|
||||
toRemove.Add(kvp.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GameObject textObj in toRemove)
|
||||
{
|
||||
positionTexts.Remove(textObj);
|
||||
ReturnTextToPool(textObj);
|
||||
}
|
||||
|
||||
// 第二步:添加新位置文本
|
||||
foreach (Vector3 position in requiredPositions)
|
||||
{
|
||||
if (!ContainsPosition(position))
|
||||
{
|
||||
GameObject textObj = GetTextFromPool();
|
||||
SetupTextObject(textObj, position);
|
||||
positionTexts[textObj] = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ContainsPosition(Vector3 position)
|
||||
{
|
||||
foreach (var pos in positionTexts.Values)
|
||||
{
|
||||
if (Vector3.Distance(pos, position) < 0.1f)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetupTextObject(GameObject textObj, Vector3 position)
|
||||
{
|
||||
textObj.transform.position = position + new Vector3(gridScale / 6, 0, gridScale / 12);
|
||||
|
||||
float scaleFactor = gridScale * 1.5f;
|
||||
textObj.transform.localScale = new Vector3(scaleFactor, scaleFactor, scaleFactor);
|
||||
|
||||
// 设置文本内容
|
||||
TMP_Text tmpText = textObj.GetComponent<TMP_Text>();
|
||||
if (tmpText != null)
|
||||
{
|
||||
tmpText.text = $"({Mathf.RoundToInt(position.x)}, {Mathf.RoundToInt(position.z)})";
|
||||
}
|
||||
|
||||
// 初始朝向
|
||||
Vector3 direction = sceneCamera.transform.position - textObj.transform.position;
|
||||
textObj.transform.forward = -direction.normalized;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共方法
|
||||
|
||||
public void ShowPositionText()
|
||||
{
|
||||
canShowPositionText = true;
|
||||
isShowingPositionText = true;
|
||||
lastTextUpdateTime = 0; // 强制下一次更新
|
||||
}
|
||||
|
||||
public void HidePositionText()
|
||||
{
|
||||
canShowPositionText = false;
|
||||
ClearAllTexts();
|
||||
}
|
||||
|
||||
public void SetGridPlane(int planeIndex)
|
||||
{
|
||||
if (planeIndex >= 0 && planeIndex <= 2)
|
||||
{
|
||||
gridPlane = planeIndex;
|
||||
gridMaterial.SetFloat("_Plane", gridPlane);
|
||||
UpdateGridPlaneCache();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
// 清理资源
|
||||
if (gridMaterial != null)
|
||||
{
|
||||
if (Application.isEditor)
|
||||
DestroyImmediate(gridMaterial);
|
||||
else
|
||||
Destroy(gridMaterial);
|
||||
}
|
||||
|
||||
ClearAllTexts();
|
||||
|
||||
// 清理对象池
|
||||
foreach (var textObj in textPool)
|
||||
{
|
||||
if (textObj != null)
|
||||
{
|
||||
if (Application.isEditor)
|
||||
DestroyImmediate(textObj);
|
||||
else
|
||||
Destroy(textObj);
|
||||
}
|
||||
}
|
||||
textPool.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ namespace Ichni
|
||||
public BackgroundController backgroundController;
|
||||
public GridController gridController;
|
||||
public CameraManager cameraManager;
|
||||
public NoteManager noteManager;
|
||||
public Ichni.Editor.PostProcessingManager postProcessingManager;
|
||||
public Canvas judgeHintCanvas;
|
||||
public Canvas inspectorCanvas;
|
||||
@@ -59,7 +60,7 @@ namespace Ichni
|
||||
isLoaded = false;
|
||||
projectManager = new ProjectManager();
|
||||
operationManager = new OperationManager();
|
||||
|
||||
noteManager = new NoteManager();
|
||||
if (!ES3.FileExists(Application.streamingAssetsPath + "/EditorSettings.es3"))
|
||||
{
|
||||
editorSettings = new EditorSettings(300, 3, 100, 100, 60);
|
||||
@@ -120,6 +121,7 @@ namespace Ichni
|
||||
private void Update()
|
||||
{
|
||||
if (isLoaded) projectManager.autoSaveManager.UpdateAutoSave();
|
||||
noteManager.UpdateNote();
|
||||
}
|
||||
|
||||
public void LoadProject(string projectName)
|
||||
|
||||
@@ -14,10 +14,9 @@ namespace Ichni.Editor
|
||||
public partial class InputListener : MonoBehaviour
|
||||
{
|
||||
public static InputListener instance;
|
||||
private PointerEventData pointerEventData;
|
||||
private bool isPointerOverUI;
|
||||
public bool isPointerOverUI;
|
||||
public TMP_Text hoveredUIText;
|
||||
public GameObject hoveredUI;
|
||||
//public GameObject hoveredUI;
|
||||
public EventSystem eventSystem;
|
||||
public List<GraphicRaycaster> graphicRaycasters;
|
||||
private List<SelectionConnector> lastHitConnectors = new List<SelectionConnector>();
|
||||
@@ -47,7 +46,7 @@ namespace Ichni.Editor
|
||||
if (currentMousePosition != lastMousePosition || frameCount % uiCheckFrameInterval == 0)
|
||||
{
|
||||
lastMousePosition = currentMousePosition;
|
||||
isPointerOverUI = IsPointerOverUI(out hoveredUI);
|
||||
isPointerOverUI = IsPointerOverUI();
|
||||
}
|
||||
SceneCameraOperation();
|
||||
MusicPlayerOperation();
|
||||
@@ -308,68 +307,34 @@ namespace Ichni.Editor
|
||||
{
|
||||
private TMP_Text UIText => EditorManager.instance.UIText;
|
||||
|
||||
public bool IsPointerOverUI(out GameObject hoveredUI)
|
||||
{
|
||||
hoveredUI = null;
|
||||
// 类级别缓存
|
||||
private PointerEventData EventData;
|
||||
private List<RaycastResult> raycastResults = new List<RaycastResult>();
|
||||
|
||||
public bool IsPointerOverUI()
|
||||
{
|
||||
if (Mouse.current == null) return false;
|
||||
|
||||
pointerEventData = new PointerEventData(eventSystem)
|
||||
if (EventData == null)
|
||||
{
|
||||
position = Mouse.current.position.ReadValue()
|
||||
};
|
||||
EventData = new PointerEventData(eventSystem);
|
||||
}
|
||||
EventData.position = Mouse.current.position.ReadValue();
|
||||
|
||||
List<RaycastResult> allResults = new List<RaycastResult>();
|
||||
raycastResults.Clear(); // 复用列表
|
||||
EventSystem.current.RaycastAll(EventData, raycastResults);
|
||||
|
||||
// 使用EventSystem的RaycastAll来确保检测所有UI
|
||||
EventSystem.current.RaycastAll(pointerEventData, allResults);
|
||||
|
||||
// 或者手动检测所有GraphicRaycaster
|
||||
foreach (var raycaster in FindObjectsOfType<GraphicRaycaster>())
|
||||
for (int i = 0; i < raycastResults.Count; i++)
|
||||
{
|
||||
if (!raycaster.enabled || !raycaster.gameObject.activeInHierarchy)
|
||||
continue;
|
||||
|
||||
List<RaycastResult> results = new List<RaycastResult>();
|
||||
raycaster.Raycast(pointerEventData, results);
|
||||
allResults.AddRange(results);
|
||||
var result = raycastResults[i];
|
||||
if (result.gameObject != null &&
|
||||
result.gameObject.activeInHierarchy &&
|
||||
result.gameObject.GetComponent<RectTransform>() != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 移除无效结果
|
||||
allResults.RemoveAll(r =>
|
||||
r.gameObject == null ||
|
||||
!r.gameObject.activeInHierarchy ||
|
||||
!r.gameObject.GetComponent<RectTransform>());
|
||||
|
||||
if (allResults.Count > 0)
|
||||
{
|
||||
// 完整排序
|
||||
// allResults.Sort((a, b) =>
|
||||
// {
|
||||
// // 先按sorting layer
|
||||
// int layerCompare = SortingLayer.GetLayerValueFromID(b.sortingLayer)
|
||||
// .CompareTo(SortingLayer.GetLayerValueFromID(a.sortingLayer));
|
||||
// if (layerCompare != 0) return layerCompare;
|
||||
|
||||
// // 再按sorting order
|
||||
// int orderCompare = b.sortingOrder.CompareTo(a.sortingOrder);
|
||||
// if (orderCompare != 0) return orderCompare;
|
||||
|
||||
// // 最后按depth
|
||||
// return b.depth.CompareTo(a.depth);
|
||||
// });
|
||||
|
||||
// hoveredUI = allResults[0].gameObject;
|
||||
// string text = $"UI: {hoveredUI.name}, Layer: {SortingLayer.IDToName(allResults[0].sortingLayer)}, Order: {allResults[0].sortingOrder}";
|
||||
// if (UIText.text != text)
|
||||
// {
|
||||
// UIText.text = text;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//UIText.text = "No UI";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
162
Assets/Scripts/Manager/NoteManager.cs
Normal file
162
Assets/Scripts/Manager/NoteManager.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni
|
||||
{
|
||||
public class NoteManager
|
||||
{
|
||||
public static NoteManager instance;
|
||||
public NoteManager()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
private List<NoteBase> allNotes = new List<NoteBase>();
|
||||
public List<NoteBase> activeNotes = new List<NoteBase>();
|
||||
private List<NoteBase> notesToRemove = new List<NoteBase>();
|
||||
|
||||
public int currentActiveNoteCount => activeNotes.Count;
|
||||
private float lastKnownTime = -1f;
|
||||
|
||||
public void AddNote(NoteBase note)
|
||||
{
|
||||
allNotes.Add(note);
|
||||
// 只在添加时排序一次
|
||||
allNotes.Sort((a, b) => a.NoteAppearTime.CompareTo(b.NoteAppearTime));
|
||||
|
||||
note.UpdateNote(); // 初始化状态
|
||||
Observable.NextFrame().Subscribe(_ =>
|
||||
{
|
||||
note.noteVisual?.generateEffect?.PreExecute();
|
||||
note.noteVisual?.noteMain.SetActive(true);
|
||||
note.UpdateNote(); // 确保在下一帧也更新一次,防止遗漏
|
||||
});
|
||||
}
|
||||
|
||||
public void RemoveNote(NoteBase note)
|
||||
{
|
||||
activeNotes.Remove(note);
|
||||
allNotes.Remove(note);
|
||||
}
|
||||
|
||||
public void UpdateNote()
|
||||
{
|
||||
if (allNotes.Count == 0) return;
|
||||
|
||||
float currentTime = EditorManager.instance.songInformation.songTime;
|
||||
|
||||
// 检测时间方向
|
||||
bool isTimeMovingForward = currentTime >= lastKnownTime;
|
||||
lastKnownTime = currentTime;
|
||||
|
||||
// 清空待移除列表
|
||||
notesToRemove.Clear();
|
||||
// 处理时间前进的情况 - 添加新音符
|
||||
if (isTimeMovingForward)
|
||||
{
|
||||
// 查找所有应该激活但尚未激活的音符
|
||||
for (int i = 0; i < allNotes.Count; i++)
|
||||
{
|
||||
var note = allNotes[i];
|
||||
|
||||
// 如果音符应该出现但还没激活
|
||||
if (note.NoteAppearTime <= currentTime
|
||||
)
|
||||
{
|
||||
if (!activeNotes.Contains(note)) activeNotes.Add(note);
|
||||
}
|
||||
else if (note.exactJudgeTime < currentTime) break;
|
||||
}
|
||||
}
|
||||
// 处理时间倒退的情况 - 调整活跃列表
|
||||
else
|
||||
{
|
||||
// 移除在当前时间之后出现的音符
|
||||
for (int i = activeNotes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var note = activeNotes[i];
|
||||
if (note.NoteAppearTime > currentTime)
|
||||
{
|
||||
notesToRemove.Add(note);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < allNotes.Count; i++)
|
||||
{
|
||||
var note = allNotes[i];
|
||||
|
||||
// 如果音符应该出现但还没激活
|
||||
if (note.isFirstJudged && note.exactJudgeTime > currentTime
|
||||
)
|
||||
{
|
||||
if (!activeNotes.Contains(note)) activeNotes.Add(note);
|
||||
}
|
||||
// else if (note.NoteAppearTime < currentTime)
|
||||
// {
|
||||
// break; // 提前退出循环,优化性能
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 更新所有活跃音符
|
||||
for (int i = 0; i < activeNotes.Count; i++)
|
||||
{
|
||||
var note = activeNotes[i];
|
||||
note.UpdateNote();
|
||||
// Debug.Log($"Updating Note {note.elementName} at time {currentTime}");
|
||||
// 标记已判定的音符等待移除
|
||||
if (note.isFirstJudged)
|
||||
{
|
||||
notesToRemove.Add(note);
|
||||
}
|
||||
}
|
||||
|
||||
// 移除标记的音符
|
||||
for (int i = 0; i < notesToRemove.Count; i++)
|
||||
{
|
||||
activeNotes.Remove(notesToRemove[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 重置所有状态(用于歌曲重新开始等)
|
||||
public void ResetAll()
|
||||
{
|
||||
activeNotes.Clear();
|
||||
notesToRemove.Clear();
|
||||
lastKnownTime = -1f;
|
||||
|
||||
// 不重置音符状态,让音符自己的逻辑处理
|
||||
}
|
||||
|
||||
// 跳转到指定时间
|
||||
public void SeekToTime(float targetTime)
|
||||
{
|
||||
// 清空当前活跃列表
|
||||
activeNotes.Clear();
|
||||
notesToRemove.Clear();
|
||||
|
||||
// 添加在目标时间之前应该出现的音符
|
||||
for (int i = 0; i < allNotes.Count; i++)
|
||||
{
|
||||
var note = allNotes[i];
|
||||
|
||||
// 添加在目标时间之前应该出现的音符
|
||||
if (note.NoteAppearTime <= targetTime)
|
||||
{
|
||||
activeNotes.Add(note);
|
||||
}
|
||||
}
|
||||
|
||||
lastKnownTime = targetTime;
|
||||
}
|
||||
|
||||
// 获取所有音符(只读)
|
||||
public IReadOnlyList<NoteBase> GetAllNotes()
|
||||
{
|
||||
return allNotes.AsReadOnly();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Manager/NoteManager.cs.meta
Normal file
11
Assets/Scripts/Manager/NoteManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fe401fc051728b49a4e682f518ffc54
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -64,7 +64,7 @@ Material:
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _Tex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Texture: {fileID: 8900000, guid: 7ba462c2dc80b544eacfdc537aab22c6, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _Tex2:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
169
Assets/StreamingAssets/NotePrefabs/Flick_Prefab.json
Normal file
169
Assets/StreamingAssets/NotePrefabs/Flick_Prefab.json
Normal file
@@ -0,0 +1,169 @@
|
||||
{
|
||||
"Note" : {
|
||||
"__type" : "System.Collections.Generic.List`1[[Ichni.RhythmGame.Beatmap.BaseElement_BM, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]],mscorlib",
|
||||
"value" : [
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.Flick_BM,Assembly-CSharp",
|
||||
"availableFlickDirections" : [
|
||||
|
||||
],
|
||||
"exactJudgeTime" : 38.1000023,
|
||||
"elementName" : "Flick (38.1)",
|
||||
"tags" : [
|
||||
|
||||
],
|
||||
"elementGuid" : {
|
||||
"value" : "da7a57fa-88a1-454c-8f2b-76d8b20da266"
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "0ae5b3f7-75f7-49c8-8841-7e4dbbb20d35"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
|
||||
"isOverridingDuration" : false,
|
||||
"startTime" : -32767,
|
||||
"endTime" : 32767,
|
||||
"attachedElementGuid" : {
|
||||
"value" : "da7a57fa-88a1-454c-8f2b-76d8b20da266"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.NoteJudgeSubmodule_BM,Assembly-CSharp",
|
||||
"judgeUnitList" : [
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TouchAreaJudgeUnit_BM,Assembly-CSharp",
|
||||
"areaRadius" : 600
|
||||
}
|
||||
],
|
||||
"attachedElementGuid" : {
|
||||
"value" : "da7a57fa-88a1-454c-8f2b-76d8b20da266"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.NoteAudioSubmodule_BM,Assembly-CSharp",
|
||||
"generalJudgeAudioList" : [
|
||||
"DefaultFlick"
|
||||
],
|
||||
"perfectAudioList" : [
|
||||
|
||||
],
|
||||
"goodAudioList" : [
|
||||
|
||||
],
|
||||
"badAudioList" : [
|
||||
|
||||
],
|
||||
"missAudioList" : [
|
||||
|
||||
],
|
||||
"holdStartAudioList" : [
|
||||
|
||||
],
|
||||
"attachedElementGuid" : {
|
||||
"value" : "da7a57fa-88a1-454c-8f2b-76d8b20da266"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteVisual_BM,Assembly-CSharp",
|
||||
"isHighlighted" : true,
|
||||
"themeBundleName" : "departure_to_multiverse",
|
||||
"objectName" : "DTM_NoteVisualFlick",
|
||||
"elementName" : "New Note Visual",
|
||||
"tags" : [
|
||||
|
||||
],
|
||||
"elementGuid" : {
|
||||
"value" : "4507c7f6-cd26-45c3-94ea-fe36d5b05251"
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "da7a57fa-88a1-454c-8f2b-76d8b20da266"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
|
||||
"originalPosition" : {
|
||||
"x" : -6.024219,
|
||||
"y" : 0,
|
||||
"z" : 0
|
||||
},
|
||||
"originalEulerAngles" : {
|
||||
"x" : 0,
|
||||
"y" : 0,
|
||||
"z" : 0
|
||||
},
|
||||
"originalScale" : {
|
||||
"x" : 1.5,
|
||||
"y" : 1.5,
|
||||
"z" : 1.5
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "4507c7f6-cd26-45c3-94ea-fe36d5b05251"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
|
||||
"isOverridingDuration" : false,
|
||||
"startTime" : -32767,
|
||||
"endTime" : 32767,
|
||||
"attachedElementGuid" : {
|
||||
"value" : "4507c7f6-cd26-45c3-94ea-fe36d5b05251"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
|
||||
"originalBaseColor" : {
|
||||
"r" : 1,
|
||||
"g" : 1,
|
||||
"b" : 1,
|
||||
"a" : 1
|
||||
},
|
||||
"emissionEnabled" : false,
|
||||
"originalEmissionColor" : {
|
||||
"r" : 0,
|
||||
"g" : 0,
|
||||
"b" : 0,
|
||||
"a" : 1
|
||||
},
|
||||
"originalEmissionIntensity" : 0,
|
||||
"attachedElementGuid" : {
|
||||
"value" : "4507c7f6-cd26-45c3-94ea-fe36d5b05251"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.EffectSubmodule_BM,Assembly-CSharp",
|
||||
"effectCollection" : {"Generate":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteGenerateExpand_BM,Assembly-CSharp",
|
||||
"generateTime" : 1,
|
||||
"effectTime" : 0.2
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.CameraShakeEffect_BM,Assembly-CSharp",
|
||||
"duration" : 0.2,
|
||||
"frequency" : 200,
|
||||
"amplitudeX" : 1,
|
||||
"amplitudeY" : 1,
|
||||
"amplitudeZ" : 1,
|
||||
"effectTime" : 0
|
||||
}
|
||||
],"GeneralJudge":[
|
||||
|
||||
],"Holding":[
|
||||
|
||||
],"Perfect":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNotePerfectBurst_BM,Assembly-CSharp",
|
||||
"effectTime" : 0
|
||||
}
|
||||
],"Good":[
|
||||
|
||||
],"Bad":[
|
||||
|
||||
],"Miss":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteMissTransparent_BM,Assembly-CSharp",
|
||||
"effectTime" : 0.2
|
||||
}
|
||||
],"AfterJudge":[
|
||||
|
||||
]
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "4507c7f6-cd26-45c3-94ea-fe36d5b05251"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67be16676571f35478a55da8ebcccbb6
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
173
Assets/StreamingAssets/NotePrefabs/Hold_Prefab.json
Normal file
173
Assets/StreamingAssets/NotePrefabs/Hold_Prefab.json
Normal file
@@ -0,0 +1,173 @@
|
||||
{
|
||||
"Note" : {
|
||||
"__type" : "System.Collections.Generic.List`1[[Ichni.RhythmGame.Beatmap.BaseElement_BM, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]],mscorlib",
|
||||
"value" : [
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.Hold_BM,Assembly-CSharp",
|
||||
"holdEndTime" : 38.1,
|
||||
"exactJudgeTime" : 37.8,
|
||||
"elementName" : "Hold (37.8-38.1)",
|
||||
"tags" : [
|
||||
|
||||
],
|
||||
"elementGuid" : {
|
||||
"value" : "fa71b9d8-5450-4602-9d01-6ec8cdd9ed7f"
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "0ae5b3f7-75f7-49c8-8841-7e4dbbb20d35"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
|
||||
"isOverridingDuration" : false,
|
||||
"startTime" : -32767,
|
||||
"endTime" : 32767,
|
||||
"attachedElementGuid" : {
|
||||
"value" : "fa71b9d8-5450-4602-9d01-6ec8cdd9ed7f"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.NoteJudgeSubmodule_BM,Assembly-CSharp",
|
||||
"judgeUnitList" : [
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TouchAreaJudgeUnit_BM,Assembly-CSharp",
|
||||
"areaRadius" : 600
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TouchAreaJudgeUnit_BM,Assembly-CSharp",
|
||||
"areaRadius" : 600
|
||||
}
|
||||
],
|
||||
"attachedElementGuid" : {
|
||||
"value" : "fa71b9d8-5450-4602-9d01-6ec8cdd9ed7f"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.NoteAudioSubmodule_BM,Assembly-CSharp",
|
||||
"generalJudgeAudioList" : [
|
||||
"DefaultEndHold"
|
||||
],
|
||||
"perfectAudioList" : [
|
||||
|
||||
],
|
||||
"goodAudioList" : [
|
||||
|
||||
],
|
||||
"badAudioList" : [
|
||||
|
||||
],
|
||||
"missAudioList" : [
|
||||
|
||||
],
|
||||
"holdStartAudioList" : [
|
||||
"DefaultStartHold"
|
||||
],
|
||||
"attachedElementGuid" : {
|
||||
"value" : "fa71b9d8-5450-4602-9d01-6ec8cdd9ed7f"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteVisualHold_BM,Assembly-CSharp",
|
||||
"isHighlighted" : false,
|
||||
"themeBundleName" : "departure_to_multiverse",
|
||||
"objectName" : "DTM_NoteVisualHold",
|
||||
"elementName" : "New Note Visual",
|
||||
"tags" : [
|
||||
|
||||
],
|
||||
"elementGuid" : {
|
||||
"value" : "d487a8d6-c440-490d-a82a-edb1d537205e"
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "fa71b9d8-5450-4602-9d01-6ec8cdd9ed7f"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
|
||||
"originalPosition" : {
|
||||
"x" : -6,
|
||||
"y" : 0,
|
||||
"z" : 0
|
||||
},
|
||||
"originalEulerAngles" : {
|
||||
"x" : 0,
|
||||
"y" : 0,
|
||||
"z" : 0
|
||||
},
|
||||
"originalScale" : {
|
||||
"x" : 1,
|
||||
"y" : 1,
|
||||
"z" : 1
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "d487a8d6-c440-490d-a82a-edb1d537205e"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
|
||||
"isOverridingDuration" : false,
|
||||
"startTime" : -32767,
|
||||
"endTime" : 32767,
|
||||
"attachedElementGuid" : {
|
||||
"value" : "d487a8d6-c440-490d-a82a-edb1d537205e"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
|
||||
"originalBaseColor" : {
|
||||
"r" : 1,
|
||||
"g" : 1,
|
||||
"b" : 1,
|
||||
"a" : 1
|
||||
},
|
||||
"emissionEnabled" : false,
|
||||
"originalEmissionColor" : {
|
||||
"r" : 0,
|
||||
"g" : 0,
|
||||
"b" : 0,
|
||||
"a" : 1
|
||||
},
|
||||
"originalEmissionIntensity" : 0,
|
||||
"attachedElementGuid" : {
|
||||
"value" : "d487a8d6-c440-490d-a82a-edb1d537205e"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.EffectSubmodule_BM,Assembly-CSharp",
|
||||
"effectCollection" : {"Generate":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteGenerateExtend_BM,Assembly-CSharp",
|
||||
"generateTime" : 1,
|
||||
"effectTime" : 0.5
|
||||
}
|
||||
],"GeneralJudge":[
|
||||
|
||||
],"StartHold":[
|
||||
|
||||
],"Holding":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteHoldingBreath_BM,Assembly-CSharp",
|
||||
"effectTime" : 0.299999237
|
||||
}
|
||||
],"Perfect":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNotePerfectBurst_BM,Assembly-CSharp",
|
||||
"effectTime" : 0
|
||||
}
|
||||
],"Good":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteGoodBurst_BM,Assembly-CSharp",
|
||||
"effectTime" : 0
|
||||
}
|
||||
],"Bad":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteBadBurst_BM,Assembly-CSharp",
|
||||
"effectTime" : 0
|
||||
}
|
||||
],"Miss":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteMissTransparent_BM,Assembly-CSharp",
|
||||
"effectTime" : 0.2
|
||||
}
|
||||
],"AfterJudge":[
|
||||
|
||||
]
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "d487a8d6-c440-490d-a82a-edb1d537205e"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
7
Assets/StreamingAssets/NotePrefabs/Hold_Prefab.json.meta
Normal file
7
Assets/StreamingAssets/NotePrefabs/Hold_Prefab.json.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95cb000d04bdebf409a018593ab4e5c4
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
166
Assets/StreamingAssets/NotePrefabs/Tap_Prefab.json
Normal file
166
Assets/StreamingAssets/NotePrefabs/Tap_Prefab.json
Normal file
@@ -0,0 +1,166 @@
|
||||
{
|
||||
"Note" : {
|
||||
"__type" : "System.Collections.Generic.List`1[[Ichni.RhythmGame.Beatmap.BaseElement_BM, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]],mscorlib",
|
||||
"value" : [
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.Tap_BM,Assembly-CSharp",
|
||||
"exactJudgeTime" : 17.7,
|
||||
"elementName" : "Tap (17.7)",
|
||||
"tags" : [
|
||||
|
||||
],
|
||||
"elementGuid" : {
|
||||
"value" : "5b0597ba-88d3-4912-8cd4-d33a51d92c98"
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
|
||||
"isOverridingDuration" : false,
|
||||
"startTime" : -32767,
|
||||
"endTime" : 32767,
|
||||
"attachedElementGuid" : {
|
||||
"value" : "5b0597ba-88d3-4912-8cd4-d33a51d92c98"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.NoteAudioSubmodule_BM,Assembly-CSharp",
|
||||
"generalJudgeAudioList" : [
|
||||
"DefaultTap"
|
||||
],
|
||||
"perfectAudioList" : [
|
||||
|
||||
],
|
||||
"goodAudioList" : [
|
||||
|
||||
],
|
||||
"badAudioList" : [
|
||||
|
||||
],
|
||||
"missAudioList" : [
|
||||
|
||||
],
|
||||
"holdStartAudioList" : [
|
||||
|
||||
],
|
||||
"attachedElementGuid" : {
|
||||
"value" : "5b0597ba-88d3-4912-8cd4-d33a51d92c98"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.NoteJudgeSubmodule_BM,Assembly-CSharp",
|
||||
"judgeUnitList" : [
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TouchAreaJudgeUnit_BM,Assembly-CSharp",
|
||||
"areaRadius" : 600
|
||||
}
|
||||
],
|
||||
"attachedElementGuid" : {
|
||||
"value" : "5b0597ba-88d3-4912-8cd4-d33a51d92c98"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteVisual_BM,Assembly-CSharp",
|
||||
"isHighlighted" : false,
|
||||
"themeBundleName" : "departure_to_multiverse",
|
||||
"objectName" : "DTM_NoteVisualTap",
|
||||
"elementName" : "New Note Visual",
|
||||
"tags" : [
|
||||
|
||||
],
|
||||
"elementGuid" : {
|
||||
"value" : "85451a3e-9d99-4706-bcd5-c3e18e182916"
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "5b0597ba-88d3-4912-8cd4-d33a51d92c98"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
|
||||
"originalPosition" : {
|
||||
"x" : 0,
|
||||
"y" : 0,
|
||||
"z" : 0
|
||||
},
|
||||
"originalEulerAngles" : {
|
||||
"x" : 0,
|
||||
"y" : 0,
|
||||
"z" : 0
|
||||
},
|
||||
"originalScale" : {
|
||||
"x" : 1.2,
|
||||
"y" : 1.2,
|
||||
"z" : 1.2
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "85451a3e-9d99-4706-bcd5-c3e18e182916"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
|
||||
"isOverridingDuration" : false,
|
||||
"startTime" : -32767,
|
||||
"endTime" : 32767,
|
||||
"attachedElementGuid" : {
|
||||
"value" : "85451a3e-9d99-4706-bcd5-c3e18e182916"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
|
||||
"originalBaseColor" : {
|
||||
"r" : 1,
|
||||
"g" : 1,
|
||||
"b" : 1,
|
||||
"a" : 1
|
||||
},
|
||||
"emissionEnabled" : false,
|
||||
"originalEmissionColor" : {
|
||||
"r" : 0,
|
||||
"g" : 0,
|
||||
"b" : 0,
|
||||
"a" : 1
|
||||
},
|
||||
"originalEmissionIntensity" : 0,
|
||||
"attachedElementGuid" : {
|
||||
"value" : "85451a3e-9d99-4706-bcd5-c3e18e182916"
|
||||
}
|
||||
},{
|
||||
"__type" : "Ichni.RhythmGame.Beatmap.EffectSubmodule_BM,Assembly-CSharp",
|
||||
"effectCollection" : {"Generate":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteGenerateExpand_BM,Assembly-CSharp",
|
||||
"generateTime" : 3,
|
||||
"effectTime" : 0.5
|
||||
}
|
||||
],"GeneralJudge":[
|
||||
|
||||
],"StartHold":[
|
||||
|
||||
],"Holding":[
|
||||
|
||||
],"Perfect":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNotePerfectBurst_BM,Assembly-CSharp",
|
||||
"effectTime" : 0
|
||||
}
|
||||
],"Good":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteGoodBurst_BM,Assembly-CSharp",
|
||||
"effectTime" : 0
|
||||
}
|
||||
],"Bad":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteBadBurst_BM,Assembly-CSharp",
|
||||
"effectTime" : 0
|
||||
}
|
||||
],"Miss":[
|
||||
{
|
||||
"__type" : "Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap.DTMNoteMissTransparent_BM,Assembly-CSharp",
|
||||
"effectTime" : 0.2
|
||||
}
|
||||
],"AfterJudge":[
|
||||
|
||||
]
|
||||
},
|
||||
"attachedElementGuid" : {
|
||||
"value" : "85451a3e-9d99-4706-bcd5-c3e18e182916"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
7
Assets/StreamingAssets/NotePrefabs/Tap_Prefab.json.meta
Normal file
7
Assets/StreamingAssets/NotePrefabs/Tap_Prefab.json.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 883ef17754a31e741b58fa60ce21b740
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -12,6 +12,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
this.noteVisual = noteVisual;
|
||||
this.generateTime = generateTime;
|
||||
this.effectTime = effectTime;
|
||||
this.nowEffectState = CheckEffectState(EditorManager.instance.songInformation.songTime);
|
||||
}
|
||||
|
||||
public sealed override void Recover()
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
private DTMNoteVisualHold noteVisualHold;
|
||||
public float targetStartPercent, targetEndPercent;
|
||||
public float startPercent, endPercent;
|
||||
|
||||
|
||||
public DTMNoteGenerateExtend(NoteVisualBase noteVisual, float generateTime, float effectTime)
|
||||
{
|
||||
this.note = noteVisual.note;
|
||||
@@ -22,6 +22,8 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
this.noteVisualHold = noteVisual as DTMNoteVisualHold;
|
||||
this.generateTime = generateTime;
|
||||
this.effectTime = effectTime;
|
||||
this.nowEffectState = CheckEffectState(EditorManager.instance.songInformation.songTime);
|
||||
|
||||
}
|
||||
|
||||
private void UpdateHold()
|
||||
@@ -31,7 +33,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
noteVisualHold.headPoint.SetPercent(startPercent);
|
||||
noteVisualHold.tailPoint.SetPercent(endPercent);
|
||||
}
|
||||
|
||||
|
||||
public override void Recover()
|
||||
{
|
||||
noteVisualHold.noteMain.SetActive(false);
|
||||
@@ -51,7 +53,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
endPercent = targetStartPercent;
|
||||
noteVisual.noteMain.SetActive(true);
|
||||
}
|
||||
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
float e = AnimationCurveEvaluator.Evaluate(AnimationCurveType.OutQuad, effectProgressPercent);
|
||||
@@ -66,7 +68,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
endPercent = targetEndPercent;
|
||||
UpdateHold();
|
||||
}
|
||||
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
{
|
||||
public List<List<Material>> normalMaterialList;
|
||||
public List<List<Material>> highlightMaterialList;
|
||||
|
||||
|
||||
public new static DTMNoteVisual GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated, string themeBundleName, string objectName, GameElement parentElement, bool isHighlighted)
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
rend.material.SetFloat("_MainAlpha", 1f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (EffectBase effect in effectSubmodule.effectCollection["Generate"])
|
||||
{
|
||||
effect.Recover();
|
||||
@@ -78,14 +78,14 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
|
||||
public override void SetHighlight()
|
||||
{
|
||||
//List<Renderer> partRendererList = notePartList.Select(part => part.GetComponent<Renderer>()).ToList();
|
||||
|
||||
|
||||
//partRendererList.ForEach(rend => Destroy(rend.material));
|
||||
|
||||
|
||||
if (note is Tap or Hold)
|
||||
{
|
||||
extraPartList[0].gameObject.SetActive(isHighlighted);
|
||||
}
|
||||
|
||||
|
||||
/*if (!isHighlighted)
|
||||
{
|
||||
for (int i = 0; i < partRendererList.Count; i++)
|
||||
|
||||
Reference in New Issue
Block a user