From 01e700a00e742fa07464be4918ac2e07f39049d7 Mon Sep 17 00:00:00 2001 From: Pasha Bibko Date: Fri, 28 Mar 2025 14:29:03 +0000 Subject: [PATCH] Made wall-riding able to turn corners Also changed air drag --- Assets/Scenes/SampleScene.unity | 221 ++++++++++++++++++- Assets/Scripts/Player/PlayerMovement.cs | 3 + Assets/Scripts/Player/PlayerState.cs | 10 +- Assets/Scripts/Player/PlayerUpdate.cs | 4 + Assets/Scripts/Player/WallRunningMovement.cs | 7 +- 5 files changed, 234 insertions(+), 11 deletions(-) diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index fe60076..c3f931e 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -618,7 +618,7 @@ MonoBehaviour: m_State: 0 m_MoveSpeed: 7 m_GroundDrag: 5 - m_AirDrag: 4 + m_AirDrag: 1 m_PlayerHeight: 2 m_GroundMask: serializedVersion: 2 @@ -634,6 +634,7 @@ MonoBehaviour: m_WallRunSpeed: 15 m_WallCheckDistance: 1.5 m_DistanceOfFloorToWallRide: 0.1 + m_WallRideDrag: 4 m_JumpKey: 32 m_SlideKey: 99 m_WallRunKey: 304 @@ -7177,7 +7178,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 5cfd42fc2ed2f504dae2b9e7095401cf, type: 3} m_Name: m_EditorClassIdentifier: - m_Sensitivity: {x: 400, y: 400} + m_Sensitivity: {x: 1200, y: 800} m_MaxAngle: 85 m_Orientation: {fileID: 166780449} --- !u!1 &974940780 @@ -8725,7 +8726,7 @@ Rigidbody: m_IsKinematic: 0 m_Interpolate: 0 m_Constraints: 0 - m_CollisionDetection: 0 + m_CollisionDetection: 1 --- !u!1 &1204641200 GameObject: m_ObjectHideFlags: 0 @@ -9362,6 +9363,112 @@ MeshFilter: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1237184041} m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1239908885 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1239908886} + - component: {fileID: 1239908889} + - component: {fileID: 1239908888} + - component: {fileID: 1239908887} + m_Layer: 10 + m_Name: Floor (101) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1239908886 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1239908885} + serializedVersion: 2 + m_LocalRotation: {x: 0.70710677, y: 0, z: 0, w: 0.70710677} + m_LocalPosition: {x: 0, y: 5, z: -4.99} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 2043134296} + m_LocalEulerAnglesHint: {x: 90, y: 90, z: 90} +--- !u!64 &1239908887 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1239908885} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 5 + m_Convex: 1 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1239908888 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1239908885} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: d68b4105a42c80a4ab173468c7256a55, 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: 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!33 &1239908889 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1239908885} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} --- !u!1 &1246331934 GameObject: m_ObjectHideFlags: 0 @@ -9468,6 +9575,112 @@ Transform: m_Children: [] m_Father: {fileID: 2043134296} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1287382798 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1287382799} + - component: {fileID: 1287382802} + - component: {fileID: 1287382801} + - component: {fileID: 1287382800} + m_Layer: 10 + m_Name: Floor (102) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1287382799 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1287382798} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0.70710677, z: -0.70710677, w: 0} + m_LocalPosition: {x: 0, y: 5, z: -5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 2043134296} + m_LocalEulerAnglesHint: {x: 90, y: 90, z: -90} +--- !u!64 &1287382800 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1287382798} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 5 + m_Convex: 1 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1287382801 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1287382798} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: d68b4105a42c80a4ab173468c7256a55, 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: 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!33 &1287382802 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1287382798} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} --- !u!1 &1315944177 GameObject: m_ObjectHideFlags: 0 @@ -12975,6 +13188,8 @@ Transform: - {fileID: 1124258151} - {fileID: 1854878171} - {fileID: 3704415} + - {fileID: 1239908886} + - {fileID: 1287382799} - {fileID: 453349377} - {fileID: 1204641201} - {fileID: 443455230} diff --git a/Assets/Scripts/Player/PlayerMovement.cs b/Assets/Scripts/Player/PlayerMovement.cs index aec253a..601690a 100644 --- a/Assets/Scripts/Player/PlayerMovement.cs +++ b/Assets/Scripts/Player/PlayerMovement.cs @@ -30,6 +30,7 @@ public partial class PlayerMovement : MonoBehaviour [SerializeField] float m_WallRunSpeed; [SerializeField] float m_WallCheckDistance; [SerializeField] float m_DistanceOfFloorToWallRide; + [SerializeField] float m_WallRideDrag; [Header("KeyBinds")] [SerializeField] KeyCode m_JumpKey; @@ -68,6 +69,7 @@ public partial class PlayerMovement : MonoBehaviour // Wall riding trackers bool m_FirstFrameWallRiding = true; bool m_FlippedWallRideDirectionFirstFrame = false; + Vector3 m_LastWallNormal; // Raycast hit objects RaycastHit m_GroundHit; @@ -91,6 +93,7 @@ public partial class PlayerMovement : MonoBehaviour // Creates the wall collider m_WallCollider = gameObject.AddComponent(); m_WallCollider.size = new Vector3(m_WallCheckDistance * 2, 0.2f, m_WallCheckDistance * 2); + m_WallCollider.center = new Vector3(0.0f, 0.5f, 0.5f); m_WallCollider.providesContacts = true; m_WallCollider.isTrigger = true; diff --git a/Assets/Scripts/Player/PlayerState.cs b/Assets/Scripts/Player/PlayerState.cs index aa874b3..92a6a64 100644 --- a/Assets/Scripts/Player/PlayerState.cs +++ b/Assets/Scripts/Player/PlayerState.cs @@ -18,14 +18,14 @@ public partial class PlayerMovement : MonoBehaviour Vector3 vel = m_Body.velocity; bool canSlide = !(Mathf.Abs(vel.x) < m_SlideRequiredSpeed && Mathf.Abs(vel.z) < m_SlideRequiredSpeed); - // Checks if the player is in the wall running state - if (GetNormalOfClosestCollider(out m_WallNormal) && m_WallRunKeyPressed) - { m_State = PlayerState.WALL_RUNNING; } - // Checks if the player is in the wall riding state - else if (m_SlidingKeyPressed && (canSlide || m_OnSlope) && m_Grounded) + if (m_SlidingKeyPressed && (canSlide || m_OnSlope) && m_Grounded) { m_State = PlayerState.SLIDING; } + // Checks if the player is in the wall running state + else if (GetNormalOfClosestCollider(out m_WallNormal) && m_WallRunKeyPressed) + { m_State = PlayerState.WALL_RUNNING; } + // Defaults to ruuning else { m_State = PlayerState.RUNNING; } diff --git a/Assets/Scripts/Player/PlayerUpdate.cs b/Assets/Scripts/Player/PlayerUpdate.cs index 46d8e48..6eb1451 100644 --- a/Assets/Scripts/Player/PlayerUpdate.cs +++ b/Assets/Scripts/Player/PlayerUpdate.cs @@ -24,6 +24,10 @@ public partial class PlayerMovement : MonoBehaviour m_Body.drag = m_SlideDrag; break; + case PlayerState.WALL_RUNNING: + m_Body.drag = m_WallRideDrag; + break; + default: // Applies different drag depending on if the player is on the ground or not if (m_Grounded) diff --git a/Assets/Scripts/Player/WallRunningMovement.cs b/Assets/Scripts/Player/WallRunningMovement.cs index 67addb7..ae2603e 100644 --- a/Assets/Scripts/Player/WallRunningMovement.cs +++ b/Assets/Scripts/Player/WallRunningMovement.cs @@ -4,8 +4,6 @@ public partial class PlayerMovement : MonoBehaviour { bool GetNormalOfClosestCollider(out Vector3 normal) { - Debug.Log(m_WallCollisions.Count); - float dist = Mathf.Infinity; Collider closest = null; @@ -53,7 +51,7 @@ public partial class PlayerMovement : MonoBehaviour // Calculates the foward direction of the wall Vector3 foward = Vector3.Cross(m_WallNormal, transform.up); - if (m_FirstFrameWallRiding == true) + if (m_FirstFrameWallRiding == true || m_LastWallNormal != m_WallNormal) { // Resets the tracker m_FirstFrameWallRiding = false; @@ -74,5 +72,8 @@ public partial class PlayerMovement : MonoBehaviour // Removes any vertical velocity the player may have m_Body.velocity = new Vector3(m_Body.velocity.x, 0.0f, m_Body.velocity.z); + + // Sets the last wall normal to the current normal for later use + m_LastWallNormal = m_WallNormal; } }