Add background
This commit is contained in:
BIN
Assets/Art/Textures/DivingBackground.png
Normal file
BIN
Assets/Art/Textures/DivingBackground.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
195
Assets/Art/Textures/DivingBackground.png.meta
Normal file
195
Assets/Art/Textures/DivingBackground.png.meta
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ad9b785acb09cb247ae2c8cd895863de
|
||||||
|
TextureImporter:
|
||||||
|
internalIDToNameTable:
|
||||||
|
- first:
|
||||||
|
213: 5958968447627082961
|
||||||
|
second: DivingBackground_0
|
||||||
|
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: 1
|
||||||
|
nPOTScale: 0
|
||||||
|
lightmap: 0
|
||||||
|
compressionQuality: 50
|
||||||
|
spriteMode: 2
|
||||||
|
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: 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
|
||||||
|
- 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: 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: WebGL
|
||||||
|
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: WindowsStoreApps
|
||||||
|
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:
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: DivingBackground_0
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 1080
|
||||||
|
height: 1981
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0, y: 0}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
customData:
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: -1
|
||||||
|
bones: []
|
||||||
|
spriteID: 1dcb29c2b3282b250800000000000000
|
||||||
|
internalID: 5958968447627082961
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
outline: []
|
||||||
|
customData:
|
||||||
|
physicsShape: []
|
||||||
|
bones: []
|
||||||
|
spriteID:
|
||||||
|
internalID: 0
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
secondaryTextures: []
|
||||||
|
spriteCustomMetadata:
|
||||||
|
entries: []
|
||||||
|
nameFileIdTable:
|
||||||
|
DivingBackground_0: 5958968447627082961
|
||||||
|
mipmapLimitGroupName:
|
||||||
|
pSDRemoveMatte: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -436,12 +436,10 @@ MonoBehaviour:
|
|||||||
ropeFollowSpeed: 5
|
ropeFollowSpeed: 5
|
||||||
ropeTrailing: 0.2
|
ropeTrailing: 0.2
|
||||||
ropeGravityStrength: 9.8
|
ropeGravityStrength: 9.8
|
||||||
ropeMaxHangDistance: 2
|
|
||||||
ropeVerticalHangStrength: 2
|
ropeVerticalHangStrength: 2
|
||||||
ropeOscillationAmplitude: 0.15
|
|
||||||
ropeOscillationFrequency: 2
|
|
||||||
ropeDamping: 0.3
|
ropeDamping: 0.3
|
||||||
initialSeparationDistance: 0.1
|
initialSeparationDistance: 0.1
|
||||||
|
initialFallImpulse: 2
|
||||||
--- !u!1 &224729330
|
--- !u!1 &224729330
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -644,6 +642,93 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!1 &461301695
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 461301697}
|
||||||
|
- component: {fileID: 461301696}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: DivingBackground_0
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!212 &461301696
|
||||||
|
SpriteRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 461301695}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_CastShadows: 0
|
||||||
|
m_ReceiveShadows: 0
|
||||||
|
m_DynamicOccludee: 1
|
||||||
|
m_StaticShadowCaster: 0
|
||||||
|
m_MotionVectors: 1
|
||||||
|
m_LightProbeUsage: 1
|
||||||
|
m_ReflectionProbeUsage: 1
|
||||||
|
m_RayTracingMode: 0
|
||||||
|
m_RayTraceProcedural: 0
|
||||||
|
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||||
|
m_RayTracingAccelStructBuildFlags: 1
|
||||||
|
m_SmallMeshCulling: 1
|
||||||
|
m_RenderingLayerMask: 1
|
||||||
|
m_RendererPriority: 0
|
||||||
|
m_Materials:
|
||||||
|
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
|
||||||
|
m_StaticBatchInfo:
|
||||||
|
firstSubMesh: 0
|
||||||
|
subMeshCount: 0
|
||||||
|
m_StaticBatchRoot: {fileID: 0}
|
||||||
|
m_ProbeAnchor: {fileID: 0}
|
||||||
|
m_LightProbeVolumeOverride: {fileID: 0}
|
||||||
|
m_ScaleInLightmap: 1
|
||||||
|
m_ReceiveGI: 1
|
||||||
|
m_PreserveUVs: 0
|
||||||
|
m_IgnoreNormalsForChartDetection: 0
|
||||||
|
m_ImportantGI: 0
|
||||||
|
m_StitchLightmapSeams: 1
|
||||||
|
m_SelectedEditorRenderState: 0
|
||||||
|
m_MinimumChartSize: 4
|
||||||
|
m_AutoUVMaxDistance: 0.5
|
||||||
|
m_AutoUVMaxAngle: 89
|
||||||
|
m_LightmapParameters: {fileID: 0}
|
||||||
|
m_SortingLayerID: 622133659
|
||||||
|
m_SortingLayer: -1
|
||||||
|
m_SortingOrder: 0
|
||||||
|
m_Sprite: {fileID: 5958968447627082961, guid: ad9b785acb09cb247ae2c8cd895863de, type: 3}
|
||||||
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_FlipX: 0
|
||||||
|
m_FlipY: 0
|
||||||
|
m_DrawMode: 0
|
||||||
|
m_Size: {x: 10.803711, y: 19.81}
|
||||||
|
m_AdaptiveModeThreshold: 0.5
|
||||||
|
m_SpriteTileMode: 0
|
||||||
|
m_WasSpriteAssigned: 1
|
||||||
|
m_MaskInteraction: 0
|
||||||
|
m_SpriteSortPoint: 0
|
||||||
|
--- !u!4 &461301697
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 461301695}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 1.12, z: 0}
|
||||||
|
m_LocalScale: {x: 0.81438, y: 0.81438, z: 0.81438}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1 &730962732
|
--- !u!1 &730962732
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1319,12 +1404,10 @@ MonoBehaviour:
|
|||||||
ropeFollowSpeed: 5
|
ropeFollowSpeed: 5
|
||||||
ropeTrailing: 0.2
|
ropeTrailing: 0.2
|
||||||
ropeGravityStrength: 9.8
|
ropeGravityStrength: 9.8
|
||||||
ropeMaxHangDistance: 2
|
|
||||||
ropeVerticalHangStrength: 2
|
ropeVerticalHangStrength: 2
|
||||||
ropeOscillationAmplitude: 0.15
|
|
||||||
ropeOscillationFrequency: 2
|
|
||||||
ropeDamping: 0.3
|
ropeDamping: 0.3
|
||||||
initialSeparationDistance: 0.1
|
initialSeparationDistance: 0.1
|
||||||
|
initialFallImpulse: 2
|
||||||
--- !u!1 &1063641111
|
--- !u!1 &1063641111
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1337,6 +1420,7 @@ GameObject:
|
|||||||
- component: {fileID: 1063641113}
|
- component: {fileID: 1063641113}
|
||||||
- component: {fileID: 1063641112}
|
- component: {fileID: 1063641112}
|
||||||
- component: {fileID: 1063641115}
|
- component: {fileID: 1063641115}
|
||||||
|
- component: {fileID: 1063641116}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Main Camera
|
m_Name: Main Camera
|
||||||
m_TagString: MainCamera
|
m_TagString: MainCamera
|
||||||
@@ -1361,8 +1445,8 @@ Camera:
|
|||||||
m_GameObject: {fileID: 1063641111}
|
m_GameObject: {fileID: 1063641111}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_ClearFlags: 1
|
m_ClearFlags: 2
|
||||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
m_BackGroundColor: {r: 0.5722232, g: 0.6321867, b: 0.7264151, a: 0}
|
||||||
m_projectionMatrixMode: 1
|
m_projectionMatrixMode: 1
|
||||||
m_GateFitMode: 2
|
m_GateFitMode: 2
|
||||||
m_FOVAxisMode: 0
|
m_FOVAxisMode: 0
|
||||||
@@ -1450,6 +1534,50 @@ MonoBehaviour:
|
|||||||
m_PostInfinity: 2
|
m_PostInfinity: 2
|
||||||
m_RotationOrder: 4
|
m_RotationOrder: 4
|
||||||
CustomBlends: {fileID: 0}
|
CustomBlends: {fileID: 0}
|
||||||
|
--- !u!114 &1063641116
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1063641111}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_RenderShadows: 1
|
||||||
|
m_RequiresDepthTextureOption: 2
|
||||||
|
m_RequiresOpaqueTextureOption: 2
|
||||||
|
m_CameraType: 0
|
||||||
|
m_Cameras: []
|
||||||
|
m_RendererIndex: -1
|
||||||
|
m_VolumeLayerMask:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 1
|
||||||
|
m_VolumeTrigger: {fileID: 0}
|
||||||
|
m_VolumeFrameworkUpdateModeOption: 2
|
||||||
|
m_RenderPostProcessing: 0
|
||||||
|
m_Antialiasing: 0
|
||||||
|
m_AntialiasingQuality: 2
|
||||||
|
m_StopNaN: 0
|
||||||
|
m_Dithering: 0
|
||||||
|
m_ClearDepth: 1
|
||||||
|
m_AllowXRRendering: 1
|
||||||
|
m_AllowHDROutput: 1
|
||||||
|
m_UseScreenCoordOverride: 0
|
||||||
|
m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_RequiresDepthTexture: 0
|
||||||
|
m_RequiresColorTexture: 0
|
||||||
|
m_Version: 2
|
||||||
|
m_TaaSettings:
|
||||||
|
m_Quality: 3
|
||||||
|
m_FrameInfluence: 0.1
|
||||||
|
m_JitterScale: 1
|
||||||
|
m_MipBias: 0
|
||||||
|
m_VarianceClampScale: 0.9
|
||||||
|
m_ContrastAdaptiveSharpening: 0
|
||||||
--- !u!1 &1224833348
|
--- !u!1 &1224833348
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1816,12 +1944,10 @@ MonoBehaviour:
|
|||||||
ropeFollowSpeed: 5
|
ropeFollowSpeed: 5
|
||||||
ropeTrailing: 0.2
|
ropeTrailing: 0.2
|
||||||
ropeGravityStrength: 9.8
|
ropeGravityStrength: 9.8
|
||||||
ropeMaxHangDistance: 2
|
|
||||||
ropeVerticalHangStrength: 2
|
ropeVerticalHangStrength: 2
|
||||||
ropeOscillationAmplitude: 0.1
|
|
||||||
ropeOscillationFrequency: 3
|
|
||||||
ropeDamping: 0.3
|
ropeDamping: 0.3
|
||||||
initialSeparationDistance: 0.1
|
initialSeparationDistance: 0.1
|
||||||
|
initialFallImpulse: 2
|
||||||
--- !u!1 &1679185997
|
--- !u!1 &1679185997
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -2128,3 +2254,4 @@ SceneRoots:
|
|||||||
- {fileID: 116234201}
|
- {fileID: 116234201}
|
||||||
- {fileID: 824396217}
|
- {fileID: 824396217}
|
||||||
- {fileID: 323864665}
|
- {fileID: 323864665}
|
||||||
|
- {fileID: 461301697}
|
||||||
|
|||||||
@@ -41,9 +41,6 @@ public class RopeBreaker : MonoBehaviour
|
|||||||
[Tooltip("Initial downward impulse for falling rope end")]
|
[Tooltip("Initial downward impulse for falling rope end")]
|
||||||
[SerializeField] private float initialFallImpulse = 2.0f;
|
[SerializeField] private float initialFallImpulse = 2.0f;
|
||||||
|
|
||||||
[Tooltip("Force Y position reset on start to ensure proper falling")]
|
|
||||||
[SerializeField] private bool forceYReset = true;
|
|
||||||
|
|
||||||
// Private references
|
// Private references
|
||||||
private Rope originalRope;
|
private Rope originalRope;
|
||||||
private LineRenderer originalLineRenderer;
|
private LineRenderer originalLineRenderer;
|
||||||
@@ -122,10 +119,9 @@ public class RopeBreaker : MonoBehaviour
|
|||||||
|
|
||||||
// Set specific transform to follow instead of using tag
|
// Set specific transform to follow instead of using tag
|
||||||
follower.SetTargetTransform(originalStartPoint);
|
follower.SetTargetTransform(originalStartPoint);
|
||||||
|
follower.canFall = false; // Player rope end doesn't fall
|
||||||
follower.followSpeed = ropeFollowSpeed;
|
follower.followSpeed = ropeFollowSpeed;
|
||||||
follower.trailing = ropeTrailing;
|
follower.trailing = ropeTrailing;
|
||||||
follower.useGravity = true; // Player rope end doesn't use gravity
|
|
||||||
|
|
||||||
// Create second break point (for the rock-attached end)
|
// Create second break point (for the rock-attached end)
|
||||||
GameObject secondBreakObj = new GameObject("RopeBreakPoint_Second");
|
GameObject secondBreakObj = new GameObject("RopeBreakPoint_Second");
|
||||||
@@ -138,15 +134,13 @@ public class RopeBreaker : MonoBehaviour
|
|||||||
|
|
||||||
// Set specific transform to follow instead of using tag
|
// Set specific transform to follow instead of using tag
|
||||||
secondFollower.SetTargetTransform(originalEndPoint);
|
secondFollower.SetTargetTransform(originalEndPoint);
|
||||||
|
secondFollower.canFall = true; // Rock end can fall
|
||||||
secondFollower.followSpeed = ropeFollowSpeed;
|
secondFollower.followSpeed = ropeFollowSpeed;
|
||||||
secondFollower.trailing = ropeTrailing;
|
secondFollower.trailing = ropeTrailing;
|
||||||
secondFollower.useGravity = true; // Enable gravity for hanging rope end
|
|
||||||
secondFollower.gravityStrength = ropeGravityStrength;
|
secondFollower.gravityStrength = ropeGravityStrength;
|
||||||
secondFollower.verticalHangStrength = ropeVerticalHangStrength;
|
secondFollower.verticalHangStrength = ropeVerticalHangStrength;
|
||||||
secondFollower.damping = ropeDamping;
|
secondFollower.damping = ropeDamping;
|
||||||
secondFollower.initialFallImpulse = initialFallImpulse;
|
secondFollower.initialFallImpulse = initialFallImpulse;
|
||||||
secondFollower.forceYReset = forceYReset;
|
|
||||||
|
|
||||||
// Create initial separation
|
// Create initial separation
|
||||||
Vector3 direction = (originalEndPoint.position - breakPointPosition).normalized;
|
Vector3 direction = (originalEndPoint.position - breakPointPosition).normalized;
|
||||||
|
|||||||
@@ -4,32 +4,29 @@ using UnityEngine;
|
|||||||
public class RopeEndPhysicsFollower : MonoBehaviour
|
public class RopeEndPhysicsFollower : MonoBehaviour
|
||||||
{
|
{
|
||||||
[Header("Target Settings")]
|
[Header("Target Settings")]
|
||||||
[Tooltip("Tag of the object this endpoint should follow (used if targetTransform is not set)")]
|
[Tooltip("Transform this endpoint should follow")]
|
||||||
public string targetTag;
|
|
||||||
[Tooltip("Transform this endpoint should follow (takes precedence over targetTag)")]
|
|
||||||
public Transform targetTransform;
|
public Transform targetTransform;
|
||||||
[Tooltip("How quickly the endpoint follows the target")]
|
[Tooltip("Tag of the object this endpoint should follow (only used if targetTransform is not set)")]
|
||||||
|
public string targetTag;
|
||||||
|
[Tooltip("How quickly the endpoint follows the target when not using physics")]
|
||||||
public float followSpeed = 5f;
|
public float followSpeed = 5f;
|
||||||
[Tooltip("How much trailing (0 = instant, 1 = very slow)")]
|
[Tooltip("How much trailing (0 = instant, 1 = very slow)")]
|
||||||
public float trailing = 0.2f;
|
public float trailing = 0.2f;
|
||||||
|
|
||||||
[Header("Physics Simulation")]
|
[Header("Physics Simulation")]
|
||||||
[Tooltip("Enable/disable gravity effect")]
|
|
||||||
public bool useGravity = true;
|
|
||||||
[Tooltip("Gravity strength")]
|
[Tooltip("Gravity strength")]
|
||||||
public float gravityStrength = 9.8f;
|
public float gravityStrength = 9.8f;
|
||||||
[Tooltip("How strongly the rope attempts to hang vertically")]
|
[Tooltip("How strongly the rope attempts to hang vertically")]
|
||||||
public float verticalHangStrength = 2f;
|
public float verticalHangStrength = 2f;
|
||||||
[Tooltip("Damping for physics movement (higher = less bouncy)")]
|
[Tooltip("Damping for physics movement (higher = less bouncy)")]
|
||||||
public float damping = 0.3f;
|
public float damping = 0.3f;
|
||||||
[Tooltip("Initial downward impulse when gravity is enabled")]
|
[Tooltip("Initial downward impulse when enabled")]
|
||||||
public float initialFallImpulse = 2.0f;
|
public float initialFallImpulse = 2.0f;
|
||||||
[Tooltip("Force a Y position reset on start to ensure falling occurs")]
|
[Tooltip("Whether this end can fall with gravity (false for player-attached ends)")]
|
||||||
public bool forceYReset = true;
|
public bool canFall = true;
|
||||||
|
|
||||||
// Private variables
|
// Private variables
|
||||||
private Transform target;
|
private Transform target;
|
||||||
private Vector3 velocity;
|
|
||||||
private Vector2 physicsVelocity;
|
private Vector2 physicsVelocity;
|
||||||
private Vector2 offset;
|
private Vector2 offset;
|
||||||
private Vector3 lastTargetPosition;
|
private Vector3 lastTargetPosition;
|
||||||
@@ -41,6 +38,162 @@ public class RopeEndPhysicsFollower : MonoBehaviour
|
|||||||
private float maxDistance;
|
private float maxDistance;
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
|
{
|
||||||
|
// Find the Rope component to determine the maximum distance
|
||||||
|
FindAttachedRope();
|
||||||
|
|
||||||
|
// Use targetTransform if set, otherwise try to find by tag
|
||||||
|
if (targetTransform != null)
|
||||||
|
{
|
||||||
|
target = targetTransform;
|
||||||
|
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Using assigned target transform: {target.name}");
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(targetTag))
|
||||||
|
{
|
||||||
|
GameObject found = GameObject.FindGameObjectWithTag(targetTag);
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
target = found.transform;
|
||||||
|
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Found target by tag '{targetTag}': {target.name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize offset and velocities
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
// Only store horizontal offset, not vertical for physics simulation
|
||||||
|
Vector2 offsetVec = transform.position - target.position;
|
||||||
|
offset.x = offsetVec.x;
|
||||||
|
offset.y = 0; // Don't preserve vertical offset for gravity simulation
|
||||||
|
lastTargetPosition = target.position;
|
||||||
|
|
||||||
|
// Apply initial falling impulse if this end can fall
|
||||||
|
if (canFall)
|
||||||
|
{
|
||||||
|
physicsVelocity = new Vector2(0, -initialFallImpulse);
|
||||||
|
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Initialized with target: {target.name}, initial Y velocity: {physicsVelocity.y}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset = Vector2.zero;
|
||||||
|
lastTargetPosition = transform.position;
|
||||||
|
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] No target found");
|
||||||
|
}
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (!target) return;
|
||||||
|
|
||||||
|
// Calculate deltaTime for physics stability
|
||||||
|
float deltaTime = Time.deltaTime;
|
||||||
|
|
||||||
|
// Get target velocity
|
||||||
|
Vector3 targetVelocity = (target.position - lastTargetPosition) / deltaTime;
|
||||||
|
lastTargetPosition = target.position;
|
||||||
|
|
||||||
|
// Current position relative to target
|
||||||
|
Vector2 relativePos = new Vector2(
|
||||||
|
transform.position.x - target.position.x,
|
||||||
|
transform.position.y - target.position.y
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get the straight-line distance between target and this transform
|
||||||
|
float currentDistance = relativePos.magnitude;
|
||||||
|
|
||||||
|
// Normalized direction from target to this transform
|
||||||
|
Vector2 directionToTarget = relativePos.normalized;
|
||||||
|
|
||||||
|
// Apply forces based on whether this end can fall
|
||||||
|
if (canFall)
|
||||||
|
{
|
||||||
|
// 1. Gravity - always pulls down
|
||||||
|
physicsVelocity.y -= gravityStrength * deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Vertical hanging force - try to align X with target when stationary
|
||||||
|
if (Mathf.Abs(targetVelocity.x) < 0.1f)
|
||||||
|
{
|
||||||
|
// Use the actual X position of the target as the desired X position
|
||||||
|
float xOffset = transform.position.x - target.position.x;
|
||||||
|
physicsVelocity.x -= xOffset * verticalHangStrength * deltaTime;
|
||||||
|
|
||||||
|
// Debug log to track vertical hanging behavior
|
||||||
|
if (debugLog && Time.frameCount % 120 == 0)
|
||||||
|
{
|
||||||
|
Debug.Log($"[RopeEndPhysicsFollower] Vertical hanging: target X={target.position.x}, my X={transform.position.x}, offset={xOffset}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Rope length constraint - apply a force toward the target if we're exceeding the rope length
|
||||||
|
if (currentDistance > maxDistance)
|
||||||
|
{
|
||||||
|
// Calculate constraint force proportional to how much we're exceeding the rope length
|
||||||
|
float exceededDistance = currentDistance - maxDistance;
|
||||||
|
|
||||||
|
// Apply a stronger constraint force the more we exceed the max distance
|
||||||
|
Vector2 constraintForce = -directionToTarget * exceededDistance * 10f;
|
||||||
|
|
||||||
|
// Apply to velocity
|
||||||
|
physicsVelocity += constraintForce * deltaTime;
|
||||||
|
|
||||||
|
if (debugLog && Time.frameCount % 60 == 0)
|
||||||
|
{
|
||||||
|
Debug.Log($"[RopeEndPhysicsFollower] Exceeding max distance: {exceededDistance}, applying constraint");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply damping to physics velocity
|
||||||
|
physicsVelocity *= (1f - damping * deltaTime);
|
||||||
|
|
||||||
|
// Log physics state periodically for debugging
|
||||||
|
if (debugLog && Time.frameCount % 60 == 0)
|
||||||
|
{
|
||||||
|
Debug.Log($"[RopeEndPhysicsFollower] Y position: {transform.position.y}, Y velocity: {physicsVelocity.y}, Distance: {currentDistance}/{maxDistance}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply physics velocity to position
|
||||||
|
Vector3 newPos = transform.position;
|
||||||
|
newPos.x += physicsVelocity.x * deltaTime;
|
||||||
|
|
||||||
|
// Only apply vertical movement if this end can fall
|
||||||
|
if (canFall)
|
||||||
|
{
|
||||||
|
newPos.y += physicsVelocity.y * deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform.position = newPos;
|
||||||
|
|
||||||
|
// Final distance check - hard constraint to ensure we never exceed the rope length
|
||||||
|
// This prevents numerical instability from causing the rope to stretch
|
||||||
|
float finalDistance = Vector2.Distance(
|
||||||
|
new Vector2(transform.position.x, transform.position.y),
|
||||||
|
new Vector2(target.position.x, target.position.y)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (finalDistance > maxDistance)
|
||||||
|
{
|
||||||
|
// Calculate the direction from target to this transform
|
||||||
|
Vector2 direction = new Vector2(
|
||||||
|
transform.position.x - target.position.x,
|
||||||
|
transform.position.y - target.position.y
|
||||||
|
).normalized;
|
||||||
|
|
||||||
|
// Set position to be exactly at the maximum distance
|
||||||
|
Vector3 constrainedPos = new Vector3(
|
||||||
|
target.position.x + direction.x * maxDistance,
|
||||||
|
target.position.y + direction.y * maxDistance,
|
||||||
|
transform.position.z
|
||||||
|
);
|
||||||
|
|
||||||
|
transform.position = constrainedPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FindAttachedRope()
|
||||||
{
|
{
|
||||||
// Find the Rope component on the same GameObject or parent
|
// Find the Rope component on the same GameObject or parent
|
||||||
attachedRope = GetComponent<Rope>();
|
attachedRope = GetComponent<Rope>();
|
||||||
@@ -82,172 +235,6 @@ public class RopeEndPhysicsFollower : MonoBehaviour
|
|||||||
maxDistance = 2f;
|
maxDistance = 2f;
|
||||||
if (debugLog) Debug.Log("[RopeEndPhysicsFollower] No attached rope found, using default max distance");
|
if (debugLog) Debug.Log("[RopeEndPhysicsFollower] No attached rope found, using default max distance");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use targetTransform if set, otherwise try to find by tag
|
|
||||||
if (targetTransform != null)
|
|
||||||
{
|
|
||||||
target = targetTransform;
|
|
||||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Using assigned target transform: {target.name}");
|
|
||||||
}
|
|
||||||
else if (!string.IsNullOrEmpty(targetTag))
|
|
||||||
{
|
|
||||||
GameObject found = GameObject.FindGameObjectWithTag(targetTag);
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
target = found.transform;
|
|
||||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Found target by tag '{targetTag}': {target.name}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize offset and velocities
|
|
||||||
if (target)
|
|
||||||
{
|
|
||||||
// Only store horizontal offset, not vertical
|
|
||||||
Vector2 offsetVec = transform.position - target.position;
|
|
||||||
offset.x = offsetVec.x;
|
|
||||||
offset.y = 0; // Don't preserve vertical offset for gravity simulation
|
|
||||||
lastTargetPosition = target.position;
|
|
||||||
|
|
||||||
// Apply initial falling impulse if using gravity
|
|
||||||
if (useGravity)
|
|
||||||
{
|
|
||||||
physicsVelocity = new Vector2(0, -initialFallImpulse);
|
|
||||||
|
|
||||||
// Force an initial position change to ensure things start moving
|
|
||||||
if (forceYReset)
|
|
||||||
{
|
|
||||||
Vector3 pos = transform.position;
|
|
||||||
pos.y = target.position.y; // Reset to target's Y position
|
|
||||||
transform.position = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Initialized with target: {target.name}, gravity enabled, initial Y velocity: {physicsVelocity.y}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offset = Vector2.zero;
|
|
||||||
lastTargetPosition = transform.position;
|
|
||||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] No target found");
|
|
||||||
}
|
|
||||||
|
|
||||||
velocity = Vector3.zero;
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
if (!target) return;
|
|
||||||
|
|
||||||
// Calculate deltaTime for physics stability
|
|
||||||
float deltaTime = Time.deltaTime;
|
|
||||||
|
|
||||||
// Get target velocity
|
|
||||||
Vector3 targetVelocity = (target.position - lastTargetPosition) / deltaTime;
|
|
||||||
lastTargetPosition = target.position;
|
|
||||||
|
|
||||||
// Basic position the endpoint should be at based on target position and horizontal offset
|
|
||||||
Vector3 basePosition = target.position + new Vector3(offset.x, 0, 0);
|
|
||||||
|
|
||||||
// Apply physics simulation if enabled
|
|
||||||
if (useGravity)
|
|
||||||
{
|
|
||||||
// Get the straight-line distance between target and this transform
|
|
||||||
float currentDistance = Vector2.Distance(
|
|
||||||
new Vector2(transform.position.x, transform.position.y),
|
|
||||||
new Vector2(target.position.x, target.position.y)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Current position relative to target
|
|
||||||
Vector2 relativePos = new Vector2(
|
|
||||||
transform.position.x - target.position.x,
|
|
||||||
transform.position.y - target.position.y
|
|
||||||
);
|
|
||||||
|
|
||||||
// Normalized direction from target to this transform
|
|
||||||
Vector2 directionToTarget = relativePos.normalized;
|
|
||||||
|
|
||||||
// Apply forces:
|
|
||||||
// 1. Gravity - always pulls down
|
|
||||||
physicsVelocity.y -= gravityStrength * deltaTime;
|
|
||||||
|
|
||||||
// 2. Vertical hanging force - try to align X with target (not with world origin)
|
|
||||||
if (Mathf.Abs(targetVelocity.x) < 0.1f)
|
|
||||||
{
|
|
||||||
// Use the actual X position of the target as the desired X position
|
|
||||||
float xOffset = transform.position.x - target.position.x;
|
|
||||||
physicsVelocity.x -= xOffset * verticalHangStrength * deltaTime;
|
|
||||||
|
|
||||||
// Debug log to track vertical hanging behavior
|
|
||||||
if (debugLog && Time.frameCount % 120 == 0)
|
|
||||||
{
|
|
||||||
Debug.Log($"[RopeEndPhysicsFollower] Vertical hanging: target X={target.position.x}, my X={transform.position.x}, offset={xOffset}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Rope length constraint - apply a force toward the target if we're exceeding the rope length
|
|
||||||
if (currentDistance > maxDistance)
|
|
||||||
{
|
|
||||||
// Calculate constraint force proportional to how much we're exceeding the rope length
|
|
||||||
float exceededDistance = currentDistance - maxDistance;
|
|
||||||
|
|
||||||
// Apply a stronger constraint force the more we exceed the max distance
|
|
||||||
Vector2 constraintForce = -directionToTarget * exceededDistance * 10f;
|
|
||||||
|
|
||||||
// Apply to velocity
|
|
||||||
physicsVelocity += constraintForce * deltaTime;
|
|
||||||
|
|
||||||
if (debugLog && Time.frameCount % 60 == 0)
|
|
||||||
{
|
|
||||||
Debug.Log($"[RopeEndPhysicsFollower] Exceeding max distance: {exceededDistance}, applying constraint");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply damping to physics velocity
|
|
||||||
physicsVelocity *= (1f - damping * deltaTime);
|
|
||||||
|
|
||||||
// Log physics state periodically for debugging
|
|
||||||
if (debugLog && Time.frameCount % 60 == 0)
|
|
||||||
{
|
|
||||||
Debug.Log($"[RopeEndPhysicsFollower] Y position: {transform.position.y}, Y velocity: {physicsVelocity.y}, Distance: {currentDistance}/{maxDistance}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply physics velocity to position
|
|
||||||
Vector3 newPos = transform.position;
|
|
||||||
newPos.x += physicsVelocity.x * deltaTime;
|
|
||||||
newPos.y += physicsVelocity.y * deltaTime;
|
|
||||||
transform.position = newPos;
|
|
||||||
|
|
||||||
// Final distance check - hard constraint to ensure we never exceed the rope length
|
|
||||||
// This prevents numerical instability from causing the rope to stretch
|
|
||||||
float finalDistance = Vector2.Distance(
|
|
||||||
new Vector2(transform.position.x, transform.position.y),
|
|
||||||
new Vector2(target.position.x, target.position.y)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (finalDistance > maxDistance)
|
|
||||||
{
|
|
||||||
// Calculate the direction from target to this transform
|
|
||||||
Vector2 direction = new Vector2(
|
|
||||||
transform.position.x - target.position.x,
|
|
||||||
transform.position.y - target.position.y
|
|
||||||
).normalized;
|
|
||||||
|
|
||||||
// Set position to be exactly at the maximum distance
|
|
||||||
Vector3 constrainedPos = new Vector3(
|
|
||||||
target.position.x + direction.x * maxDistance,
|
|
||||||
target.position.y + direction.y * maxDistance,
|
|
||||||
transform.position.z
|
|
||||||
);
|
|
||||||
|
|
||||||
transform.position = constrainedPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Original smooth follow behavior without physics
|
|
||||||
transform.position = Vector3.SmoothDamp(transform.position, basePosition, ref velocity, trailing, followSpeed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTargetTransform(Transform newTarget)
|
public void SetTargetTransform(Transform newTarget)
|
||||||
@@ -273,8 +260,8 @@ public class RopeEndPhysicsFollower : MonoBehaviour
|
|||||||
offset.y = 0; // Don't preserve vertical offset for gravity simulation
|
offset.y = 0; // Don't preserve vertical offset for gravity simulation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply initial falling impulse if using gravity
|
// Apply initial falling impulse if this end can fall
|
||||||
if (useGravity)
|
if (canFall)
|
||||||
{
|
{
|
||||||
physicsVelocity = new Vector2(physicsVelocity.x, -initialFallImpulse);
|
physicsVelocity = new Vector2(physicsVelocity.x, -initialFallImpulse);
|
||||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Reset Y velocity to {physicsVelocity.y} after target change to {target.name}");
|
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Reset Y velocity to {physicsVelocity.y} after target change to {target.name}");
|
||||||
@@ -289,30 +276,7 @@ public class RopeEndPhysicsFollower : MonoBehaviour
|
|||||||
GameObject found = GameObject.FindGameObjectWithTag(targetTag);
|
GameObject found = GameObject.FindGameObjectWithTag(targetTag);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
targetTransform = found.transform;
|
SetTargetTransform(found.transform);
|
||||||
target = found.transform;
|
|
||||||
lastTargetPosition = target.position;
|
|
||||||
|
|
||||||
// Only update horizontal offset to maintain current vertical position
|
|
||||||
if (initialized)
|
|
||||||
{
|
|
||||||
Vector2 newOffset = transform.position - target.position;
|
|
||||||
offset.x = newOffset.x;
|
|
||||||
// Don't update offset.y to allow gravity to work
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Vector2 newOffset = transform.position - target.position;
|
|
||||||
offset.x = newOffset.x;
|
|
||||||
offset.y = 0; // Don't preserve vertical offset for gravity simulation
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply initial falling impulse if using gravity
|
|
||||||
if (useGravity)
|
|
||||||
{
|
|
||||||
physicsVelocity = new Vector2(physicsVelocity.x, -initialFallImpulse);
|
|
||||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Reset Y velocity to {physicsVelocity.y} after target change");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user