Compare commits

...

3 Commits

Author SHA1 Message Date
Kexun Liu
00c4432007 update 2026-04-24 14:09:37 +08:00
SoulliesOfficial
3a63641a2c 谱面改进 2026-04-09 11:03:18 -04:00
SoulliesOfficial
9af26bb435 贴图更新 2026-04-06 11:57:38 -04:00
193 changed files with 3028 additions and 2384 deletions

5
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"recommendations": [
"visualstudiotoolsforunity.vstuc"
]
}

10
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,10 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Unity",
"type": "vstuc",
"request": "attach"
}
]
}

71
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,71 @@
{
"files.exclude": {
"**/.DS_Store": true,
"**/.git": true,
"**/.vs": true,
"**/.gitmodules": true,
"**/.vsconfig": true,
"**/*.booproj": true,
"**/*.pidb": true,
"**/*.suo": true,
"**/*.user": true,
"**/*.userprefs": true,
"**/*.unityproj": true,
"**/*.dll": true,
"**/*.exe": true,
"**/*.pdf": true,
"**/*.mid": true,
"**/*.midi": true,
"**/*.wav": true,
"**/*.gif": true,
"**/*.ico": true,
"**/*.jpg": true,
"**/*.jpeg": true,
"**/*.png": true,
"**/*.psd": true,
"**/*.tga": true,
"**/*.tif": true,
"**/*.tiff": true,
"**/*.3ds": true,
"**/*.3DS": true,
"**/*.fbx": true,
"**/*.FBX": true,
"**/*.lxo": true,
"**/*.LXO": true,
"**/*.ma": true,
"**/*.MA": true,
"**/*.obj": true,
"**/*.OBJ": true,
"**/*.asset": true,
"**/*.cubemap": true,
"**/*.flare": true,
"**/*.mat": true,
"**/*.meta": true,
"**/*.prefab": true,
"**/*.unity": true,
"build/": true,
"Build/": true,
"Library/": true,
"library/": true,
"obj/": true,
"Obj/": true,
"Logs/": true,
"logs/": true,
"ProjectSettings/": true,
"UserSettings/": true,
"temp/": true,
"Temp/": true
},
"files.associations": {
"*.asset": "yaml",
"*.meta": "yaml",
"*.prefab": "yaml",
"*.unity": "yaml",
},
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.patterns": {
"*.sln": "*.csproj",
"*.slnx": "*.csproj"
},
"dotnet.defaultSolution": "ichni_Official.slnx"
}

View File

@@ -213,7 +213,7 @@ Material:
- _Dst: 10
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EdgeValue: 0.55675477
- _EdgeValue: 0.7907124
- _EnvironmentReflections: 1
- _FNLfanxiangkaiguan: 0
- _Face: 1
@@ -258,7 +258,7 @@ Material:
- _Mask_scale: 1
- _Metallic: 0
- _OcclusionStrength: 1
- _Opacity: 0.44324523
- _Opacity: 0.20928758
- _Parallax: 0.005
- _Pass: 0
- _QueueOffset: 0

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: e00e6f90ab8233e46a41c5e33917c642
timeCreated: 1585839223
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 2690f45490c175045bbdc63395bf6278
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: fbd1fd9b3a70fad429d1eaaa5799c2a5
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 3579d9cf4b75c564faa8fffc58a9f3f6
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 0023a0858ba124646a55dfcb7231ed46
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d1c0b77896049554fa4b635531caf741
timeCreated: 1533059192
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c0a0a980c9ba86345bc15411db88d34f
timeCreated: 1585839223
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 2edbf4a9b9544774bbef617e92429664
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 13ab599a7bda4e54fba3e92a13c9580a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: f6f268949ccf3f34fa4d18e92501ed82
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 69bc3229216b1504ea3e28b5820bbb0d
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 4f665a06c5a2aa5499fa1c79ac058999
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 8a87ed432fe2d97498c0de5fae312e35
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 7c3bfbbeb9427b94099254e2e2768ad4
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: c5303861611f41c438a30be552da5de4
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: a9d68dd8913f05d4d9ce75e7b40c6044
timeCreated: 1575902011
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 2243c8b4e1ab6914995699133f67ab5a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 9a5e61a8b3421b944863d0946e32da0a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 89f0b84148d149d4d96b838d7ef60e92
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 19939ee2cdb76e0489b1b8cd4bed7f3d
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 70777e8ce9f3c8d4a8182ca2f965cdb2
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: ba281a1a00c8ac54c914e0763299f637
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: e6fc8948257acee42b666d0bfe1d782c
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 4b5cb8698f2d9c14fadf8e2383441d37
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: b460b52e6c1feae45b70b7ddc2c45bd6
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 57fcea0ed8b5eb347923c4c21fa31b57
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 2e9da72e7e3196146bf7d27450013734
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 0904cdf24ddcd5042b024326476220d5
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 929783250050f8a448821b6ca1f2c578
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: fcc4d2eb0af82e546ae75506872cf092
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: cd0a0171c5157b748afe763b89f71211
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: f4990f6ace6142c4bbbf41cdd80b0bd3
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 1782b72cd0e99a54fac09382c482e3db
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 49d5bcbbd4cbd754b98cf3200197b0f1
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: eefe45a405f061045be947217e30ed10
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 2e995dfe11e22d34d92432383d15c067
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: ec984c51d4ae2504184eeb292734c672
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: e447b3d7d913d694ca35f74e30581840
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 6584a66582083a1459dcf5e4e87f6d62
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 0190b8bde50f12943926613d9a63c89a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: ae2ce8ad295486349839288636aed1ed
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: d69745226619e3241a8e04ce86aee6a6
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 37e6a9374416bc946a55779c58d0d984
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,143 @@
fileFormatVersion: 2
guid: 801a03839a65e3042abae742e903cb62
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: iOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: e45363610a59a4543a9793b3bf2be4aa
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M
org.gradle.parallel=true
unityStreamingAssets=**STREAMING_ASSETS**
# Android Resolver Properties Start
android.useAndroidX=true
android.enableJetifier=true
# Android Resolver Properties End
**ADDITIONAL_PROPERTIES**

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 641c955d37d2fac4f87e00ac5c9d9bd8
guid: 2f011dc9caa295e4ba52ccf2f88914df
DefaultImporter:
externalObjects: {}
userData:

View File

@@ -0,0 +1,62 @@
apply plugin: 'com.android.library'
apply from: '../shared/keepUnitySymbols.gradle'
apply from: '../shared/common.gradle'
**APPLY_PLUGINS**
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Android Resolver Dependencies Start
implementation 'com.taptap.sdk:tap-core-unity:4.5.4' // Packages/com.taptap.sdk.core/Mobile/Editor/NativeDependencies.xml:7
implementation 'com.taptap.sdk:tap-login-unity:4.5.4' // Packages/com.taptap.sdk.login/Mobile/Editor/NativeDependencies.xml:7
// Android Resolver Dependencies End
**DEPS**}
// Android Resolver Exclusions Start
android {
packagingOptions {
exclude ('/lib/armeabi/*' + '*')
exclude ('/lib/mips/*' + '*')
exclude ('/lib/mips64/*' + '*')
exclude ('/lib/x86/*' + '*')
exclude ('/lib/x86_64/*' + '*')
}
}
// Android Resolver Exclusions End
android {
namespace "com.unity3d.player"
ndkPath "**NDKPATH**"
ndkVersion "**NDKVERSION**"
compileSdk **APIVERSION**
buildToolsVersion = "**BUILDTOOLS**"
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
defaultConfig {
minSdk **MINSDK**
targetSdk **TARGETSDK**
ndk {
abiFilters **ABIFILTERS**
debugSymbolLevel **DEBUGSYMBOLLEVEL**
}
versionCode **VERSIONCODE**
versionName '**VERSIONNAME**'
consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
**DEFAULT_CONFIG_SETUP**
}
lint {
abortOnError false
}
androidResources {
noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
}**PACKAGING**
}
**IL_CPP_BUILD_SETUP**
**SOURCE_BUILD_SETUP**
**EXTERNAL_SOURCES**

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 9da5530d5ebfab24c8ecad68795e720f
guid: 655395b375b4d6a42912b6dcb6975d5a
DefaultImporter:
externalObjects: {}
userData:

View File

@@ -0,0 +1,30 @@
pluginManagement {
repositories {
**ARTIFACTORYREPOSITORY**
gradlePluginPortal()
google()
mavenCentral()
}
}
include ':launcher', ':unityLibrary'
**INCLUDES**
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
**ARTIFACTORYREPOSITORY**
google()
mavenCentral()
// Android Resolver Repos Start
def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
maven {
url "https://repo.maven.apache.org/maven2" // Packages/com.taptap.sdk.core/Mobile/Editor/NativeDependencies.xml:6, Packages/com.taptap.sdk.login/Mobile/Editor/NativeDependencies.xml:6
}
mavenLocal()
// Android Resolver Repos End
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: aa102d640b98b5d4781710a3a3dd6983
guid: 118024034a116824492c045e4ed76102
DefaultImporter:
externalObjects: {}
userData:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: de41a70ead12af544a4e99a925b269d2
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: f597f19f656ba56eae4f6a3a7cc528f4
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 48e08dc33330d11e9d4a1b246c52e4f6
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: ed09910c0094cb27be8f3ca264680da3
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: cc355dd4cf1e6173beaeb22c2858cbe1
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,6 @@
fileFormatVersion: 2
guid: 7a0bb33169d95ec499136d59cb25918b
guid: 10881d2adadf8ec4b98d2d82ac5aeced
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:

View File

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

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>taptap</key>
<dict>
<key>client_id</key>
<string>hkbfpbh2jv2kbxupmo</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2e16439f3c8742e290813744436c8547
timeCreated: 1777006961

View File

@@ -75,18 +75,17 @@ MonoBehaviour:
parentElement: {fileID: 0}
childElementList: []
trackListFolder: {fileID: 0}
nowAttachedTrack: {fileID: 0}
trackPositioner: {fileID: -320456605675426144}
trackSwitch:
value: 0
animations: []
trackPercent:
value: 0
currentAnimationIndex: 0
animations: []
isSwitchingReturnType: 0
lastReturnType: 0
returnType: 0
nowAttachedTrack: {fileID: 0}
trackPositioner: {fileID: -320456605675426144}
--- !u!114 &-320456605675426144
MonoBehaviour:
m_ObjectHideFlags: 0

View File

@@ -1 +1 @@
Nïqsª¡L¨^bHTnZq£ý8ÿdÈ•}⋇Oô¢Ó¯´ èV Uù0ùŠ®¸m†òÓg”¹µËû½Í«æ7¼Qö&Í;_£@ÃüyÏÀþN²ç‰%3#W¾¢$ò†Ä<E280A0>þ"O"–¹ 0‡ÅzüÜ}¢E<C2A2>'¡ÿÐg;«ú4­Ê¦ÿp êöøÎÐv®·ë·HÞßZ¡Ûkç<>ÕŽO;Ùž¬(i<>D-Öðσþ„eÁZðÏÆ<C38F>`|{Æz_Ší~
0"ª§ƒ.µü|cIØ{òXçlqEg]ußM è'ÙËKY§ƒh½uÊ^¬jûœ„Dh3DGמ³FòNSjfC™ §%,æ¤&Í<> YÚçd©¥¯‡+騄0Sí8#Ð[Q¾¶äûËF{!Ý[¸ü²ÍVPÉOÓÉ»Œ0.¬ü#ñÞ=žNh0Œ$ÙΕ`È?0ƒ¶"«j®ÐιÉö©àžèÖ¢¬òÏUnæO•·`ÿ<>Ë[ì<>:â¯Æ-ÚõÒò

View File

@@ -1 +1 @@
2ŸQº6<EFBFBD>5üñ9Å•JšrEeyµ[¯êéÿ$R ~¼©62Véšaâ«E¤| û~²<1F>Å ›ÕùÐ)<29>j_ÇÂn'¶C@ùÓ`hw(È„mëTqËÄŠ.E4_'³-(+5F”î8ƒòMðBÌði4†]Dž¬½Uíø¥ôi<C3B4>ü™½á¸ˆ»Z7Yk ñÈèPœ…éO&|S-•g´Æ[Ö~hhRÐH¬ðßÕæ)a•š·Ô¶¼,Œ`b±¨ièŠ|ÊO׆é„Åš °ƒú½Å\¿dÜÀŒ¤ïauTWJ¤h¶Sµ™ðÉNÛ¬ÆpR¼l=<3D>î‰OJõ¨à÷-øa !ã|¯Ûy}¥C÷ã<C3B7>oÚÍQâ—„ Ø®ŒE`)[Al ÔKºëÄ~Þ–Ž?4c<34>Aϯد}Ojd†P€¡ª[øúÃú0å.ã¸û÷êð œôÆ`àÞåd,¼˜ˆ“~mò§! sœ0LÄ<4C>yó¥µAz¯
¼¶DufäÔ†ˆs\Ò§n*à´åß~K1ПÚüiY——©àÇ&-Y<>rÓPgܯˆÄ-?“ãùàxú£µ'o“¦ ع<C398>Uñ?GYD7úc÷u$ó”ˆcåŽ<C3A5>Û«æ-¢ýðÙAZÂ(cا*ëϤ=g)†,X7Y<17>6³És¨ýÙ~î±ÚÈ<E280BA>™vÄÊÔ6G»g]ŠÊ,ÛwÛ<77>ž!ÛuÄׇ4 :MÊïicÏ'ð“øÁÜ«R\DpÒ3Àç¯# R3<52>ya_ñ6=W÷V` ìo¢ ¥¡¹üó«ŠÎ<C5A0>Ÿ¥µ@Ìu×þÏËž•oQ³µäÿ<C3A4>†d.

View File

@@ -1,2 +1,2 @@
‡3&H x¥©'A_€iØ’üÆ€ÿ½¸±
ú Knüq׬.¿^X:þ¿"°Õÿ?àFopù¯qЗGª;
etmžÔ#A*2`p*ŹÍ»&0pn´Ęq;ÄigÂcZž“`Ňbľ„Ię|˝ŹÝÍ4>Ě3·ćű<C487>ů‡“·ÓT ´îú®94<08>/<{ľľ ^ŇzŹŕŻC…~9î°ŰZĽHjÇIDç Wd­óăGÄFĐ,}µÁouČWR3ę D㨠¨S¨ůěĚ®$ďr>Ťs€v84o±3Ĺ­ł
ŹÖéě.•Ö<E280A2>qÁLÓiŤ2]¸=řÖ–Ů

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 2d07768ea909cfb498ad7d94654ddb43
guid: 8483718c446c7ed45b3b86df1288ce1d
DefaultImporter:
externalObjects: {}
userData:

View File

@@ -1 +1 @@
~ Ç¿¸ã˜Ðm¹
.<2E>¯ôc8KŒ³o+0oÑÆb.T@Qdᮤ@¾`.ÇA ÞKcÁ\2ÎÜ „–Ó*S~§ÚX½ÁðqABýwûN7·åéE2¨<ÏöåðЇÀÝ…¶Fw²Õâ{:oc™˜Pv³šÜ˜½U<C2BD><55>·®S¥íI9Î+qt<71>RCÙì/ú°z(NDÃó<15>MØ)qô5'<27>P&ðg brÐ<E2809A>MÜiO,¹R<è·†hˆE^

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6db0530f3f252ea49a8632143147055a
guid: cad57e5cfb75195408117eab9d49cb5b
DefaultImporter:
externalObjects: {}
userData:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 026dad72b6da4aa4084dc964e0318385
guid: f30fbeb27fd2d4447a921b871b5290f3
DefaultImporter:
externalObjects: {}
userData:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: cabf01a814316254195299c0ec98c034
guid: 368abe1a7c6070948b31ad33bdbcc8b7
DefaultImporter:
externalObjects: {}
userData:

Binary file not shown.

View File

@@ -10146,6 +10146,16 @@ MonoBehaviour:
valueGuidInternal:
WwiseObjectReference: {fileID: 11400000, guid: d277bb13d318c414999deb758c16baac,
type: 2}
HighPassFilter:
idInternal: 0
valueGuidInternal:
WwiseObjectReference: {fileID: 11400000, guid: 2506771a66ac1e84f80022e7212bfc01,
type: 2}
LowPassFilter:
idInternal: 0
valueGuidInternal:
WwiseObjectReference: {fileID: 11400000, guid: 2ad6d003174f1ae4387341238ade2cb4,
type: 2}
songTimeSegment: 0
pauseTimeSegment: 0
judgeOffset: 0

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@ namespace Ichni.RhythmGame.Beatmap
public class HighPassFilterEffect_BM: EffectBase_BM
{
public float peak;
public bool useEQ;
public AnimationCurve intensityCurve;
public HighPassFilterEffect_BM()
@@ -12,17 +13,17 @@ namespace Ichni.RhythmGame.Beatmap
}
public HighPassFilterEffect_BM(float effectTime, float peak, AnimationCurve intensityCurve)
public HighPassFilterEffect_BM(float effectTime, float peak, bool useEQ, AnimationCurve intensityCurve)
{
this.effectTime = 0;
this.effectTime = effectTime;
this.peak = peak;
this.useEQ = useEQ;
this.intensityCurve = intensityCurve;
}
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{
return new HighPassFilterEffect(effectTime, peak, intensityCurve);
return new HighPassFilterEffect(effectTime, peak, useEQ, intensityCurve);
}
}
}

View File

@@ -5,6 +5,7 @@ namespace Ichni.RhythmGame.Beatmap
public class LowPassFilterEffect_BM: EffectBase_BM
{
public float bottom;
public bool useEQ;
public AnimationCurve intensityCurve;
public LowPassFilterEffect_BM()
@@ -12,17 +13,17 @@ namespace Ichni.RhythmGame.Beatmap
}
public LowPassFilterEffect_BM(float effectTime, float bottom, AnimationCurve intensityCurve)
public LowPassFilterEffect_BM(float effectTime, float bottom, bool useEQ, AnimationCurve intensityCurve)
{
this.effectTime = 0;
this.effectTime = effectTime;
this.bottom = bottom;
this.useEQ = useEQ;
this.intensityCurve = intensityCurve;
}
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{
return new LowPassFilterEffect(effectTime, bottom, intensityCurve);
return new LowPassFilterEffect(effectTime, bottom, useEQ, intensityCurve);
}
}
}

View File

@@ -12,8 +12,13 @@ namespace Ichni.RhythmGame
#region [] Exposed Fields & References
private TransformSubmodule targetTransformSubmodule;
public FlexibleFloat positionX, positionY, positionZ;
public static HashSet<Displacement> ActiveDisplacements = new HashSet<Displacement>();
#endregion
protected void OnEnable() { ActiveDisplacements.Add(this); }
protected void OnDisable() { ActiveDisplacements.Remove(this); }
#region [] Lifecycle & Factory
public static Displacement GenerateElement(string elementName, Guid id,
List<string> tags, bool isFirstGenerated, GameElement animatedObject,
@@ -45,21 +50,65 @@ namespace Ichni.RhythmGame
positionY.UpdateFlexibleFloat(songTime);
positionZ.UpdateFlexibleFloat(songTime);
if (forceUpdate || positionX.returnType is FlexibleReturnType.MiddleExecuting ||
positionY.returnType is FlexibleReturnType.MiddleExecuting ||
positionZ.returnType is FlexibleReturnType.MiddleExecuting)
bool isMiddleExecuting = positionX.returnType is FlexibleReturnType.MiddleExecuting ||
positionY.returnType is FlexibleReturnType.MiddleExecuting ||
positionZ.returnType is FlexibleReturnType.MiddleExecuting;
bool isSwitching = positionX.isSwitchingReturnType || positionY.isSwitchingReturnType || positionZ.isSwitchingReturnType;
if (forceUpdate || isMiddleExecuting)
{
if(!forceUpdate) animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentPosition = new Vector3(positionX.value, positionY.value, positionZ.value);
targetTransformSubmodule.positionOffset += currentPosition;
targetTransformSubmodule.positionDirtyMark = true;
// 首帧合并退让保护
bool shouldSkipFirstFrame = false;
if (!forceUpdate && isSwitching)
{
foreach (var d in ActiveDisplacements)
{
if (d != this && d.targetTransformSubmodule == this.targetTransformSubmodule)
{
if (d.positionX.isSwitchingReturnType || d.positionY.isSwitchingReturnType || d.positionZ.isSwitchingReturnType)
{
shouldSkipFirstFrame = true;
break;
}
}
}
}
if (!shouldSkipFirstFrame)
{
Vector3 currentPosition = new Vector3(positionX.value, positionY.value, positionZ.value);
targetTransformSubmodule.positionOffset += currentPosition;
targetTransformSubmodule.positionDirtyMark = true;
}
}
else if (positionX.isSwitchingReturnType || positionY.isSwitchingReturnType || positionZ.isSwitchingReturnType)
else if (isSwitching)
{
//animationReturnType = FlexibleReturnType.MiddleExecuting;
//Vector3 currentPosition = new Vector3(positionX.value, positionY.value, positionZ.value);
//targetTransformSubmodule.positionOffset += currentPosition;
//targetTransformSubmodule.positionDirtyMark = true;
// 最终帧补偿机制
bool isAnyOtherExecuting = false;
foreach (var d in ActiveDisplacements)
{
if (d != this && d.targetTransformSubmodule == this.targetTransformSubmodule)
{
if (d.positionX.returnType is FlexibleReturnType.MiddleExecuting ||
d.positionY.returnType is FlexibleReturnType.MiddleExecuting ||
d.positionZ.returnType is FlexibleReturnType.MiddleExecuting)
{
isAnyOtherExecuting = true;
break;
}
}
}
if (!isAnyOtherExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentPosition = new Vector3(positionX.value, positionY.value, positionZ.value);
targetTransformSubmodule.positionOffset += currentPosition;
targetTransformSubmodule.positionDirtyMark = true;
}
}
else
{

View File

@@ -11,8 +11,14 @@ namespace Ichni.RhythmGame
#region [] Exposed Fields & References
public TransformSubmodule targetTransformSubmodule;
public FlexibleFloat scaleX, scaleY, scaleZ;
// 静态跟踪全局激活的Scale组件为了方便同物体的跨动画状态感应
public static HashSet<Scale> ActiveScales = new HashSet<Scale>();
#endregion
protected void OnEnable() { ActiveScales.Add(this); }
protected void OnDisable() { ActiveScales.Remove(this); }
#region [] Lifecycle & Factory
public static Scale GenerateElement(string elementName, Guid id,
List<string> tags, bool isFirstGenerated, GameElement animatedObject,
@@ -49,21 +55,65 @@ namespace Ichni.RhythmGame
scaleY.UpdateFlexibleFloat(songTime);
scaleZ.UpdateFlexibleFloat(songTime);
if (forceUpdate || scaleX.returnType is FlexibleReturnType.MiddleExecuting ||
scaleY.returnType is FlexibleReturnType.MiddleExecuting ||
scaleZ.returnType is FlexibleReturnType.MiddleExecuting)
bool isMiddleExecuting = scaleX.returnType is FlexibleReturnType.MiddleExecuting ||
scaleY.returnType is FlexibleReturnType.MiddleExecuting ||
scaleZ.returnType is FlexibleReturnType.MiddleExecuting;
bool isSwitching = scaleX.isSwitchingReturnType || scaleY.isSwitchingReturnType || scaleZ.isSwitchingReturnType;
if (forceUpdate || isMiddleExecuting)
{
if(!forceUpdate) animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentScale = new Vector3(scaleX.value, scaleY.value, scaleZ.value);
targetTransformSubmodule.scaleOffset += currentScale;
targetTransformSubmodule.scaleDirtyMark = true;
// 检查是否是刚开始的第一帧,且有其它同类动画正在收尾(避免两帧叠加导致 ScaleX2
bool shouldSkipFirstFrame = false;
if (!forceUpdate && isSwitching)
{
foreach (var s in ActiveScales)
{
if (s != this && s.targetTransformSubmodule == this.targetTransformSubmodule)
{
if (s.scaleX.isSwitchingReturnType || s.scaleY.isSwitchingReturnType || s.scaleZ.isSwitchingReturnType)
{
shouldSkipFirstFrame = true;
break;
}
}
}
}
if (!shouldSkipFirstFrame)
{
Vector3 currentScale = new Vector3(scaleX.value, scaleY.value, scaleZ.value);
targetTransformSubmodule.scaleOffset += currentScale;
targetTransformSubmodule.scaleDirtyMark = true;
}
}
else if (scaleX.isSwitchingReturnType || scaleY.isSwitchingReturnType || scaleZ.isSwitchingReturnType)
else if (isSwitching)
{
//animationReturnType = FlexibleReturnType.MiddleExecuting;
//Vector3 currentScale = new Vector3(scaleX.value, scaleY.value, scaleZ.value);
//targetTransformSubmodule.scaleOffset += currentScale;
//targetTransformSubmodule.scaleDirtyMark = true;
// 【收尾保护】如果这个动画是附着物体的“最后的动画”的结束,额外更新彻底将其设为终定值
bool isAnyOtherExecuting = false;
foreach (var s in ActiveScales)
{
if (s != this && s.targetTransformSubmodule == this.targetTransformSubmodule)
{
if (s.scaleX.returnType is FlexibleReturnType.MiddleExecuting ||
s.scaleY.returnType is FlexibleReturnType.MiddleExecuting ||
s.scaleZ.returnType is FlexibleReturnType.MiddleExecuting)
{
isAnyOtherExecuting = true;
break;
}
}
}
if (!isAnyOtherExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting; // 使系统认为有有效活动
Vector3 currentScale = new Vector3(scaleX.value, scaleY.value, scaleZ.value);
targetTransformSubmodule.scaleOffset += currentScale;
targetTransformSubmodule.scaleDirtyMark = true;
}
}
else
{

View File

@@ -12,8 +12,13 @@ namespace Ichni.RhythmGame
#region [] Exposed Fields & References
private TransformSubmodule targetTransformSubmodule;
public FlexibleFloat eulerAngleX, eulerAngleY, eulerAngleZ;
public static HashSet<Swirl> ActiveSwirls = new HashSet<Swirl>();
#endregion
protected void OnEnable() { ActiveSwirls.Add(this); }
protected void OnDisable() { ActiveSwirls.Remove(this); }
#region [] Lifecycle & Factory
public static Swirl GenerateElement(string elementName, Guid id,
List<string> tags, bool isFirstGenerated, GameElement animatedObject,
@@ -43,22 +48,65 @@ namespace Ichni.RhythmGame
eulerAngleY.UpdateFlexibleFloat(songTime);
eulerAngleZ.UpdateFlexibleFloat(songTime);
if (forceUpdate || eulerAngleX.returnType is FlexibleReturnType.MiddleExecuting ||
eulerAngleY.returnType is FlexibleReturnType.MiddleExecuting ||
eulerAngleZ.returnType is FlexibleReturnType.MiddleExecuting)
bool isMiddleExecuting = eulerAngleX.returnType is FlexibleReturnType.MiddleExecuting ||
eulerAngleY.returnType is FlexibleReturnType.MiddleExecuting ||
eulerAngleZ.returnType is FlexibleReturnType.MiddleExecuting;
bool isSwitching = eulerAngleX.isSwitchingReturnType || eulerAngleY.isSwitchingReturnType || eulerAngleZ.isSwitchingReturnType;
if (forceUpdate || isMiddleExecuting)
{
if(!forceUpdate) animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentEulerAngles = new Vector3(eulerAngleX.value, eulerAngleY.value, eulerAngleZ.value);
targetTransformSubmodule.eulerAnglesOffset += currentEulerAngles;
targetTransformSubmodule.eulerAnglesDirtyMark = true;
// 首帧合并退让保护
bool shouldSkipFirstFrame = false;
if (!forceUpdate && isSwitching)
{
foreach (var s in ActiveSwirls)
{
if (s != this && s.targetTransformSubmodule == this.targetTransformSubmodule)
{
if (s.eulerAngleX.isSwitchingReturnType || s.eulerAngleY.isSwitchingReturnType || s.eulerAngleZ.isSwitchingReturnType)
{
shouldSkipFirstFrame = true;
break;
}
}
}
}
if (!shouldSkipFirstFrame)
{
Vector3 currentEulerAngles = new Vector3(eulerAngleX.value, eulerAngleY.value, eulerAngleZ.value);
targetTransformSubmodule.eulerAnglesOffset += currentEulerAngles;
targetTransformSubmodule.eulerAnglesDirtyMark = true;
}
}
else if (eulerAngleX.isSwitchingReturnType || eulerAngleY.isSwitchingReturnType || eulerAngleZ.isSwitchingReturnType)
else if (isSwitching)
{
//animationReturnType = FlexibleReturnType.MiddleExecuting;
//Vector3 currentEulerAngles = new Vector3(eulerAngleX.value, eulerAngleY.value, eulerAngleZ.value);
//targetTransformSubmodule.eulerAnglesOffset += currentEulerAngles;
//Debug.Break();
//targetTransformSubmodule.eulerAnglesDirtyMark = true;
// 最终帧补偿机制
bool isAnyOtherExecuting = false;
foreach (var s in ActiveSwirls)
{
if (s != this && s.targetTransformSubmodule == this.targetTransformSubmodule)
{
if (s.eulerAngleX.returnType is FlexibleReturnType.MiddleExecuting ||
s.eulerAngleY.returnType is FlexibleReturnType.MiddleExecuting ||
s.eulerAngleZ.returnType is FlexibleReturnType.MiddleExecuting)
{
isAnyOtherExecuting = true;
break;
}
}
}
if (!isAnyOtherExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentEulerAngles = new Vector3(eulerAngleX.value, eulerAngleY.value, eulerAngleZ.value);
targetTransformSubmodule.eulerAnglesOffset += currentEulerAngles;
targetTransformSubmodule.eulerAnglesDirtyMark = true;
}
}
else
{

View File

@@ -1,40 +1,92 @@
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class HighPassFilterEffect : EffectBase
/// <summary>
/// 高通滤波效果Wwise RTPC 驱动版)。
/// 在 Wwise 中需要创建名为 "Song_Highpass" 的 RTPC范围 0~100
/// 并将其连接到 Music Bus 的 High-Pass Filter 参数Built-in Parameter
///
/// BM 中存储的 peak 是 Unity AudioHighPassFilter.cutoffFrequencyHz
/// 运行时使用对数公式转换为 Wwise RTPC0~100保持与 Unity 编辑器中一致的感知效果。
/// 转换公式rtpc = (ln(currentFreq) - ln(minFreq)) / (ln(maxFreq) - ln(minFreq)) * 100
///
/// 示例3500 Hz → RTPC ≈ 76与编辑器中 Unity HPF 3500Hz 感知等效)
/// </summary>
public partial class HighPassFilterEffect : EffectBase
{
#region [] Effect Parameters
// peakBM 中存储的目标截止频率Hz语义与 Unity AudioHighPassFilter.cutoffFrequency 一致
public float peak;
public bool useEQ;
public AnimationCurve intensityCurve;
private const string RtpcName = "Song_Highpass";
// 人耳可听范围边界
private const float MinFrequency = 20f; // 对应 RTPC = 0无滤波
private const float MaxFrequency = 20000f; // 对应 RTPC = 100完全截止
// 幂次指数:调节频率到 RTPC 的曲线弯曲程度
// 1.0 = 纯线性(效果太弱)
// 0.5 = 接近对数(效果太强)
// 0.65 = 推荐起点,可根据实际测试微调(向 1.0 调弱,向 0.5 调强)
private const float PowerExponent = 0.25f;
#endregion
#region [] Initialization
public HighPassFilterEffect(float effectTime, float peak, AnimationCurve intensityCurve)
public HighPassFilterEffect(float effectTime, float peak, bool useEQ, AnimationCurve intensityCurve)
: base(effectTime)
{
this.effectTime = 0;
this.effectTime = effectTime;
this.peak = peak;
this.useEQ = useEQ;
this.intensityCurve = intensityCurve;
}
#endregion
#region [] Effect Pattern Overrides
public override void Adjust()
#region [] Hz Wwise RTPC
/// <summary>
/// 将频率值Hz通过幂次曲线映射到 Wwise HPF RTPC0~100
/// 10 Hz → 0无滤波22000 Hz → 100完全截止
/// 调整 PowerExponent 可改变曲线弯曲程度:越小越像对数(强),越接近 1 越线性(弱)。
/// </summary>
private static float FrequencyToRtpc(float frequencyHz)
{
/*MMF_Player effect = LeanPool.Spawn(GameManager.Instance.basePrefabs.highPassFilterEffect).GetComponent<MMF_Player>();
effect.GetFeedbackOfType<MMF_AudioFilterHighPass>().effectTime = effectTime;
effect.GetFeedbackOfType<MMF_AudioFilterHighPass>().RemapHighPassZero = 10;
effect.GetFeedbackOfType<MMF_AudioFilterHighPass>().RemapHighPassOne = peak;
effect.GetFeedbackOfType<MMF_AudioFilterHighPass>().ShakeHighPass = intensityCurve;
effect.PlayFeedbacks();
LeanPool.Despawn(effect.gameObject, effectTime);*/
float clampedFreq = Mathf.Clamp(frequencyHz, MinFrequency, MaxFrequency);
// 先归一化到 0~1线性
float normalized = (clampedFreq - MinFrequency) / (MaxFrequency - MinFrequency);
// 幂次变换compressed = normalized^exponent使曲线在低频段更灵敏
float shaped = Mathf.Pow(normalized, PowerExponent);
return Mathf.Clamp(shaped * 100f, 0f, 100f);
}
#endregion
#region [] Effect Pattern Overrides
public override void PreExecute() { }
public override void Execute()
{
// 在 10Hz无效果与 peak Hz最强截止之间基于曲线插值
float intensity = intensityCurve != null ? intensityCurve.Evaluate(effectProgressPercent) : 0f;
float currentFreq = Mathf.Lerp(MinFrequency, peak, intensity);
// 对数映射到 Wwise RTPC
float rtpcValue = FrequencyToRtpc(currentFreq);
GameManager.Instance.songPlayer.HighPassFilter.SetValue(GameManager.Instance.songPlayer.gameObject, rtpcValue);
}
public override void Adjust() { ResetEffect(); }
public override void Recover() { ResetEffect(); }
public override void Disrupt() { ResetEffect(); }
private void ResetEffect()
{
// RTPC = 0 → 10Hz → 无滤波
GameManager.Instance.songPlayer.HighPassFilter.SetValue(GameManager.Instance.songPlayer.gameObject, 0f);
Debug.Log("HighPassFilterEffect reset: RTPC set to 0 (10Hz, no filter)");
}
#endregion
}
}

View File

@@ -1,42 +1,89 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class LowPassFilterEffect : EffectBase
/// <summary>
/// 低通滤波效果Wwise RTPC 驱动版)。
/// 在 Wwise 中需要创建名为 "Song_Lowpass" 的 RTPC范围 0~100
/// 并将其连接到 Music Bus 的 Low-Pass Filter 参数Built-in Parameter
///
/// BM 中存储的 bottom 是 Unity AudioLowPassFilter.cutoffFrequencyHz
/// 运行时使用对数公式转换为 Wwise RTPC0~100保持与 Unity 编辑器中一致的感知效果。
/// 转换公式rtpc = (ln(maxFreq) - ln(currentFreq)) / (ln(maxFreq) - ln(minFreq)) * 100
/// </summary>
public partial class LowPassFilterEffect : EffectBase
{
#region [] Effect Parameters
// bottomBM 中存储的目标截止频率Hz语义与 Unity AudioLowPassFilter.cutoffFrequency 一致
public float bottom;
public bool useEQ;
public AnimationCurve intensityCurve;
private const string RtpcName = "Song_Lowpass";
// 人耳可听范围边界
private const float MinFrequency = 20f; // 对应 RTPC = 100完全截止
private const float MaxFrequency = 20000f; // 对应 RTPC = 0无滤波
// 幂次指数:调节频率到 RTPC 的曲线弯曲程度
// 1.0 = 纯线性(效果太弱)
// 0.5 = 接近对数(效果太强)
// 0.65 = 推荐起点,可根据实际测试微调(向 1.0 调弱,向 0.5 调强)
private const float PowerExponent = 0.25f;
#endregion
#region [] Initialization
public LowPassFilterEffect(float effectTime, float bottom, AnimationCurve intensityCurve)
public LowPassFilterEffect(float effectTime, float bottom, bool useEQ, AnimationCurve intensityCurve)
: base(effectTime)
{
this.effectTime = 0;
this.effectTime = effectTime;
this.bottom = bottom;
this.useEQ = useEQ;
this.intensityCurve = intensityCurve;
}
#endregion
#region [] Effect Pattern Overrides
public override void Adjust()
#region [] Hz Wwise RTPC
/// <summary>
/// 将频率值Hz通过幂次曲线映射到 Wwise LPF RTPC0~100
/// 22000 Hz → 0无滤波趋近 10 Hz → 100完全截止
/// 调整 PowerExponent 可改变曲线弯曲程度:越小越像对数(强),越接近 1 越线性(弱)。
/// </summary>
private static float FrequencyToRtpc(float frequencyHz)
{
/*MMF_Player effect = LeanPool.Spawn(GameManager.Instance.basePrefabs.lowPassFilterEffect).GetComponent<MMF_Player>();
effect.GetFeedbackOfType<MMF_AudioFilterLowPass>().effectTime = effectTime;
effect.GetFeedbackOfType<MMF_AudioFilterLowPass>().RemapLowPassZero = 22000;
effect.GetFeedbackOfType<MMF_AudioFilterLowPass>().RemapLowPassOne = bottom;
effect.GetFeedbackOfType<MMF_AudioFilterLowPass>().ShakeLowPass = intensityCurve;
effect.PlayFeedbacks();
LeanPool.Despawn(effect.gameObject, effectTime);*/
float clampedFreq = Mathf.Clamp(frequencyHz, MinFrequency, MaxFrequency);
// 先归一化:频率大 = 房内线性值大(无滤波方向)
float normalized = (clampedFreq - MinFrequency) / (MaxFrequency - MinFrequency);
// 幂次变换,然后反转(频率越低 = RTPC 越高 = 截止越强)
float shaped = Mathf.Pow(normalized, PowerExponent);
return Mathf.Clamp((1f - shaped) * 100f, 0f, 100f);
}
#endregion
#region [] Effect Pattern Overrides
public override void PreExecute() { }
public override void Execute()
{
// 在 22000Hz无效果与 bottom Hz最强截止之间基于曲线插值
float intensity = intensityCurve != null ? intensityCurve.Evaluate(effectProgressPercent) : 0f;
float currentFreq = Mathf.Lerp(MaxFrequency, bottom, intensity);
// 对数映射到 Wwise RTPC
float rtpcValue = FrequencyToRtpc(currentFreq);
GameManager.Instance.songPlayer.LowPassFilter.SetValue(GameManager.Instance.songPlayer.gameObject, rtpcValue);
}
public override void Adjust() { ResetEffect(); }
public override void Recover() { ResetEffect(); }
public override void Disrupt() { ResetEffect(); }
private void ResetEffect()
{
// RTPC = 0 → 22000Hz → 无滤波
GameManager.Instance.songPlayer.LowPassFilter.SetValue(GameManager.Instance.songPlayer.gameObject, 0f);
}
#endregion
}
}

View File

@@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using AK.Wwise;
using Sirenix.OdinInspector;
using SLSUtilities.WwiseAssistance;
using UnityEngine;
@@ -21,6 +22,9 @@ namespace Ichni
public Event ResumeMusicEvent; // 恢复播放背景音乐的事件
public Event PauseMusicEvent; // 暂停播放背景音乐的事件
public Event StopMusicEvent; // 停止播放背景音乐的事件
public RTPC HighPassFilter;
public RTPC LowPassFilter;
private uint _playingId;
public float songTimeSegment = 0;
@@ -36,6 +40,7 @@ namespace Ichni
InformationTransistor.instance.songSwitch.SetValue(gameObject);
isLoading = true;
isStarting = false;
}
private void Update()
@@ -73,12 +78,31 @@ namespace Ichni
if (isPlaying)
{
// 获取底层 Wwise 的当前正确时间
float currentSongSegment = PlaySegment() / 1000f - (judgeOffset / 1000f);
if (recordedSongSeg < currentSongSegment)
// 1. 让游戏时间先基于引擎渲染帧线性平滑推进
songTimeSegment += Time.deltaTime * Time.timeScale;
// 2. 计算当前平滑时间与底层实际音频时间的误差
float difference = currentSongSegment - songTimeSegment;
// 3. 时间校准逻辑
// 如果偏差非常大(例如超过 50ms说明游戏发生过卡顿停顿强行同步消除误差
if (Mathf.Abs(difference) > 0.05f)
{
songTimeSegment = currentSongSegment;
recordedSongSeg = currentSongSegment;
}
else
{
// 如果在正常范围内使用微调去柔和追击这个误差避免肉眼看到跳变Jitter
songTimeSegment += difference * 0.1f;
}
// 保证时间不要神奇地倒退影响铺面逻辑
if (songTimeSegment > recordedSongSeg)
{
recordedSongSeg = songTimeSegment;
}
}
else if (isPausing)
@@ -155,7 +179,7 @@ namespace Ichni
int PlaySegment()
{
AkSegmentInfo segmentInfo = new AkSegmentInfo();
AkSoundEngine.GetPlayingSegmentInfo(_playingId, segmentInfo,true);
AkUnitySoundEngine.GetPlayingSegmentInfo(_playingId, segmentInfo,true);
return segmentInfo.iCurrentPosition;
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8cd5753e721a43d49cb651f2c5479bac
timeCreated: 1777005537

Some files were not shown because too many files have changed in this diff Show More