This commit is contained in:
SoulliesOfficial
2026-04-03 10:53:11 -04:00
parent e7b890686d
commit 1bc9af280b
177 changed files with 4029 additions and 3302 deletions

View File

@@ -30,9 +30,9 @@ namespace Ichni.RhythmGame
// 【新增】受管家管控
GameManager.Instance.animationManager.RegisterAnimation(this);
float delay = GameManager.Instance.songInformation.delay;
if (timeDurationSubmodule.CheckTimeInDuration(delay))
if (timeDurationSubmodule.CheckTimeInDuration(-delay))
{
UpdateAnimation(0f); // 确保与最新的 SongTime 同步
ManualUpdate(-delay, true);
}
}
@@ -40,13 +40,13 @@ namespace Ichni.RhythmGame
/// 更新动画
/// </summary>
/// <param name="songTime">歌曲时间</param>
protected abstract void UpdateAnimation(float songTime);
protected abstract void UpdateAnimation(float songTime, bool forceUpdate);
public virtual void ManualUpdate(float currentSongTime)
public virtual void ManualUpdate(float currentSongTime, bool forceUpdate = false)
{
if (timeDurationSubmodule.CheckTimeInDuration(currentSongTime))
{
UpdateAnimation(currentSongTime);
UpdateAnimation(currentSongTime, forceUpdate);
}
if (timeDurationSubmodule.CheckAfterEndTime(currentSongTime))

View File

@@ -37,11 +37,11 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
fieldOfView.UpdateFlexibleFloat(songTime);
if (fieldOfView.returnType == FlexibleReturnType.MiddleExecuting)
if (forceUpdate || fieldOfView.returnType == FlexibleReturnType.MiddleExecuting)
{
targetGameCamera.perspectiveAngle = fieldOfView.value;
targetGameCamera.cam.fieldOfView = fieldOfView.value;

View File

@@ -45,19 +45,19 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
colorR.UpdateFlexibleFloat(songTime);
colorG.UpdateFlexibleFloat(songTime);
colorB.UpdateFlexibleFloat(songTime);
colorA.UpdateFlexibleFloat(songTime);
if ((colorR.returnType is FlexibleReturnType.MiddleExecuting || colorR.isSwitchingReturnType) ||
if (forceUpdate || (colorR.returnType is FlexibleReturnType.MiddleExecuting || colorR.isSwitchingReturnType) ||
(colorG.returnType is FlexibleReturnType.MiddleExecuting || colorG.isSwitchingReturnType) ||
(colorB.returnType is FlexibleReturnType.MiddleExecuting || colorB.isSwitchingReturnType) ||
(colorA.returnType is FlexibleReturnType.MiddleExecuting || colorA.isSwitchingReturnType))
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
if(!forceUpdate) animationReturnType = FlexibleReturnType.MiddleExecuting;
targetColorSubmodule.currentBaseColor = new Color(colorR.value, colorG.value, colorB.value, colorA.value);
targetColorSubmodule.baseColorDirtyMark = true;

View File

@@ -44,7 +44,7 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
colorR.UpdateFlexibleFloat(songTime);
colorG.UpdateFlexibleFloat(songTime);
@@ -56,7 +56,7 @@ namespace Ichni.RhythmGame
(colorB.returnType is FlexibleReturnType.MiddleExecuting || colorB.isSwitchingReturnType) ||
(colorI.returnType is FlexibleReturnType.MiddleExecuting || colorI.isSwitchingReturnType))
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
if(!forceUpdate) animationReturnType = FlexibleReturnType.MiddleExecuting;
targetColorSubmodule.currentEmissionColor = new Color(colorR.value, colorG.value, colorB.value, 1);
targetColorSubmodule.currentEmissionIntensity = colorI.value;

View File

@@ -103,7 +103,7 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
if (targetComponent == null) return;

View File

@@ -102,7 +102,7 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
if (targetComponent == null || propertyValue == null || propertyValue.animations.Count == 0) return;

View File

@@ -102,7 +102,7 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
if (targetComponent == null) return;

View File

@@ -44,19 +44,19 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
colorR.UpdateFlexibleFloat(songTime);
colorG.UpdateFlexibleFloat(songTime);
colorB.UpdateFlexibleFloat(songTime);
colorA.UpdateFlexibleFloat(songTime);
if ((colorR.returnType is FlexibleReturnType.MiddleExecuting || colorR.isSwitchingReturnType) ||
if (forceUpdate || (colorR.returnType is FlexibleReturnType.MiddleExecuting || colorR.isSwitchingReturnType) ||
(colorG.returnType is FlexibleReturnType.MiddleExecuting || colorG.isSwitchingReturnType) ||
(colorB.returnType is FlexibleReturnType.MiddleExecuting || colorB.isSwitchingReturnType) ||
(colorA.returnType is FlexibleReturnType.MiddleExecuting || colorA.isSwitchingReturnType))
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
if(!forceUpdate) animationReturnType = FlexibleReturnType.MiddleExecuting;
Color color = new Color(colorR.value, colorG.value, colorB.value, colorA.value);
((Track)animatedObject).trackRendererSubmodule.meshGenerator.color = color;
}
@@ -83,7 +83,7 @@ namespace Ichni.RhythmGame
}
else
{
UpdateAnimation(CoreServices.TimeProvider.SongTime);
UpdateAnimation(CoreServices.TimeProvider.SongTime, false);
}
}
#endregion

View File

@@ -37,7 +37,7 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
totalTime.UpdateFlexibleFloat(songTime);

View File

@@ -39,17 +39,17 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
positionX.UpdateFlexibleFloat(songTime);
positionY.UpdateFlexibleFloat(songTime);
positionZ.UpdateFlexibleFloat(songTime);
if (positionX.returnType is FlexibleReturnType.MiddleExecuting ||
if (forceUpdate || positionX.returnType is FlexibleReturnType.MiddleExecuting ||
positionY.returnType is FlexibleReturnType.MiddleExecuting ||
positionZ.returnType is FlexibleReturnType.MiddleExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
if(!forceUpdate) animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentPosition = new Vector3(positionX.value, positionY.value, positionZ.value);
targetTransformSubmodule.positionOffset += currentPosition;
targetTransformSubmodule.positionDirtyMark = true;

View File

@@ -33,9 +33,7 @@ namespace Ichni.RhythmGame
look.targetGameElement = lookAtTarget;
look.targetTransformSubmodule = (animatedObject as IHaveTransformSubmodule).transformSubmodule;
//look.timeDurationSubmodule.SetDuration(-999f, 999f); //TODO: 换为(-delay, songLength)
return look;
}
@@ -43,6 +41,12 @@ namespace Ichni.RhythmGame
{
timeDurationSubmodule = new TimeDurationSubmodule(this);
}
public override void AfterInitialize()
{
base.AfterInitialize();
}
#endregion
#region [] Core Animation Logic
@@ -54,7 +58,7 @@ namespace Ichni.RhythmGame
}
}
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
if (targetGameElement is null) return;
@@ -64,7 +68,7 @@ namespace Ichni.RhythmGame
{
targetTransformSubmodule.eulerAnglesOffsetLock = enabling.value;
}
if (enabling.value)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;

View File

@@ -42,17 +42,18 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
scaleX.UpdateFlexibleFloat(songTime);
scaleY.UpdateFlexibleFloat(songTime);
scaleZ.UpdateFlexibleFloat(songTime);
if (scaleX.returnType is FlexibleReturnType.MiddleExecuting ||
if (forceUpdate || scaleX.returnType is FlexibleReturnType.MiddleExecuting ||
scaleY.returnType is FlexibleReturnType.MiddleExecuting ||
scaleZ.returnType is FlexibleReturnType.MiddleExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
if(!forceUpdate) animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentScale = new Vector3(scaleX.value, scaleY.value, scaleZ.value);
targetTransformSubmodule.scaleOffset += currentScale;
targetTransformSubmodule.scaleDirtyMark = true;

View File

@@ -37,17 +37,17 @@ namespace Ichni.RhythmGame
#endregion
#region [] Core Animation Logic
protected override void UpdateAnimation(float songTime)
protected override void UpdateAnimation(float songTime, bool forceUpdate)
{
eulerAngleX.UpdateFlexibleFloat(songTime);
eulerAngleY.UpdateFlexibleFloat(songTime);
eulerAngleZ.UpdateFlexibleFloat(songTime);
if (eulerAngleX.returnType is FlexibleReturnType.MiddleExecuting ||
if (forceUpdate || eulerAngleX.returnType is FlexibleReturnType.MiddleExecuting ||
eulerAngleY.returnType is FlexibleReturnType.MiddleExecuting ||
eulerAngleZ.returnType is FlexibleReturnType.MiddleExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
if(!forceUpdate) animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentEulerAngles = new Vector3(eulerAngleX.value, eulerAngleY.value, eulerAngleZ.value);
targetTransformSubmodule.eulerAnglesOffset += currentEulerAngles;
targetTransformSubmodule.eulerAnglesDirtyMark = true;

View File

@@ -28,7 +28,7 @@ namespace Ichni.RhythmGame
if (HaveSameSubmodule)
{
Debug.LogAssertion($"物体 '{attachedGameElement.name}' 已经有一个类型为 '{this.GetType().Name}' 的 Submodule 了,新的 Submodule 将不会被添加。");
//Debug.LogAssertion($"物体 '{attachedGameElement.name}' 已经有一个类型为 '{this.GetType().Name}' 的 Submodule 了,新的 Submodule 将不会被添加。");
return;
}

View File

@@ -60,8 +60,7 @@ namespace Ichni.RhythmGame
skyboxThemeBundleName = themeBundleName;
skyboxMaterialName = materialName;
skyboxMaterial = ThemeBundleManager.instance.GetObject<Material>(themeBundleName, materialName);
if (skyboxMaterial == null) skyboxMaterial = GameManager.Instance.basePrefabs.defaultSkyboxMaterial;
GameManager.Instance.backgroundController.SetSkybox(skyboxMaterial);
if (skyboxMaterial != null) GameManager.Instance.backgroundController.SetSkybox(skyboxMaterial);
}
private void SetBackgroundSprite(string spriteName)

View File

@@ -114,12 +114,12 @@ namespace Ichni.RhythmGame
particleSystemRenderer.material.SetColor("_BaseColor", colorSubmodule.currentBaseColor);
if (colorSubmodule.emissionEnabled)
{
particleSystemRenderer.material.EnableKeyword("_EMISSION_ON");
particleSystemRenderer.material.SetFloat("_EnableEmission", 1);
particleSystemRenderer.material.SetColor("_EmissionColor", colorSubmodule.GetCurrentEmissionColor());
}
else
{
particleSystemRenderer.material.DisableKeyword("_EMISSION_ON");
particleSystemRenderer.material.SetFloat("_EnableEmission", 0);
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Dreamteck.Splines;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
@@ -45,6 +46,20 @@ namespace Ichni.RhythmGame
return pathNode;
}
public override void AfterInitialize()
{
base.AfterInitialize();
if (childElementList.Any(c => c is AnimationBase))
{
if(track.trackRendererSubmodule != null) track.trackRendererSubmodule.meshGenerator.autoUpdate = true;
}
else
{
//LeanPool.Despawn(gameObject);
}
}
public override void SetDefaultSubmodules()
{
transformSubmodule = new TransformSubmodule(this);

View File

@@ -60,6 +60,12 @@ namespace Ichni.RhythmGame
public void ClosePath()
{
if (pathNodeList.Count == 2)
{
path.type = Spline.Type.Linear;
path.sampleRate = 1;
}
if (isClosed)
{
path.Close();
@@ -95,7 +101,7 @@ namespace Ichni.RhythmGame
SetPathNode(pathNode);
}
ClosePath();
path.RebuildImmediate(true, true);
path.RebuildImmediate();
}
}
#endregion

View File

@@ -37,20 +37,6 @@ namespace Ichni.RhythmGame
{
this.track.trackRendererSubmodule = this;
}
// 【盲区修复】: 在启用所需的轨道生成器前,强行将对象池残留里的其他轨道生成器打入休眠状态,以防止管网和曲线同屏出现重叠!
DisableAllGenerators();
}
private void DisableAllGenerators()
{
if (track.trackRenderer == null) return;
if (track.trackRenderer.TryGetComponent(out SplineRenderer sr)) sr.enabled = false;
if (track.trackRenderer.TryGetComponent(out PathGenerator pg)) pg.enabled = false;
if (track.trackRenderer.TryGetComponent(out TubeGenerator tg)) tg.enabled = false;
if (track.trackRenderer.TryGetComponent(out SurfaceGenerator sg)) sg.enabled = false;
if (track.trackRenderer.TryGetComponent(out MeshRenderer mr)) mr.enabled = false;
}
#endregion
@@ -79,8 +65,6 @@ namespace Ichni.RhythmGame
protected void SetMesh()
{
this.meshGenerator.enabled = true;
if (track.trackTimeSubmodule is TrackTimeSubmoduleMovable trackTimeSubmoduleMovable)
{
meshGenerator.clipFrom = trackTimeSubmoduleMovable.tailPercent;
@@ -91,10 +75,6 @@ namespace Ichni.RhythmGame
meshGenerator.clipFrom = 0;
meshGenerator.clipTo = 1;
}
this.meshRenderer.enabled = true;
// 短暂激活生成网格后,为了性能再度关闭自身的实时刷新。
this.meshGenerator.enabled = false;
}
protected void SetEnableEmission() => meshRenderer.material.SetInt("_Emission", enableEmission ? 1 : 0);

View File

@@ -1,6 +1,7 @@
using System;
using Dreamteck.Splines;
using Ichni.RhythmGame.Beatmap;
using UniRx;
using UnityEngine;
namespace Ichni.RhythmGame
@@ -16,16 +17,16 @@ namespace Ichni.RhythmGame
bool zWrite, Vector2 uvScale, Vector2 uvOffset, Material material = null) :
base(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset)
{
this.splineRenderer = track.trackRenderer.GetComponent<SplineRenderer>();
this.splineRenderer = track.trackRenderer.AddComponent<SplineRenderer>();
this.meshRenderer = splineRenderer.GetComponent<MeshRenderer>();
this.meshGenerator = splineRenderer;
// 真正安全地仅激活该模块需要用到的引擎
this.splineRenderer.enabled = true;
this.meshGenerator.enabled = true;
this.renderMaterial = material == null ? GameManager.Instance.basePrefabs.defaultTrackMaterial : material;
this.splineRenderer.spline = track.trackPathSubmodule.path;
this.splineRenderer.doubleSided = true;
this.splineRenderer.clipFrom = 0;
this.splineRenderer.clipTo = 1;
this.splineRenderer.updateMethod = SplineUser.UpdateMethod.Update;

View File

@@ -1,6 +1,7 @@
using System;
using Dreamteck.Splines;
using Ichni.RhythmGame.Beatmap;
using UniRx;
using UnityEngine;
namespace Ichni.RhythmGame
@@ -16,15 +17,15 @@ namespace Ichni.RhythmGame
bool zWrite, Vector2 uvScale, Vector2 uvOffset, Material material = null) :
base(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset)
{
this.pathGenerator = track.trackRenderer.GetComponent<PathGenerator>();
this.pathGenerator = track.trackRenderer.AddComponent<PathGenerator>();
this.meshRenderer = pathGenerator.GetComponent<MeshRenderer>();
this.meshGenerator = pathGenerator;
this.pathGenerator.enabled = true;
this.meshGenerator.enabled = true;
this.renderMaterial = material == null ? GameManager.Instance.basePrefabs.defaultTrackMaterial : material;
this.pathGenerator.spline = track.trackPathSubmodule.path;
this.pathGenerator.doubleSided = true;
this.pathGenerator.clipFrom = 0;
this.pathGenerator.clipTo = 1;
this.pathGenerator.updateMethod = SplineUser.UpdateMethod.Update;

View File

@@ -16,15 +16,15 @@ namespace Ichni.RhythmGame
bool zWrite, Vector2 uvScale, Vector2 uvOffset, Material material = null) :
base(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset)
{
this.surface = track.trackRenderer.GetComponent<SurfaceGenerator>();
this.surface = track.trackRenderer.AddComponent<SurfaceGenerator>();
this.meshRenderer = surface.GetComponent<MeshRenderer>();
this.meshGenerator = surface;
this.surface.enabled = true;
this.meshGenerator.enabled = true;
this.renderMaterial = material == null ? GameManager.Instance.basePrefabs.defaultTrackMaterial : material;
this.surface.spline = track.trackPathSubmodule.path;
this.surface.doubleSided = true;
this.surface.clipFrom = 0;
this.surface.clipTo = 1;
this.surface.updateMethod = SplineUser.UpdateMethod.Update;

View File

@@ -19,12 +19,11 @@ namespace Ichni.RhythmGame
{
this.sideCount = sideCount;
this.tubeGenerator = track.trackRenderer.GetComponent<TubeGenerator>();
this.tubeGenerator = track.trackRenderer.AddComponent<TubeGenerator>();
this.meshRenderer = tubeGenerator.GetComponent<MeshRenderer>();
this.meshGenerator = tubeGenerator;
this.tubeGenerator.enabled = true;
this.meshGenerator.enabled = true;
this.renderMaterial = material == null ? GameManager.Instance.basePrefabs.defaultTrackMaterial : material;
this.tubeGenerator.spline = track.trackPathSubmodule.path;

View File

@@ -127,12 +127,12 @@ namespace Ichni.RhythmGame
particleSystemRenderer.material.SetColor("_BaseColor", colorSubmodule.currentBaseColor);
if (colorSubmodule.emissionEnabled)
{
particleSystemRenderer.material.EnableKeyword("_EMISSION_ON");
particleSystemRenderer.material.SetFloat("_EnableEmission", 1);
particleSystemRenderer.material.SetColor("_EmissionColor", colorSubmodule.GetCurrentEmissionColor());
}
else
{
particleSystemRenderer.material.DisableKeyword("_EMISSION_ON");
particleSystemRenderer.material.SetFloat("_EnableEmission", 0);
}
}
}

View File

@@ -76,6 +76,7 @@ namespace Ichni
{
GameManager.Instance.gameLoadingCanvas.FadeOut();
GameManager.Instance.songPlayer.isLoading = false;
GameManager.Instance.songPlayer.isStarting = true;
GameManager.Instance.beatmapContainer.gameElementList.ForEach(element => element.BeforeStart());

View File

@@ -10,12 +10,12 @@ namespace Ichni
public class SongPlayer : SerializedMonoBehaviour
{
public bool isLoading = true;
public bool isStarting = true;
public bool isStarting = false;
public bool isDelaying = false;
public bool isPlaying = false; // 是否正在播放音乐
public bool isPausing = false; // 是否正在暂停音乐
public bool isFinished = false;
public bool isUpdating => isDelaying || isPlaying;
public bool isUpdating => isStarting || isDelaying || isPlaying;
public Event PlayMusicEvent; // 播放背景音乐的事件
public Event ResumeMusicEvent; // 恢复播放背景音乐的事件
@@ -35,7 +35,7 @@ namespace Ichni
InformationTransistor.instance.chapterSwitch.SetValue(gameObject);
InformationTransistor.instance.songSwitch.SetValue(gameObject);
isLoading = true;
isStarting = true;
isStarting = false;
}
private void Update()

View File

@@ -193,11 +193,11 @@ namespace Ichni
assetList_Other = new List<Object>();
}
public T GetObject<T>(string name)
public T GetObject<T>(string name) where T : class
{
if (name == "None")
{
return default(T);
return null;
}
T[] assetList;
@@ -210,7 +210,7 @@ namespace Ichni
{
if (name == assetList_GameObject[i].name)
{
return assetList[i];
if (assetList != null) return assetList[i];
}
}
}
@@ -222,7 +222,7 @@ namespace Ichni
{
if (name == assetList_Material[i].name)
{
return assetList[i];
if (assetList != null) return assetList[i];
}
}
}
@@ -234,7 +234,7 @@ namespace Ichni
{
if (name == assetList_Texture[i].name)
{
return assetList[i];
if (assetList != null) return assetList[i];
}
}
}
@@ -245,12 +245,12 @@ namespace Ichni
{
if (name == assetList_Other[i].name)
{
return assetList[i];
if (assetList != null) return assetList[i];
}
}
}
return default(T);
return null;
}
}
}