Ropes breaking and shit
This commit is contained in:
3
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef
vendored
Normal file
3
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"name": "OptimizedRope"
|
||||||
|
}
|
||||||
7
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef.meta
vendored
Normal file
7
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef.meta
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f7c43f01316c63c43a8b70a1dd6bdfac
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -75,8 +75,20 @@ namespace GogoGaga.OptimizedRopesAndCables
|
|||||||
|
|
||||||
public bool IsPrefab => gameObject.scene.rootCount == 0;
|
public bool IsPrefab => gameObject.scene.rootCount == 0;
|
||||||
|
|
||||||
private void Start()
|
// Track initialization state
|
||||||
|
private bool isInitialized = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Public method to explicitly initialize the rope.
|
||||||
|
/// Call this after setting up endpoints if creating ropes at runtime.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if initialization was successful, false otherwise</returns>
|
||||||
|
public bool Initialize()
|
||||||
{
|
{
|
||||||
|
// Skip if already initialized
|
||||||
|
if (isInitialized)
|
||||||
|
return true;
|
||||||
|
|
||||||
InitializeLineRenderer();
|
InitializeLineRenderer();
|
||||||
if (AreEndPointsValid())
|
if (AreEndPointsValid())
|
||||||
{
|
{
|
||||||
@@ -84,7 +96,17 @@ namespace GogoGaga.OptimizedRopesAndCables
|
|||||||
targetValue = currentValue;
|
targetValue = currentValue;
|
||||||
currentVelocity = Vector3.zero;
|
currentVelocity = Vector3.zero;
|
||||||
SetSplinePoint(); // Ensure initial spline point is set correctly
|
SetSplinePoint(); // Ensure initial spline point is set correctly
|
||||||
|
isInitialized = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
// Use the same initialization method to avoid code duplication
|
||||||
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnValidate()
|
private void OnValidate()
|
||||||
@@ -208,15 +230,62 @@ namespace GogoGaga.OptimizedRopesAndCables
|
|||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 GetPointAt(float t)
|
/// <summary>
|
||||||
|
/// Set the start point of the rope
|
||||||
|
/// </summary>
|
||||||
|
public void SetStartPoint(Transform newStartPoint, bool recalculateRope = false)
|
||||||
{
|
{
|
||||||
if (!AreEndPointsValid())
|
startPoint = newStartPoint;
|
||||||
{
|
if (recalculateRope)
|
||||||
Debug.LogError("StartPoint or EndPoint is not assigned.", gameObject);
|
RecalculateRope();
|
||||||
return Vector3.zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetRationalBezierPoint(startPoint.position, currentValue, endPoint.position, t, StartPointWeight, midPointWeight, EndPointWeight);
|
/// <summary>
|
||||||
|
/// Set the end point of the rope
|
||||||
|
/// </summary>
|
||||||
|
public void SetEndPoint(Transform newEndPoint, bool recalculateRope = false)
|
||||||
|
{
|
||||||
|
endPoint = newEndPoint;
|
||||||
|
if (recalculateRope)
|
||||||
|
RecalculateRope();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the mid point of the rope
|
||||||
|
/// </summary>
|
||||||
|
public void SetMidPoint(Transform newMidPoint, bool recalculateRope = false)
|
||||||
|
{
|
||||||
|
midPoint = newMidPoint;
|
||||||
|
if (recalculateRope)
|
||||||
|
RecalculateRope();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a point along the rope at the specified position (0-1)
|
||||||
|
/// </summary>
|
||||||
|
public Vector3 GetPointAt(float position)
|
||||||
|
{
|
||||||
|
position = Mathf.Clamp01(position);
|
||||||
|
Vector3 mid = GetMidPoint();
|
||||||
|
return GetRationalBezierPoint(startPoint.position, mid, endPoint.position, position, StartPointWeight, midPointWeight, EndPointWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Force recalculation of the rope
|
||||||
|
/// </summary>
|
||||||
|
public void RecalculateRope()
|
||||||
|
{
|
||||||
|
if (!isInitialized)
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AreEndPointsValid())
|
||||||
|
{
|
||||||
|
SetSplinePoint();
|
||||||
|
SimulatePhysics();
|
||||||
|
NotifyPointsChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FixedUpdate()
|
private void FixedUpdate()
|
||||||
@@ -262,61 +331,6 @@ namespace GogoGaga.OptimizedRopesAndCables
|
|||||||
// Gizmos.DrawSphere(midPos, 0.2f);
|
// Gizmos.DrawSphere(midPos, 0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// New API methods for setting start and end points
|
|
||||||
// with instantAssign parameter to recalculate the rope immediately, without
|
|
||||||
// animating the rope to the new position.
|
|
||||||
// When newStartPoint or newEndPoint is null, the rope will be recalculated immediately
|
|
||||||
|
|
||||||
public void SetStartPoint(Transform newStartPoint, bool instantAssign = false)
|
|
||||||
{
|
|
||||||
startPoint = newStartPoint;
|
|
||||||
prevStartPointPosition = startPoint == null ? Vector3.zero : startPoint.position;
|
|
||||||
|
|
||||||
if (instantAssign || newStartPoint == null)
|
|
||||||
{
|
|
||||||
RecalculateRope();
|
|
||||||
}
|
|
||||||
|
|
||||||
NotifyPointsChanged();
|
|
||||||
}
|
|
||||||
public void SetMidPoint(Transform newMidPoint, bool instantAssign = false)
|
|
||||||
{
|
|
||||||
midPoint = newMidPoint;
|
|
||||||
prevMidPointPosition = midPoint == null ? 0.5f : midPointPosition;
|
|
||||||
|
|
||||||
if (instantAssign || newMidPoint == null)
|
|
||||||
{
|
|
||||||
RecalculateRope();
|
|
||||||
}
|
|
||||||
NotifyPointsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetEndPoint(Transform newEndPoint, bool instantAssign = false)
|
|
||||||
{
|
|
||||||
endPoint = newEndPoint;
|
|
||||||
prevEndPointPosition = endPoint == null ? Vector3.zero : endPoint.position;
|
|
||||||
|
|
||||||
if (instantAssign || newEndPoint == null)
|
|
||||||
{
|
|
||||||
RecalculateRope();
|
|
||||||
}
|
|
||||||
|
|
||||||
NotifyPointsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RecalculateRope()
|
|
||||||
{
|
|
||||||
if (!AreEndPointsValid())
|
|
||||||
{
|
|
||||||
lineRenderer.positionCount = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentValue = GetMidPoint();
|
|
||||||
targetValue = currentValue;
|
|
||||||
currentVelocity = Vector3.zero;
|
|
||||||
SetSplinePoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NotifyPointsChanged()
|
private void NotifyPointsChanged()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -248,6 +248,7 @@ GameObject:
|
|||||||
- component: {fileID: 173052725}
|
- component: {fileID: 173052725}
|
||||||
- component: {fileID: 173052727}
|
- component: {fileID: 173052727}
|
||||||
- component: {fileID: 173052726}
|
- component: {fileID: 173052726}
|
||||||
|
- component: {fileID: 173052728}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Rope2
|
m_Name: Rope2
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -417,6 +418,27 @@ LineRenderer:
|
|||||||
m_UseWorldSpace: 1
|
m_UseWorldSpace: 1
|
||||||
m_Loop: 0
|
m_Loop: 0
|
||||||
m_ApplyActiveColorSpace: 1
|
m_ApplyActiveColorSpace: 1
|
||||||
|
--- !u!114 &173052728
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 173052724}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 30919200017f4879867c3b6289429924, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
breakPosition: 0.5
|
||||||
|
breakEffect: {fileID: 0}
|
||||||
|
breakSound: {fileID: 0}
|
||||||
|
fallSpeed: 2
|
||||||
|
swingAmount: 0.5
|
||||||
|
ropeFollowSpeed: 5
|
||||||
|
ropeTrailing: 0.2
|
||||||
|
ropeOscillationAmplitude: 0.15
|
||||||
|
ropeOscillationFrequency: 2
|
||||||
--- !u!1 &224729330
|
--- !u!1 &224729330
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -600,6 +622,10 @@ MonoBehaviour:
|
|||||||
spawnCooldown: 5
|
spawnCooldown: 5
|
||||||
basePoints: 10
|
basePoints: 10
|
||||||
depthMultiplier: 2
|
depthMultiplier: 2
|
||||||
|
playerRopes:
|
||||||
|
- {fileID: 1435210811}
|
||||||
|
- {fileID: 1062017697}
|
||||||
|
- {fileID: 173052728}
|
||||||
--- !u!4 &424805726
|
--- !u!4 &424805726
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1102,6 +1128,7 @@ GameObject:
|
|||||||
- component: {fileID: 1062017694}
|
- component: {fileID: 1062017694}
|
||||||
- component: {fileID: 1062017696}
|
- component: {fileID: 1062017696}
|
||||||
- component: {fileID: 1062017695}
|
- component: {fileID: 1062017695}
|
||||||
|
- component: {fileID: 1062017697}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Rope3
|
m_Name: Rope3
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -1271,6 +1298,27 @@ LineRenderer:
|
|||||||
m_UseWorldSpace: 1
|
m_UseWorldSpace: 1
|
||||||
m_Loop: 0
|
m_Loop: 0
|
||||||
m_ApplyActiveColorSpace: 1
|
m_ApplyActiveColorSpace: 1
|
||||||
|
--- !u!114 &1062017697
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1062017693}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 30919200017f4879867c3b6289429924, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
breakPosition: 0.5
|
||||||
|
breakEffect: {fileID: 0}
|
||||||
|
breakSound: {fileID: 0}
|
||||||
|
fallSpeed: 2
|
||||||
|
swingAmount: 0.5
|
||||||
|
ropeFollowSpeed: 5
|
||||||
|
ropeTrailing: 0.2
|
||||||
|
ropeOscillationAmplitude: 0.15
|
||||||
|
ropeOscillationFrequency: 2
|
||||||
--- !u!1 &1063641111
|
--- !u!1 &1063641111
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1744,51 +1792,27 @@ LineRenderer:
|
|||||||
m_UseWorldSpace: 1
|
m_UseWorldSpace: 1
|
||||||
m_Loop: 0
|
m_Loop: 0
|
||||||
m_ApplyActiveColorSpace: 1
|
m_ApplyActiveColorSpace: 1
|
||||||
--- !u!23 &1435210811
|
--- !u!114 &1435210811
|
||||||
MeshRenderer:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 1435210807}
|
m_GameObject: {fileID: 1435210807}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
m_CastShadows: 1
|
m_EditorHideFlags: 0
|
||||||
m_ReceiveShadows: 1
|
m_Script: {fileID: 11500000, guid: 30919200017f4879867c3b6289429924, type: 3}
|
||||||
m_DynamicOccludee: 1
|
m_Name:
|
||||||
m_StaticShadowCaster: 0
|
m_EditorClassIdentifier:
|
||||||
m_MotionVectors: 1
|
breakPosition: 0.5
|
||||||
m_LightProbeUsage: 1
|
breakEffect: {fileID: 0}
|
||||||
m_ReflectionProbeUsage: 1
|
breakSound: {fileID: 0}
|
||||||
m_RayTracingMode: 2
|
fallSpeed: 2
|
||||||
m_RayTraceProcedural: 0
|
swingAmount: 0.5
|
||||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
ropeFollowSpeed: 5
|
||||||
m_RayTracingAccelStructBuildFlags: 1
|
ropeTrailing: 0.2
|
||||||
m_SmallMeshCulling: 1
|
ropeOscillationAmplitude: 0.1
|
||||||
m_RenderingLayerMask: 1
|
ropeOscillationFrequency: 3
|
||||||
m_RendererPriority: 0
|
|
||||||
m_Materials:
|
|
||||||
- {fileID: 0}
|
|
||||||
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: 3
|
|
||||||
m_MinimumChartSize: 4
|
|
||||||
m_AutoUVMaxDistance: 0.5
|
|
||||||
m_AutoUVMaxAngle: 89
|
|
||||||
m_LightmapParameters: {fileID: 0}
|
|
||||||
m_SortingLayerID: 0
|
|
||||||
m_SortingLayer: 0
|
|
||||||
m_SortingOrder: 0
|
|
||||||
m_AdditionalVertexStreams: {fileID: 0}
|
|
||||||
--- !u!1 &1679185997
|
--- !u!1 &1679185997
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
"AstarPathfindingProject",
|
"AstarPathfindingProject",
|
||||||
"Unity.ResourceManager",
|
"Unity.ResourceManager",
|
||||||
"Unity.InputSystem",
|
"Unity.InputSystem",
|
||||||
"Unity.TextMeshPro"
|
"Unity.TextMeshPro",
|
||||||
|
"OptimizedRope"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ namespace Minigames.DivingForPictures
|
|||||||
[Tooltip("Additional points per depth unit")]
|
[Tooltip("Additional points per depth unit")]
|
||||||
[SerializeField] private int depthMultiplier = 10;
|
[SerializeField] private int depthMultiplier = 10;
|
||||||
|
|
||||||
|
[Header("Rope Damage System")]
|
||||||
|
[Tooltip("Ropes that will break one by one as player takes damage")]
|
||||||
|
[SerializeField] private RopeBreaker[] playerRopes;
|
||||||
|
|
||||||
// Private state variables
|
// Private state variables
|
||||||
private int playerScore = 0;
|
private int playerScore = 0;
|
||||||
private float currentSpawnProbability;
|
private float currentSpawnProbability;
|
||||||
@@ -46,6 +50,12 @@ namespace Minigames.DivingForPictures
|
|||||||
public event Action<Monster> OnMonsterSpawned;
|
public event Action<Monster> OnMonsterSpawned;
|
||||||
public event Action<Monster, int> OnPictureTaken;
|
public event Action<Monster, int> OnPictureTaken;
|
||||||
public event Action<float> OnSpawnProbabilityChanged;
|
public event Action<float> OnSpawnProbabilityChanged;
|
||||||
|
public event Action OnGameOver;
|
||||||
|
public event Action<int> OnRopeBroken; // Passes remaining ropes count
|
||||||
|
|
||||||
|
// Private state variables for rope system
|
||||||
|
private int currentRopeIndex = 0;
|
||||||
|
private bool isGameOver = false;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@@ -64,6 +74,18 @@ namespace Minigames.DivingForPictures
|
|||||||
{
|
{
|
||||||
Debug.LogWarning("No TrenchTileSpawner found in scene. Monster spawning won't work.");
|
Debug.LogWarning("No TrenchTileSpawner found in scene. Monster spawning won't work.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subscribe to player damage events
|
||||||
|
PlayerCollisionBehavior.OnDamageTaken += OnPlayerDamageTaken;
|
||||||
|
|
||||||
|
// Validate rope references
|
||||||
|
ValidateRopeReferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
// Unsubscribe from events when the manager is destroyed
|
||||||
|
PlayerCollisionBehavior.OnDamageTaken -= OnPlayerDamageTaken;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
@@ -176,6 +198,127 @@ namespace Minigames.DivingForPictures
|
|||||||
monster.OnMonsterDespawned -= OnMonsterDespawned;
|
monster.OnMonsterDespawned -= OnMonsterDespawned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the player takes damage from any collision
|
||||||
|
/// </summary>
|
||||||
|
private void OnPlayerDamageTaken()
|
||||||
|
{
|
||||||
|
if (isGameOver) return;
|
||||||
|
|
||||||
|
// Break the next rope in sequence
|
||||||
|
BreakNextRope();
|
||||||
|
|
||||||
|
// Check if all ropes are broken
|
||||||
|
if (currentRopeIndex >= playerRopes.Length)
|
||||||
|
{
|
||||||
|
TriggerGameOver();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Notify listeners about rope break and remaining ropes
|
||||||
|
int remainingRopes = playerRopes.Length - currentRopeIndex;
|
||||||
|
OnRopeBroken?.Invoke(remainingRopes);
|
||||||
|
|
||||||
|
Debug.Log($"[DivingGameManager] Rope broken! {remainingRopes} ropes remaining.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Breaks the next available rope in the sequence
|
||||||
|
/// </summary>
|
||||||
|
private void BreakNextRope()
|
||||||
|
{
|
||||||
|
if (currentRopeIndex < playerRopes.Length)
|
||||||
|
{
|
||||||
|
RopeBreaker ropeToBreak = playerRopes[currentRopeIndex];
|
||||||
|
|
||||||
|
if (ropeToBreak != null)
|
||||||
|
{
|
||||||
|
// Let the RopeBreaker component handle the breaking, effects, and sounds
|
||||||
|
ropeToBreak.BreakRope();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[DivingGameManager] Rope at index {currentRopeIndex} is null!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to the next rope regardless if current was null
|
||||||
|
currentRopeIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manually break a rope (for testing or external events)
|
||||||
|
/// </summary>
|
||||||
|
public void ForceBreakRope()
|
||||||
|
{
|
||||||
|
if (!isGameOver)
|
||||||
|
{
|
||||||
|
OnPlayerDamageTaken();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggers game over state when all ropes are broken
|
||||||
|
/// </summary>
|
||||||
|
private void TriggerGameOver()
|
||||||
|
{
|
||||||
|
if (isGameOver) return;
|
||||||
|
|
||||||
|
isGameOver = true;
|
||||||
|
Debug.Log("[DivingGameManager] Game Over! All ropes broken.");
|
||||||
|
|
||||||
|
// Fire game over event
|
||||||
|
OnGameOver?.Invoke();
|
||||||
|
|
||||||
|
// Call the existing end game method
|
||||||
|
EndGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates rope references and logs warnings if any are missing
|
||||||
|
/// </summary>
|
||||||
|
private void ValidateRopeReferences()
|
||||||
|
{
|
||||||
|
if (playerRopes == null || playerRopes.Length == 0)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[DivingGameManager] No ropes assigned to break! Damage system won't work properly.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < playerRopes.Length; i++)
|
||||||
|
{
|
||||||
|
if (playerRopes[i] == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[DivingGameManager] Rope at index {i} is null!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets the rope system for a new game
|
||||||
|
/// </summary>
|
||||||
|
public void ResetRopeSystem()
|
||||||
|
{
|
||||||
|
// Reset rope state
|
||||||
|
currentRopeIndex = 0;
|
||||||
|
isGameOver = false;
|
||||||
|
|
||||||
|
// Restore all broken ropes
|
||||||
|
if (playerRopes != null)
|
||||||
|
{
|
||||||
|
foreach (var rope in playerRopes)
|
||||||
|
{
|
||||||
|
if (rope != null)
|
||||||
|
{
|
||||||
|
rope.RestoreRope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log("[DivingGameManager] Rope system reset.");
|
||||||
|
}
|
||||||
|
|
||||||
// Call this when the game ends
|
// Call this when the game ends
|
||||||
public void EndGame()
|
public void EndGame()
|
||||||
{
|
{
|
||||||
|
|||||||
376
Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs
Normal file
376
Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using GogoGaga.OptimizedRopesAndCables;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Component that allows breaking a rope in half.
|
||||||
|
/// Attach this to the same GameObject that has a Rope and LineRenderer component.
|
||||||
|
/// </summary>
|
||||||
|
public class RopeBreaker : MonoBehaviour
|
||||||
|
{
|
||||||
|
[Header("Break Settings")]
|
||||||
|
[Tooltip("Position along rope where break occurs (0-1)")]
|
||||||
|
[Range(0f, 1f)]
|
||||||
|
[SerializeField] private float breakPosition = 0.5f;
|
||||||
|
|
||||||
|
[Tooltip("Effect to spawn at break point (optional)")]
|
||||||
|
[SerializeField] private GameObject breakEffect;
|
||||||
|
|
||||||
|
[Tooltip("Sound to play when rope breaks (optional)")]
|
||||||
|
[SerializeField] private AudioClip breakSound;
|
||||||
|
|
||||||
|
[Header("Animation Settings")]
|
||||||
|
[Tooltip("How quickly the rope ends fall after breaking")]
|
||||||
|
[SerializeField] private float fallSpeed = 2f;
|
||||||
|
|
||||||
|
[Tooltip("How much the rope ends swing after breaking")]
|
||||||
|
[SerializeField] private float swingAmount = 0.5f;
|
||||||
|
|
||||||
|
[Header("Physics Settings")]
|
||||||
|
[Tooltip("Follow speed for the rope physics simulation")]
|
||||||
|
[SerializeField] private float ropeFollowSpeed = 5f;
|
||||||
|
|
||||||
|
[Tooltip("Trailing amount for the rope physics simulation")]
|
||||||
|
[SerializeField] private float ropeTrailing = 0.2f;
|
||||||
|
|
||||||
|
[Tooltip("Oscillation amplitude for the rope physics simulation")]
|
||||||
|
[SerializeField] private float ropeOscillationAmplitude = 0.15f;
|
||||||
|
|
||||||
|
[Tooltip("Oscillation frequency for the rope physics simulation")]
|
||||||
|
[SerializeField] private float ropeOscillationFrequency = 2f;
|
||||||
|
|
||||||
|
// Private references
|
||||||
|
private Rope originalRope;
|
||||||
|
private LineRenderer originalLineRenderer;
|
||||||
|
private GameObject firstHalfRope;
|
||||||
|
private GameObject secondHalfRope;
|
||||||
|
private Rope firstHalfRopeComponent;
|
||||||
|
private Rope secondHalfRopeComponent;
|
||||||
|
private Transform breakPointTransform;
|
||||||
|
private Transform secondBreakTransform;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
// Get references to the required components
|
||||||
|
originalRope = GetComponent<Rope>();
|
||||||
|
originalLineRenderer = GetComponent<LineRenderer>();
|
||||||
|
|
||||||
|
if (originalRope == null || originalLineRenderer == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("RopeBreaker requires both Rope and LineRenderer components on the same GameObject");
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Breaks the rope at the specified position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="breakPositionOverride">Optional override for break position (0-1)</param>
|
||||||
|
/// <returns>True if rope was broken successfully, false otherwise</returns>
|
||||||
|
public bool BreakRope(float? breakPositionOverride = null)
|
||||||
|
{
|
||||||
|
if (originalRope == null || !originalRope.StartPoint || !originalRope.EndPoint)
|
||||||
|
{
|
||||||
|
Debug.LogError("Cannot break rope: Missing rope component or endpoints");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use override position if provided
|
||||||
|
float breakPos = breakPositionOverride ?? breakPosition;
|
||||||
|
breakPos = Mathf.Clamp01(breakPos);
|
||||||
|
|
||||||
|
// Get the world position at the break point
|
||||||
|
Vector3 breakPointPosition = originalRope.GetPointAt(breakPos);
|
||||||
|
|
||||||
|
// Create a transform at the break point to use as an anchor
|
||||||
|
CreateBreakPointTransform(breakPointPosition);
|
||||||
|
|
||||||
|
// Create two new rope GameObjects
|
||||||
|
CreateRopeSegments();
|
||||||
|
|
||||||
|
// Hide the original rope
|
||||||
|
originalLineRenderer.enabled = false;
|
||||||
|
|
||||||
|
// Play effects
|
||||||
|
PlayBreakEffects(breakPointPosition);
|
||||||
|
|
||||||
|
// Start the animation coroutine
|
||||||
|
StartCoroutine(AnimateRopeBreak());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a transform at the break point to use as an anchor
|
||||||
|
/// </summary>
|
||||||
|
private void CreateBreakPointTransform(Vector3 breakPointPosition)
|
||||||
|
{
|
||||||
|
// Create a new GameObject for the break point
|
||||||
|
GameObject breakPointObj = new GameObject("RopeBreakPoint");
|
||||||
|
breakPointTransform = breakPointObj.transform;
|
||||||
|
breakPointTransform.position = breakPointPosition;
|
||||||
|
breakPointTransform.SetParent(transform.parent); // Parent to the same parent as the rope
|
||||||
|
|
||||||
|
// Add the physics follower component to the break point
|
||||||
|
RopeEndPhysicsFollower follower = breakPointObj.AddComponent<RopeEndPhysicsFollower>();
|
||||||
|
follower.targetTag = "Player";
|
||||||
|
follower.followSpeed = ropeFollowSpeed;
|
||||||
|
follower.trailing = ropeTrailing;
|
||||||
|
follower.oscillationAmplitude = ropeOscillationAmplitude;
|
||||||
|
follower.oscillationFrequency = ropeOscillationFrequency;
|
||||||
|
follower.disableOscillation = true; // Disable oscillation for player-attached rope
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates two new rope GameObjects for the broken segments
|
||||||
|
/// </summary>
|
||||||
|
private void CreateRopeSegments()
|
||||||
|
{
|
||||||
|
// Create the first half rope (from start to break point)
|
||||||
|
firstHalfRope = new GameObject("Rope_FirstHalf");
|
||||||
|
firstHalfRope.transform.position = transform.position;
|
||||||
|
firstHalfRope.transform.rotation = transform.rotation;
|
||||||
|
firstHalfRope.transform.SetParent(transform.parent);
|
||||||
|
|
||||||
|
// Add Rope component which automatically adds LineRenderer due to RequireComponent
|
||||||
|
firstHalfRopeComponent = firstHalfRope.AddComponent<Rope>();
|
||||||
|
|
||||||
|
// Get the LineRenderer that was automatically added
|
||||||
|
LineRenderer firstLineRenderer = firstHalfRope.GetComponent<LineRenderer>();
|
||||||
|
if (firstLineRenderer == null)
|
||||||
|
{
|
||||||
|
// Only add if somehow not created (shouldn't happen, but safety check)
|
||||||
|
firstLineRenderer = firstHalfRope.AddComponent<LineRenderer>();
|
||||||
|
}
|
||||||
|
CopyLineRendererProperties(originalLineRenderer, firstLineRenderer);
|
||||||
|
|
||||||
|
// Create the second half rope (from break point to end)
|
||||||
|
secondHalfRope = new GameObject("Rope_SecondHalf");
|
||||||
|
secondHalfRope.transform.position = transform.position;
|
||||||
|
secondHalfRope.transform.rotation = transform.rotation;
|
||||||
|
secondHalfRope.transform.SetParent(transform.parent);
|
||||||
|
|
||||||
|
// Add Rope component which automatically adds LineRenderer due to RequireComponent
|
||||||
|
secondHalfRopeComponent = secondHalfRope.AddComponent<Rope>();
|
||||||
|
|
||||||
|
// Get the LineRenderer that was automatically added
|
||||||
|
LineRenderer secondLineRenderer = secondHalfRope.GetComponent<LineRenderer>();
|
||||||
|
if (secondLineRenderer == null)
|
||||||
|
{
|
||||||
|
// Only add if somehow not created (shouldn't happen, but safety check)
|
||||||
|
secondLineRenderer = secondHalfRope.AddComponent<LineRenderer>();
|
||||||
|
}
|
||||||
|
CopyLineRendererProperties(originalLineRenderer, secondLineRenderer);
|
||||||
|
|
||||||
|
// Configure the first half rope
|
||||||
|
firstHalfRopeComponent.SetStartPoint(originalRope.StartPoint);
|
||||||
|
firstHalfRopeComponent.SetEndPoint(breakPointTransform, false); // Don't recalculate yet
|
||||||
|
|
||||||
|
// Copy properties from original rope
|
||||||
|
CopyRopeProperties(originalRope, firstHalfRopeComponent);
|
||||||
|
|
||||||
|
// Explicitly initialize the rope
|
||||||
|
firstHalfRopeComponent.Initialize();
|
||||||
|
|
||||||
|
// Now force recalculation after initialization
|
||||||
|
firstHalfRopeComponent.RecalculateRope();
|
||||||
|
|
||||||
|
// Configure the second half rope - REVERSED: Rock (End) is now Start, Break point is now End
|
||||||
|
secondHalfRopeComponent.SetStartPoint(originalRope.EndPoint);
|
||||||
|
secondHalfRopeComponent.SetEndPoint(breakPointTransform, false); // Don't recalculate yet
|
||||||
|
|
||||||
|
// Copy properties from original rope
|
||||||
|
CopyRopeProperties(originalRope, secondHalfRopeComponent);
|
||||||
|
|
||||||
|
// Explicitly initialize the rope
|
||||||
|
secondHalfRopeComponent.Initialize();
|
||||||
|
|
||||||
|
// Now force recalculation after initialization
|
||||||
|
secondHalfRopeComponent.RecalculateRope();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copies properties from one LineRenderer to another
|
||||||
|
/// </summary>
|
||||||
|
private void CopyLineRendererProperties(LineRenderer source, LineRenderer destination)
|
||||||
|
{
|
||||||
|
// Copy material
|
||||||
|
destination.material = source.material;
|
||||||
|
|
||||||
|
// Copy colors
|
||||||
|
destination.startColor = source.startColor;
|
||||||
|
destination.endColor = source.endColor;
|
||||||
|
|
||||||
|
// Copy width
|
||||||
|
destination.startWidth = source.startWidth;
|
||||||
|
destination.endWidth = source.endWidth;
|
||||||
|
|
||||||
|
// Copy other properties
|
||||||
|
destination.numCornerVertices = source.numCornerVertices;
|
||||||
|
destination.numCapVertices = source.numCapVertices;
|
||||||
|
destination.alignment = source.alignment;
|
||||||
|
destination.textureMode = source.textureMode;
|
||||||
|
destination.generateLightingData = source.generateLightingData;
|
||||||
|
destination.useWorldSpace = source.useWorldSpace;
|
||||||
|
destination.loop = source.loop;
|
||||||
|
destination.sortingLayerID = source.sortingLayerID;
|
||||||
|
destination.sortingOrder = source.sortingOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copies properties from one Rope to another
|
||||||
|
/// </summary>
|
||||||
|
private void CopyRopeProperties(Rope source, Rope destination)
|
||||||
|
{
|
||||||
|
destination.linePoints = source.linePoints;
|
||||||
|
destination.stiffness = source.stiffness;
|
||||||
|
destination.damping = source.damping;
|
||||||
|
destination.ropeLength = source.ropeLength / 2f; // Halve the rope length for each segment
|
||||||
|
destination.ropeWidth = source.ropeWidth;
|
||||||
|
destination.midPointWeight = source.midPointWeight;
|
||||||
|
destination.midPointPosition = source.midPointPosition;
|
||||||
|
|
||||||
|
// Recalculate the rope to update its appearance
|
||||||
|
destination.RecalculateRope();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Plays visual and audio effects at the break point
|
||||||
|
/// </summary>
|
||||||
|
private void PlayBreakEffects(Vector3 breakPointPosition)
|
||||||
|
{
|
||||||
|
// Spawn break effect if assigned
|
||||||
|
if (breakEffect != null)
|
||||||
|
{
|
||||||
|
Instantiate(breakEffect, breakPointPosition, Quaternion.identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play break sound if assigned
|
||||||
|
if (breakSound != null)
|
||||||
|
{
|
||||||
|
AudioSource.PlayClipAtPoint(breakSound, breakPointPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Animates the rope break with falling and swinging effects
|
||||||
|
/// </summary>
|
||||||
|
private IEnumerator AnimateRopeBreak()
|
||||||
|
{
|
||||||
|
float elapsedTime = 0f;
|
||||||
|
Vector3 originalBreakPosition = breakPointTransform.position;
|
||||||
|
|
||||||
|
// Create a second break point that will move in the opposite direction
|
||||||
|
GameObject secondBreakPoint = new GameObject("RopeBreakPoint_Second");
|
||||||
|
secondBreakTransform = secondBreakPoint.transform;
|
||||||
|
secondBreakTransform.position = originalBreakPosition;
|
||||||
|
secondBreakTransform.SetParent(transform.parent);
|
||||||
|
|
||||||
|
// Add the physics follower component to the second break point
|
||||||
|
RopeEndPhysicsFollower secondFollower = secondBreakPoint.AddComponent<RopeEndPhysicsFollower>();
|
||||||
|
secondFollower.targetTag = "Rock";
|
||||||
|
secondFollower.followSpeed = ropeFollowSpeed;
|
||||||
|
secondFollower.trailing = ropeTrailing;
|
||||||
|
secondFollower.oscillationAmplitude = ropeOscillationAmplitude * 1.5f; // Slightly more oscillation for falling piece
|
||||||
|
secondFollower.oscillationFrequency = ropeOscillationFrequency;
|
||||||
|
secondFollower.disableOscillation = true; // Enable oscillation for rock-attached end
|
||||||
|
|
||||||
|
// Update the second rope to use this new break point as the end point
|
||||||
|
// (since we reversed the rope direction, the break point is now the end)
|
||||||
|
secondHalfRopeComponent.SetEndPoint(secondBreakTransform);
|
||||||
|
secondHalfRopeComponent.RecalculateRope();
|
||||||
|
|
||||||
|
// Get the directions for swinging
|
||||||
|
Vector3 direction1 = (originalRope.StartPoint.position - breakPointTransform.position).normalized;
|
||||||
|
Vector3 direction2 = (originalRope.EndPoint.position - breakPointTransform.position).normalized;
|
||||||
|
|
||||||
|
// Make sure the directions have horizontal components
|
||||||
|
direction1.y = 0;
|
||||||
|
direction2.y = 0;
|
||||||
|
|
||||||
|
// Normalize to prevent zero vectors
|
||||||
|
if (direction1.magnitude < 0.01f) direction1 = Vector3.right;
|
||||||
|
if (direction2.magnitude < 0.01f) direction2 = Vector3.left;
|
||||||
|
|
||||||
|
direction1.Normalize();
|
||||||
|
direction2.Normalize();
|
||||||
|
|
||||||
|
// Initial separation to create a visual gap
|
||||||
|
float separationDistance = originalLineRenderer.startWidth * 2f; // Base the gap on the rope width
|
||||||
|
breakPointTransform.position += -direction2 * separationDistance * 0.5f;
|
||||||
|
secondBreakTransform.position += direction2 * separationDistance * 0.5f;
|
||||||
|
|
||||||
|
// Recalculate the ropes after initial separation
|
||||||
|
firstHalfRopeComponent.RecalculateRope();
|
||||||
|
secondHalfRopeComponent.RecalculateRope();
|
||||||
|
|
||||||
|
while (elapsedTime < 0.75f) // Animate for 1 second
|
||||||
|
{
|
||||||
|
elapsedTime += Time.deltaTime;
|
||||||
|
|
||||||
|
// Calculate swing motion using sine wave (with different phases for each end)
|
||||||
|
float swingFactor1 = Mathf.Sin(elapsedTime * 4f) * swingAmount * Mathf.Exp(-elapsedTime);
|
||||||
|
float swingFactor2 = Mathf.Sin(elapsedTime * 4f + Mathf.PI * 0.5f) * swingAmount * Mathf.Exp(-elapsedTime);
|
||||||
|
|
||||||
|
// First break point (attached to player) - maintain Y position but allow swinging
|
||||||
|
Vector3 pos1 = originalBreakPosition;
|
||||||
|
pos1.y = originalBreakPosition.y; // Keep original Y position - no falling
|
||||||
|
pos1 += direction1 * swingFactor1;
|
||||||
|
pos1 += -direction2 * (separationDistance * 0.5f); // Maintain separation
|
||||||
|
breakPointTransform.position = pos1;
|
||||||
|
|
||||||
|
// Second break point (hanging rope end) - allow small amount of falling
|
||||||
|
Vector3 pos2 = originalBreakPosition;
|
||||||
|
float fallDistance = fallSpeed * elapsedTime;
|
||||||
|
pos2.y = originalBreakPosition.y - fallDistance; // Limited falling
|
||||||
|
pos2 += direction2 * swingFactor2;
|
||||||
|
pos2 += direction2 * (separationDistance * 0.5f); // Maintain separation
|
||||||
|
secondBreakTransform.position = pos2;
|
||||||
|
|
||||||
|
// Recalculate the ropes each frame
|
||||||
|
firstHalfRopeComponent.RecalculateRope();
|
||||||
|
secondHalfRopeComponent.RecalculateRope();
|
||||||
|
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After the initial animation, let the physics followers take over
|
||||||
|
// They will continue to move and animate the rope endpoints
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restores the original rope and cleans up the broken pieces
|
||||||
|
/// </summary>
|
||||||
|
public void RestoreRope()
|
||||||
|
{
|
||||||
|
// Re-enable the original rope
|
||||||
|
if (originalLineRenderer != null)
|
||||||
|
{
|
||||||
|
originalLineRenderer.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up the broken rope pieces
|
||||||
|
if (firstHalfRope != null)
|
||||||
|
{
|
||||||
|
Destroy(firstHalfRope);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondHalfRope != null)
|
||||||
|
{
|
||||||
|
Destroy(secondHalfRope);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up both break points
|
||||||
|
if (breakPointTransform != null)
|
||||||
|
{
|
||||||
|
Destroy(breakPointTransform.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find and destroy the second break point if it exists
|
||||||
|
Transform secondBreakPoint = transform.parent?.Find("RopeBreakPoint_Second");
|
||||||
|
if (secondBreakPoint != null)
|
||||||
|
{
|
||||||
|
Destroy(secondBreakPoint.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 30919200017f4879867c3b6289429924
|
||||||
|
timeCreated: 1758466190
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class RopeEndPhysicsFollower : MonoBehaviour
|
||||||
|
{
|
||||||
|
[Tooltip("Tag of the object this endpoint should follow (e.g., 'player' or 'rock')")]
|
||||||
|
public string targetTag;
|
||||||
|
[Tooltip("How quickly the endpoint follows the target")] public float followSpeed = 5f;
|
||||||
|
[Tooltip("How much trailing (0 = instant, 1 = very slow)")] public float trailing = 0.2f;
|
||||||
|
[Tooltip("Amplitude of fake gravity/flap")] public float oscillationAmplitude = 0.15f;
|
||||||
|
[Tooltip("Frequency of fake gravity/flap")] public float oscillationFrequency = 2f;
|
||||||
|
[Tooltip("If true, disable vertical oscillation (useful for player attachment)")]
|
||||||
|
public bool disableOscillation = true;
|
||||||
|
|
||||||
|
private Transform target;
|
||||||
|
private Vector3 velocity;
|
||||||
|
private Vector3 offset;
|
||||||
|
private float oscillationTime;
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(targetTag))
|
||||||
|
{
|
||||||
|
GameObject found = GameObject.FindGameObjectWithTag(targetTag);
|
||||||
|
if (found) target = found.transform;
|
||||||
|
}
|
||||||
|
offset = transform.position - (target ? target.position : Vector3.zero);
|
||||||
|
oscillationTime = Random.value * Mathf.PI * 2f; // randomize phase
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (!target) return;
|
||||||
|
// Smooth follow with trailing
|
||||||
|
Vector3 desired = target.position + offset;
|
||||||
|
transform.position = Vector3.SmoothDamp(transform.position, desired, ref velocity, trailing, followSpeed);
|
||||||
|
|
||||||
|
// Add fake gravity/flap (only if oscillation is enabled)
|
||||||
|
if (!disableOscillation)
|
||||||
|
{
|
||||||
|
oscillationTime += Time.deltaTime * oscillationFrequency;
|
||||||
|
float yOsc = Mathf.Sin(oscillationTime) * oscillationAmplitude;
|
||||||
|
transform.position += new Vector3(0, yOsc, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTargetTag(string tag)
|
||||||
|
{
|
||||||
|
targetTag = tag;
|
||||||
|
GameObject found = GameObject.FindGameObjectWithTag(targetTag);
|
||||||
|
if (found) target = found.transform;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bc5a0e35b5e74474b4241fae08971e7a
|
||||||
|
timeCreated: 1758485385
|
||||||
@@ -6,6 +6,7 @@ TagManager:
|
|||||||
tags:
|
tags:
|
||||||
- CharacterArt
|
- CharacterArt
|
||||||
- Pulver
|
- Pulver
|
||||||
|
- Rock
|
||||||
layers:
|
layers:
|
||||||
- Default
|
- Default
|
||||||
- TransparentFX
|
- TransparentFX
|
||||||
|
|||||||
Reference in New Issue
Block a user