This commit is contained in:
SoulliesOfficial
2025-07-10 08:42:30 -04:00
parent 150ef744e8
commit e483cfe502
286 changed files with 31518 additions and 947 deletions

View File

@@ -157,14 +157,16 @@ namespace Ichni.RhythmGame
After = 1,
Error = 100
}
public BaseElement_BM matchedBM { get; set; }
public GameElement attachedGameElement;
/// <summary>
/// 效果的持续时间如果为0则表示瞬间效果
/// </summary>
public float effectTime;
/// <summary>
/// 是否是瞬间效果
/// </summary>
@@ -174,7 +176,7 @@ namespace Ichni.RhythmGame
/// 效果的进度百分比
/// </summary>
public float effectProgressPercent;
/// <summary>
/// 效果当前的状态
/// </summary>
@@ -193,7 +195,7 @@ namespace Ichni.RhythmGame
this.nowEffectState = EffectState.Before;
this.effectProgressPercent = 0;
}
public void SaveBM()
{
throw new System.NotImplementedException();
@@ -203,7 +205,7 @@ namespace Ichni.RhythmGame
{
EffectState state = CheckEffectState(triggerTime);
float songTime = GameManager.instance.songTime;
if (state == EffectState.Before && nowEffectState != EffectState.Before)
{
nowEffectState = EffectState.Before;
@@ -216,7 +218,7 @@ namespace Ichni.RhythmGame
{
PreExecute();
}
nowEffectState = EffectState.Middle;
effectProgressPercent = (songTime - triggerTime) / effectTime;
Execute();
@@ -251,21 +253,21 @@ namespace Ichni.RhythmGame
return EffectState.Error;
}
/// <summary>
/// 当从Before状态进入Middle状态时仅在效果的开始时触发一次方法
/// </summary>
public virtual void PreExecute()
{
}
/// <summary>
/// 在效果的持续时间内,触发这个方法
/// </summary>
public virtual void Execute()
{
}
/// <summary>
@@ -274,7 +276,7 @@ namespace Ichni.RhythmGame
/// </summary>
public virtual void Adjust()
{
}
/// <summary>
@@ -282,6 +284,14 @@ namespace Ichni.RhythmGame
/// </summary>
public virtual void Recover()
{
}
/// <summary>
/// 如果效果被打断,则触发这个方法
/// </summary>
public virtual void Disrupt()
{
}

View File

@@ -118,7 +118,9 @@ namespace Ichni.RhythmGame
{
GameElement_BM.identifier.Add(gameElement.elementGuid, gameElement);
}
Debug.Log(element.attachedElementGuid);
element.ExecuteBM();
remainingElementAmount.Value--;

View File

@@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using MoreMountains.Feedbacks;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class CameraOffsetEffect : EffectBase
{
public float duration;
public Vector3 offsetValue;
public AnimationCurve offsetCurve;
Transform gameCameraTransform => GameManager.instance.cameraManager.gameCamera.gameCamera.transform;
Tweener offsetTweener;
public CameraOffsetEffect(float duration, Vector3 offsetValue, AnimationCurve offsetCurve)
{
this.effectTime = this.duration;
this.duration = duration;
this.offsetValue = offsetValue;
this.offsetCurve = offsetCurve;
}
public override void Recover()
{
offsetTweener?.Kill(true);
gameCameraTransform.localPosition = Vector3.zero;
}
public override void PreExecute()
{
offsetTweener = gameCameraTransform.DOBlendableLocalMoveBy(offsetValue, duration).SetEase(offsetCurve);
}
public override EffectBase_BM ConvertToBM()
{
return new CameraOffsetEffect_BM(duration, offsetValue, offsetCurve);
}
}
namespace Beatmap
{
public class CameraOffsetEffect_BM : EffectBase_BM
{
public float duration;
public Vector3 offsetValue;
public AnimationCurve offsetCurve;
public CameraOffsetEffect_BM(float duration, Vector3 offsetValue, AnimationCurve offsetCurve)
{
this.effectTime = duration;
this.duration = duration;
this.offsetValue = offsetValue;
this.offsetCurve = offsetCurve;
}
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{
return new CameraOffsetEffect(duration, offsetValue, offsetCurve);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b082ee12ba2393b48b5f6bce4cf23e23
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class CameraTiltEffect : EffectBase
{
public float duration;
public Vector3 tiltValue;
public AnimationCurve tiltCurve;
Transform gameCameraTransform => GameManager.instance.cameraManager.gameCamera.gameCamera.transform;
Tweener tiltTweener;
public CameraTiltEffect(float duration, Vector3 tiltValue, AnimationCurve tiltCurve)
{
this.effectTime = duration;
this.duration = duration;
this.tiltValue = tiltValue;
this.tiltCurve = tiltCurve;
}
public override void Recover()
{
tiltTweener?.Kill(true);
gameCameraTransform.localEulerAngles = Vector3.zero;
}
public override void PreExecute()
{
tiltTweener = gameCameraTransform.DOBlendableLocalRotateBy(tiltValue, duration, RotateMode.FastBeyond360).SetEase(tiltCurve);
}
public override void Adjust()
{
}
public override EffectBase_BM ConvertToBM()
{
return new CameraTiltEffect_BM(duration, tiltValue, tiltCurve);
}
public override void Disrupt()
{
tiltTweener?.Kill();
gameCameraTransform.DOLocalRotate(Vector3.zero, 0.4f);
}
}
namespace Beatmap
{
public class CameraTiltEffect_BM : EffectBase_BM
{
public float duration;
public Vector3 tiltValue;
public AnimationCurve tiltCurve;
public CameraTiltEffect_BM(float duration, Vector3 tiltValue, AnimationCurve tiltCurve)
{
this.effectTime = duration;
this.duration = duration;
this.tiltValue = tiltValue;
this.tiltCurve = tiltCurve;
}
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{
return new CameraTiltEffect(duration, tiltValue, tiltCurve);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 764e22166d03b564bb12196d028a7640
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using MoreMountains.Feedbacks;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class CameraZoomEffect : EffectBase
{
public float duration;
public float relativeZoom;
public AnimationCurve zoomCurve;
public CameraZoomEffect(float duration, float relativeZoom, AnimationCurve zoomCurve)
{
this.effectTime = 0f;
this.duration = duration;
this.relativeZoom = relativeZoom;
this.zoomCurve = zoomCurve;
}
public override void Adjust()
{
MMF_Player effect = LeanPool.Spawn(GameManager.instance.basePrefabs.cameraZoomEffect).GetComponent<MMF_Player>();
effect.GetFeedbackOfType<MMF_CameraFieldOfView>().Duration = duration;
effect.GetFeedbackOfType<MMF_CameraFieldOfView>().RemapFieldOfViewOne = relativeZoom;
effect.GetFeedbackOfType<MMF_CameraFieldOfView>().ShakeFieldOfView = zoomCurve;
effect.PlayFeedbacks();
LeanPool.Despawn(effect.gameObject, duration);
}
public override EffectBase_BM ConvertToBM()
{
return new CameraZoomEffect_BM(duration, relativeZoom, zoomCurve);
}
}
namespace Beatmap
{
public class CameraZoomEffect_BM : EffectBase_BM
{
public float duration;
public float relativeZoom;
public AnimationCurve zoomCurve;
public CameraZoomEffect_BM()
{
}
public CameraZoomEffect_BM(float duration, float relativeZoom, AnimationCurve zoomCurve)
{
this.duration = duration;
this.relativeZoom = relativeZoom;
this.zoomCurve = zoomCurve;
}
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{
return new CameraZoomEffect(duration, relativeZoom, zoomCurve);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d739305a671fa543ab8b5e1d608edc6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,90 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class PixelateEffect : EffectBase
{
public float duration;
public float bottomX;
public float bottomY;
public AnimationCurve intensityCurve;
public PixelateEffect(float duration, float bottomX, float bottomY, AnimationCurve intensityCurve)
{
this.effectTime = duration;
this.duration = duration;
this.bottomX = bottomX;
this.bottomY = bottomY;
this.intensityCurve = intensityCurve;
}
public override void Recover()
{
GameManager.instance.postProcessingManager.SetPixelateStrength(Screen.width, Screen.height);
GameManager.instance.postProcessingManager.SetFeatureActive(false);
}
public override void Disrupt()
{
GameManager.instance.postProcessingManager.SetPixelateStrength(Screen.width, Screen.height);
GameManager.instance.postProcessingManager.SetFeatureActive(false);
}
public override void PreExecute()
{
GameManager.instance.postProcessingManager.SetFeatureActive(true);
GameManager.instance.postProcessingManager.SetPixelateStrength(Screen.width, Screen.height);
}
public override void Execute()
{
float x = Mathf.Lerp(Screen.width, bottomX, intensityCurve.Evaluate(effectProgressPercent));
float y = Mathf.Lerp(Screen.height, bottomY, intensityCurve.Evaluate(effectProgressPercent));
Debug.Log(x + ", " + y);
GameManager.instance.postProcessingManager.SetPixelateStrength(x,y);
}
public override void Adjust()
{
GameManager.instance.postProcessingManager.SetPixelateStrength(Screen.width, Screen.height);
GameManager.instance.postProcessingManager.SetFeatureActive(false);
}
public override EffectBase_BM ConvertToBM()
{
return new PixelateEffect_BM(duration, bottomX, bottomY, intensityCurve);
}
}
namespace Beatmap
{
public class PixelateEffect_BM : EffectBase_BM
{
public float duration;
public float bottomX;
public float bottomY;
public AnimationCurve intensityCurve;
public PixelateEffect_BM(float duration, float bottomX, float bottomY, AnimationCurve intensityCurve)
{
this.effectTime = duration;
this.duration = duration;
this.bottomX = bottomX;
this.bottomY = bottomY;
this.intensityCurve = intensityCurve;
}
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{
return new PixelateEffect(duration, bottomX, bottomY, intensityCurve)
{
attachedGameElement = attachedGameElement
};
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7b8ffa1f96c4b9943ba150ea99ae9005
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -7,8 +7,9 @@ using UnityEngine;
namespace Ichni.RhythmGame
{
public partial class TimeEffectsCollection : GameElement, IHaveEffectSubmodule
public partial class TimeEffectsCollection : GameElement, IHaveTransformSubmodule, IHaveEffectSubmodule
{
public TransformSubmodule transformSubmodule { get; set; }
public EffectSubmodule effectSubmodule { get; set; }
public float time; //触发效果的时间
@@ -23,6 +24,7 @@ namespace Ichni.RhythmGame
public override void SetDefaultSubmodules()
{
transformSubmodule = new TransformSubmodule(this);
effectSubmodule = new EffectSubmodule(this);
}

View File

@@ -12,7 +12,7 @@ namespace Ichni.RhythmGame
public partial class Flick : NoteBase
{
public static readonly NoteJudgeIntervals judgeIntervals = new NoteJudgeIntervals(
new TimeInterval(-0.25f, -0.25f), new TimeInterval(-0.25f, -0.25f),
new TimeInterval(-0.15f, -0.25f), new TimeInterval(-0.25f, -0.25f),
new TimeInterval(-0.25f, -0.25f), new TimeInterval(-0.25f, 0.15f),
new TimeInterval(0.15f, 0.25f), new TimeInterval(0.25f, 0.25f), 0.25f);

View File

@@ -147,8 +147,6 @@ namespace Ichni.RhythmGame
float triggerTime = GameManager.instance.songTime;
float timeDifference = triggerTime - exactJudgeTime;
noteAudioSubmodule.PlayGeneralJudgeAudios();
NoteJudgeType startJudgeType = GetStartJudgeType(timeDifference);
if (startJudgeType == NoteJudgeType.Perfect)
{
@@ -167,6 +165,11 @@ namespace Ichni.RhythmGame
Miss(triggerTime);
}
if (startJudgeType != NoteJudgeType.Miss)
{
noteAudioSubmodule.PlayGeneralJudgeAudios();
}
isFirstJudged = true;
}

View File

@@ -25,8 +25,8 @@ namespace Ichni.RhythmGame
stay.preJudgeType = NoteJudgeType.NotJudged;
stay.judgeIntervals = new NoteJudgeIntervals(
new TimeInterval(-0.15f, -0.15f), new TimeInterval(-0.15f, -0.15f),
new TimeInterval(-0.15f, -0.15f), new TimeInterval(-0.15f, 0.1f),
new TimeInterval(0.1f, 0.15f), new TimeInterval(0.15f, 0.15f), 0.15f);
new TimeInterval(-0.15f, -0.15f), new TimeInterval(-0.15f, 0.125f),
new TimeInterval(0.125f, 0.15f), new TimeInterval(0.15f, 0.15f), 0.15f);
if (parentElement.TryGetComponent(out Track track))
{
@@ -63,7 +63,7 @@ namespace Ichni.RhythmGame
GameManager.instance.inputManager.checkingStayList.Add(this);
}
DecideJudge(songTime);
ExecuteFinalJudge(songTime);
base.Update();
}
@@ -89,7 +89,7 @@ namespace Ichni.RhythmGame
}
}
public void DecideJudge(float triggerTime)
public void ExecuteFinalJudge(float triggerTime)
{
if (isFirstJudged && !isFinalJudged && preJudgeType != NoteJudgeType.NotJudged &&
GameManager.instance.songTime >= exactJudgeTime)
@@ -110,6 +110,11 @@ namespace Ichni.RhythmGame
{
Miss(triggerTime);
}
if (preJudgeType != NoteJudgeType.Miss)
{
noteAudioSubmodule.PlayGeneralJudgeAudios();
}
isFinalJudged = true;
}

View File

@@ -21,9 +21,9 @@ namespace Ichni.RhythmGame
tap.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
tap.exactJudgeTime = exactJudgeTime;
tap.judgeIntervals = new NoteJudgeIntervals(
new TimeInterval(-0.15f, -0.15f), new TimeInterval(-0.15f, -0.1f),
new TimeInterval(-0.1f, -0.05f), new TimeInterval(-0.05f, 0.05f),
new TimeInterval(0.05f, 0.1f), new TimeInterval(0.1f, 0.15f), 0.15f);
new TimeInterval(-0.15f, -0.15f), new TimeInterval(-0.15f, -0.125f),
new TimeInterval(-0.125f, -0.1f), new TimeInterval(-0.1f, 0.1f),
new TimeInterval(0.1f, 0.125f), new TimeInterval(0.125f, 0.15f), 0.15f);
if (parentElement.TryGetComponent(out Track track))
{

View File

@@ -19,6 +19,7 @@ namespace Ichni.RhythmGame
string themeBundleName, string objectName, GameElement parentElement)
{
GameObject themeBundleObject = ThemeBundleManager.instance.GetObject<GameObject>(themeBundleName, objectName);
Debug.Log(themeBundleName + " " + objectName + " " + (themeBundleObject == null));
SubstantialObject substantialObject = Instantiate(themeBundleObject, parentElement.transform).GetComponent<SubstantialObject>();
substantialObject.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
substantialObject.themeBundleName = themeBundleName;

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ee0ac5310b2ba504fab9267f9ad81a9b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,257 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Dreamteck.Splines;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
using UnityEngine.Serialization;
namespace Ichni.RhythmGame
{
public partial class ParticleTracker : GameElement, IHaveColorSubmodule
{
public Track track;
public ParticleController particleController;
public ParticleSystem particle;
public ColorSubmodule colorSubmodule { get; set; }
public bool haveBaseColor => true;
public bool haveEmissionColor => true;
public string themeBundleName;
public string materialName;
public bool prewarm;
public float playTime;
public float stopTime;
public bool is3D;
public float width;
public Vector3 extendDirection;
public float density;
public float lifeTime;
public bool isAutoOrient;
public Vector3 particleRotation;
public static ParticleTracker GenerateElement(string elementName, Guid id, List<string> tags,
bool isFirstGenerated, Track track, string themeBundleName, string materialName,
bool prewarm, float playTime, float stopTime,
bool is3D, float width, Vector3 extendDirection,
float density, float lifeTime,
bool isAutoOrient, Vector3 particleRotation)
{
ParticleTracker particleTracker = Instantiate(GameManager.instance.basePrefabs.particleTracker, track.transform)
.GetComponent<ParticleTracker>();
particleTracker.Initialize(elementName, id, tags, isFirstGenerated, track);
particleTracker.track = track;
particleTracker.particleController.spline = track.trackPathSubmodule.path;
particleTracker.playTime = playTime;
particleTracker.stopTime = stopTime;
particleTracker.SetParticleMaterial(themeBundleName, materialName);
particleTracker.SetParticleSettings(prewarm, is3D, width, extendDirection, density, lifeTime, isAutoOrient, particleRotation);
return particleTracker;
}
public override void SetDefaultSubmodules()
{
colorSubmodule = new ColorSubmodule(this, Color.white, true, Color.white, 0);
}
public void SetParticleMaterial(string themeBundleName, string materialName)
{
Material material = ThemeBundleManager.instance.GetObject<Material>(themeBundleName, materialName) ??
GameManager.instance.basePrefabs.defaultParticleMaterial;
Renderer particleRenderer = particle.GetComponent<Renderer>();
particleRenderer.material = Instantiate(material);
particleRenderer.InitializeShader();
}
public void SetParticleSettings(bool prewarm,
bool is3D, float width, Vector3 extendDirection,
float density, float lifeTime,
bool isAutoOrient, Vector3 particleRotation)
{
this.prewarm = prewarm;
this.is3D = is3D;
this.width = width;
this.extendDirection = extendDirection;
this.density = density;
this.lifeTime = lifeTime;
this.prewarm = prewarm;
this.isAutoOrient = isAutoOrient;
this.particleRotation = particleRotation;
SetPrewarm();
SetShape();
SetDensity();
SetLifeTime();
SetAlignment();
}
}
public partial class ParticleTracker
{
private void Update()
{
float songTime = GameManager.instance.songTime;
if (playTime > songTime || stopTime < songTime)
{
particle.Stop();
}
else
{
if (!particle.isPlaying)
{
particle.Play();
}
}
}
public override void SaveBM()
{
matchedBM = new ParticleTracker_BM(elementName, elementGuid, tags,
parentElement.matchedBM as GameElement_BM,
prewarm, playTime, stopTime, is3D, width, extendDirection, density, lifeTime, isAutoOrient, particleRotation,
themeBundleName, materialName);
}
}
public partial class ParticleTracker
{
private void SetShape()
{
particleController.is3D = is3D;
particleController.width = width;
particleController.extendDirection = extendDirection;
particleController.Rebuild();
}
private void SetDensity()
{
var emission = particle.emission;
emission.rateOverTime = density;
}
private void SetLifeTime()
{
var mainModule = particle.main;
mainModule.startLifetime = lifeTime;
}
private void SetPrewarm()
{
var mainModule = particle.main;
mainModule.prewarm = prewarm;
}
private void SetAlignment()
{
ParticleSystemRenderer particleSystemRenderer = particle.GetComponent<ParticleSystemRenderer>();
var mainModule = particle.main;
if (isAutoOrient)
{
particleSystemRenderer.alignment = ParticleSystemRenderSpace.View;
mainModule.startRotation3D = false; // 禁用3D旋转
}
else
{
particleSystemRenderer.alignment = ParticleSystemRenderSpace.Local;
mainModule.startRotation3D = true; // 启用3D旋转
SetParticleRotation();
}
}
private void SetParticleRotation()
{
var mainModule = particle.main;
mainModule.startRotationX = particleRotation.x;
mainModule.startRotationY = particleRotation.y;
mainModule.startRotationZ = particleRotation.z;
}
public override void Refresh()
{
base.Refresh();
ParticleSystemRenderer particleSystemRenderer = particle.GetComponent<ParticleSystemRenderer>();
particleSystemRenderer.material.SetColor("_BaseColor", colorSubmodule.currentBaseColor);
if (colorSubmodule.emissionEnabled)
{
particleSystemRenderer.material.EnableKeyword("_EMISSION_ON");
particleSystemRenderer.material.SetColor("_EmissionColor", colorSubmodule.GetCurrentEmissionColor());
}
else
{
particleSystemRenderer.material.DisableKeyword("_EMISSION_ON");
}
}
}
namespace Beatmap
{
public class ParticleTracker_BM : GameElement_BM
{
public bool prewarm = false;
public float playTime = 0f;
public float stopTime = 1f;
public bool is3D = false;
public float width = 10f;
public Vector3 extendDirection = Vector3.right;
public float density = 10;
public float lifeTime = 5;
public bool isAutoOrient = true;
public Vector3 particleRotation = Vector3.zero;
public string materialThemeBundleName = string.Empty;
public string materialName = string.Empty;
public ParticleTracker_BM()
{
}
public ParticleTracker_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
bool prewarm, float playTime, float stopTime,
bool is3D, float width, Vector3 extendDirection,
float density, float lifeTime,
bool isAutoOrient, Vector3 particleRotation,
string materialThemeBundleName, string materialName) : base(elementName, elementGuid, tags, attachedElement)
{
this.prewarm = prewarm;
this.playTime = playTime;
this.stopTime = stopTime;
this.width = width;
this.density = density;
this.is3D = is3D;
this.extendDirection = extendDirection;
this.lifeTime = lifeTime;
this.isAutoOrient = isAutoOrient;
this.particleRotation = particleRotation;
this.materialThemeBundleName = materialThemeBundleName;
this.materialName = materialName;
}
public override void ExecuteBM()
{
matchedElement = ParticleTracker.GenerateElement(
elementName, elementGuid, tags, false,
GetElement(attachedElementGuid) as Track, materialThemeBundleName, materialName,
prewarm, playTime, stopTime, is3D, width, extendDirection, density, lifeTime, isAutoOrient, particleRotation);
}
public override GameElement DuplicateBM(GameElement attached)
{
return ParticleTracker.GenerateElement(
elementName, Guid.NewGuid(), tags, false,
attached as Track, materialThemeBundleName, materialName,
prewarm, playTime, stopTime, is3D, width, extendDirection, density, lifeTime, isAutoOrient, particleRotation);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ab4c5365c4f21d4797255075067de95
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -19,6 +19,7 @@ public class BasePrefabsCollection : SerializedScriptableObject
public GameObject trackDisplay;
public GameObject pathNode;
public Material defaultTrackMaterial;
public GameObject particleTracker;
[Title("Trail相关")]
public GameObject trail;
@@ -36,8 +37,10 @@ public class BasePrefabsCollection : SerializedScriptableObject
public GameObject triggerHint;
[Title("Effect相关")]
public Material defaultParticleMaterial;
public GameObject bloomEffect;
public GameObject cameraShakeEffect;
public GameObject cameraZoomEffect;
public GameObject chromaticAberrationEffect;
public GameObject vignetteEffect;
public GameObject lowPassFilterEffect;

View File

@@ -0,0 +1,27 @@
using System.Collections;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Ichni.RhythmGame
{
[CreateAssetMenu(fileName = "BasePrefabsCollection", menuName = "Ichni/CustomPrefabsCollection", order = 0)]
public class CustomPrefabsCollection : SerializedScriptableObject
{
public string themeBundleName = "theme_bundle_name_here";
public Dictionary<string, GameObject> Prefabs = new Dictionary<string, GameObject>();
public GameObject GetPrefab(string prefabName)
{
if (Prefabs.TryGetValue(prefabName, out GameObject prefab))
{
return prefab;
}
else
{
Debug.LogError($"Prefab '{prefabName}' not found in {themeBundleName} collection.");
return null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f21a52ae2934677448c0b4addcbcd9da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -34,6 +34,7 @@ namespace Ichni
public SongInformation songInformation;
public BasePrefabsCollection basePrefabs;
public Dictionary<string, CustomPrefabsCollection> customPrefabs;
[Title("UI")]
public Canvas judgeHintCanvas;

View File

@@ -1,12 +1,93 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace Ichni
{
public class PostProcessingManager : MonoBehaviour
{
public Volume globalVolume;
public PixelateFeature pixelateFeature;
void Awake()
{
FindAndCacheFeatureWithReflection();
SetFeatureActive(false);
SetPixelateStrength(Screen.width, Screen.height);
}
private void FindAndCacheFeatureWithReflection()
{
var pipelineAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (pipelineAsset == null)
{
Debug.LogError("当前渲染管线不是 UniversalRenderPipelineAsset。");
return;
}
// 2. 使用反射来获取内部的 m_RendererDataList 字段
FieldInfo rendererDataListField =
typeof(UniversalRenderPipelineAsset).GetField("m_RendererDataList", BindingFlags.NonPublic | BindingFlags.Instance);
if (rendererDataListField == null)
{
Debug.LogError("在 UniversalRenderPipelineAsset 中无法通过反射找到 'm_RendererDataList' 字段。API可能已在你的URP版本中更改。");
return;
}
var rendererDataList = rendererDataListField.GetValue(pipelineAsset) as ScriptableRendererData[];
if (rendererDataList == null)
{
Debug.LogError("获取渲染器数据列表失败。");
return;
}
// 3. 遍历获取到的列表来查找我们的Feature
foreach (var rendererData in rendererDataList)
{
if (rendererData == null) continue;
var feature = rendererData.rendererFeatures.OfType<PixelateFeature>().FirstOrDefault();
if (feature != null)
{
pixelateFeature = feature;
Debug.Log("成功找到并缓存 pixelateFeature (通过反射)!");
break;
}
}
if (pixelateFeature == null)
{
Debug.LogError("在所有 RendererData 中都未找到 pixelateFeature。");
}
}
[Button]
public void SetFeatureActive(bool enable)
{
if (pixelateFeature != null)
{
pixelateFeature.SetActive(enable);
}
}
[Button]
public void SetPixelateStrength(float strengthX, float strengthY)
{
if (pixelateFeature != null)
{
pixelateFeature.settings.pixelateStrengthX = strengthX;
pixelateFeature.settings.pixelateStrengthY = strengthY;
pixelateFeature.pixelatePass.UpdateConfig(strengthX, strengthY);
}
else
{
Debug.LogError("Pixelate feature is not initialized.");
}
}
}
}

View File

@@ -32,7 +32,15 @@ namespace Ichni
[Button("TestLoad")]
public void TestLoad()
{
ThemeBundleManager.instance.LoadThemeBundles(new List<string>(){"departure_to_multiverse"});
string beatMapFolderPath = "Beatmaps/" + InformationTransistor.instance.chapterName +
"/" + InformationTransistor.instance.songName +
"/" + InformationTransistor.instance.difficultyName;
LoadProjectInfo(beatMapFolderPath);
LoadSongInfo(beatMapFolderPath);
LoadCommandScripts(beatMapFolderPath);
ThemeBundleManager.instance.LoadThemeBundles(GameManager.instance.projectInformation.selectedThemeBundleList);
loadPercent = 0f;
Observable.EveryUpdate()
@@ -40,9 +48,7 @@ namespace Ichni
.First()
.Subscribe(_ =>
{
Load(InformationTransistor.instance.chapterName,
InformationTransistor.instance.songName,
InformationTransistor.instance.difficultyName);
LoadBeatMap(beatMapFolderPath);
});
Observable.EveryUpdate()

View File

@@ -39,7 +39,12 @@ namespace Ichni.Menu
new Color(1f, 0.2f, 0.2f, 1f)));
}
}
}
[Button]
public void SelectSwitch()
{
MenuAudioManager.instance.audioContainer.SetSwitch(chapterSwitch);
}
}

View File

@@ -96,14 +96,7 @@ namespace Ichni.Menu.UI
if (songItemPrefab != null)
{
for (int i = 0; i < songTitles.Count; i++)
{
GameObject itemGO = Instantiate(songItemPrefab, content);
itemGO.name = $"Song_{i}_{songTitles[i]}";
Text itemText = itemGO.GetComponentInChildren<Text>();
if (itemText != null) itemText.text = songTitles[i];
songItems.Add(itemGO.GetComponent<RectTransform>());
}
GenerateSongTabs();
}
Canvas.ForceUpdateCanvases();
@@ -115,7 +108,17 @@ namespace Ichni.Menu.UI
}
}
Tweener contentTween;
public void GenerateSongTabs()
{
string chapter = ChapterSelectionManager.instance.currentChapter;
ChapterSelectionUnit chapterUnit = ChapterSelectionManager.instance.chapters.Find(c => c.chapterIndex == chapter);
foreach (SongItemData song in chapterUnit.songs)
{
SongSelectionTabUI tab = Instantiate(songItemPrefab ,content).GetComponent<SongSelectionTabUI>();
songItems.Add(tab.GetComponent<RectTransform>());
tab.SetUpTab(song);
}
}
public void OnBeginDrag(PointerEventData eventData)
{
@@ -190,6 +193,22 @@ namespace Ichni.Menu.UI
}
}
public IEnumerator SnapToTab(SongSelectionTabUI tab)
{
selectedTab?.SetSelection(false);
selectedTab = null; // 清除当前选中的Tab
DOTween.To(x=>targetX = x, targetX, -1600f, 0.2f).SetEase(Ease.OutQuad).Play();
songItems.ForEach(item => item.DOScale(1.2f,0.2f).SetEase(Ease.OutQuad).Play());
yield return new WaitForSeconds(0.2f);
DOTween.To(x => targetX = x, targetX, -1500f, 0.2f).SetEase(Ease.OutQuad).Play();
songItems.ForEach(item => item.DOScale(1,0.2f).SetEase(Ease.OutQuad).Play());
yield return StartCoroutine(SnapToItem(tab.GetComponent<RectTransform>(), false));
}
private IEnumerator SnapToItem(RectTransform targetItem, bool immediate)
{
if (!immediate)

View File

@@ -14,6 +14,7 @@ namespace Ichni.Menu.UI
public TMP_Text songNameText;
public Button switchDifficultyButton;
public Button previewButton;
public Button startSongButton;
public string currentDifficultyName;
[Title("背景图&选中处理")]
@@ -45,6 +46,19 @@ namespace Ichni.Menu.UI
MenuAudioManager.instance.audioContainer.SetSwitch(connectedSong.songSwitch);
MenuAudioManager.instance.audioContainer.PostEvent("PlayPreview");
});
startSongButton.onClick.AddListener(() =>
{
if (MenuManager.instance.songSelectionUIPage.songListController.selectedTab == this)
{
MenuManager.instance.prepareUIPage.SetUpPrepareUIPage(song.songName);
MenuManager.instance.prepareUIPage.FadeIn();
}
else
{
StartCoroutine(MenuManager.instance.songSelectionUIPage.songListController.SnapToTab(this));
}
});
}
}

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using Ichni.Menu;
using Ichni.Menu.UI;
using Ichni.UI;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.UI;
@@ -11,18 +12,19 @@ namespace Ichni.Menu.UI
{
public class SongSelectionUIPage : UIPageBase
{
public GameObject songSelectionTabPrefab;
public RectTransform songSelectionTabContainer;
public List<SongSelectionTabUI> songSelectionTabs;
public SongListControllerUI songListController;
public bool isLowpassing;
public Button lowPassFilterButton;
public bool isHighpassing;
public Button highPassFilterButton;
[Title("Test")] public AK.Wwise.Switch defaultSwitch;
private void Start()
{
//GenerateSongTabs();
MenuAudioManager.instance.audioContainer.SetSwitch(defaultSwitch);
lowPassFilterButton.onClick.AddListener(() =>
{
@@ -40,25 +42,5 @@ namespace Ichni.Menu.UI
MenuAudioManager.instance.audioContainer.SetRTPC("PreviewHighPassFilter", value);
});
}
public void GenerateSongTabs()
{
string chapter = ChapterSelectionManager.instance.currentChapter;
ChapterSelectionUnit chapterUnit = ChapterSelectionManager.instance.chapters.Find(c => c.chapterIndex == chapter);
foreach (SongItemData song in chapterUnit.songs)
{
SongSelectionTabUI tab = Instantiate(songSelectionTabPrefab, songSelectionTabContainer).GetComponent<SongSelectionTabUI>();
tab.SetUpTab(song);
}
}
private void ClearTabs()
{
foreach (SongSelectionTabUI tab in songSelectionTabs)
{
Destroy(tab.gameObject);
}
songSelectionTabs.Clear();
}
}
}