@@ -8,7 +8,8 @@ enum PlayerState {
88 Idle , // grounded not moving
99 Walking , // grounded moving
1010 Jumping , // pressed jump, hasn't touched ground yet
11- Falling // didn't press jump, velocity of y is negative
11+ Falling , // didn't press jump, velocity of y is negative
12+ WallClinging , // player is clinging to a wall
1213 }
1314
1415 [ SerializeField ] private PlayerState _playerState = PlayerState . Idle ;
@@ -18,6 +19,8 @@ enum PlayerState {
1819 private ButtonControl [ ] _jumpButtonControls ;
1920
2021 [ SerializeField ] private Rigidbody2D _rigidbody2D ;
22+
23+ [ SerializeField ] private BoxCollider2D _boxCollider2D ;
2124
2225 [ SerializeField ] private float _movementSpeed = 4 ;
2326
@@ -34,10 +37,16 @@ enum PlayerState {
3437 private int _maxJumps = 2 ;
3538
3639 private float _graceJumpPeriod = 0f ; // grace period for jumping after walking off a ledge
40+
41+ private int _wallClingingDirection = 0 ;
42+
43+ private float _wallClingTimer = 0f ;
3744
3845 [ SerializeField ] private LayerMask _groundMask ;
46+
47+ [ SerializeField ] private LayerMask _wallClingMask ;
3948
40- private int _layer = - 1 ;
49+ private int _layerBeneath = - 1 ;
4150
4251 private Vector2 _movementInput ;
4352
@@ -49,7 +58,19 @@ private void Awake() {
4958 } ;
5059
5160 _playerActions . Player . Jump . performed += context => {
52- if ( _layer == ControllerUtils . PlatformLayer && Math . Abs ( _movementInput . y - ( - 1 ) ) < 0.01f ) {
61+ if ( _wallClingTimer > 0f ) return ;
62+
63+ if ( _playerState == PlayerState . WallClinging ) {
64+ _rigidbody2D . AddForce ( new Vector2 ( _wallClingingDirection == 1 ? 25 : - 25 , 50 ) * _jumpStrength ) ;
65+
66+ _wallClingTimer = 0.15f ;
67+
68+ TriggerJump ( ) ;
69+
70+ return ;
71+ }
72+
73+ if ( _layerBeneath == ControllerUtils . PlatformLayer && Math . Abs ( _movementInput . y - ( - 1 ) ) < 0.01f ) {
5374 _playerState = PlayerState . Falling ;
5475
5576 _canTriggerNewJump = false ;
@@ -81,6 +102,10 @@ private void TriggerJump() {
81102 }
82103
83104 private float HandleJump ( ) {
105+ if ( _playerState == PlayerState . WallClinging ) {
106+ return _rigidbody2D . linearVelocity . y / 2 ;
107+ }
108+
84109 if ( ControllerUtils . IsButtonDown ( _jumpButtonControls ) ) {
85110 if ( _canTriggerNewJump && _playerState != PlayerState . Jumping && _playerState != PlayerState . Falling ) {
86111 TriggerJump ( ) ;
@@ -123,10 +148,18 @@ private void Update() {
123148
124149 if ( _graceJumpPeriod > 0f )
125150 _graceJumpPeriod -= Time . deltaTime ;
151+
152+ if ( _wallClingTimer > 0f )
153+ _wallClingTimer -= Time . deltaTime ;
154+ }
155+
156+ private RaycastHit2D CastInDirection ( float radius , Vector2 direction , float distance , LayerMask mask ) {
157+ return Physics2D . CircleCast ( transform . position , radius , direction , distance , mask ) ;
126158 }
127159
128160 private void FixedUpdate ( ) {
129- _rigidbody2D . linearVelocity = HandleControllerMovement ( ) ;
161+ if ( _wallClingTimer <= 0f )
162+ _rigidbody2D . linearVelocity = HandleControllerMovement ( ) ;
130163
131164 if ( _rigidbody2D . linearVelocity . y < 0 && _playerState != PlayerState . Jumping && _playerState != PlayerState . Falling ) {
132165 _graceJumpPeriod = 0.15f ;
@@ -135,47 +168,74 @@ private void FixedUpdate() {
135168 }
136169
137170 if ( _jumpTimer <= 0f && ( _playerState == PlayerState . Falling || _playerState == PlayerState . Jumping ) ) {
138- RaycastHit2D hit = Physics2D . CircleCast ( transform . position , GroundRayCastRadius , Vector2 . down , GroundRayCastDistance , _groundMask ) ;
171+ RaycastHit2D bottomHit = CastInDirection ( RayCastRadius , Vector2 . down , RayCastDistance , _groundMask ) ;
172+
173+ RaycastHit2D rightHit = CastInDirection ( RayCastRadius , Vector2 . right , RayCastDistance , _wallClingMask ) ;
174+
175+ RaycastHit2D leftHit = CastInDirection ( RayCastRadius , Vector2 . left , RayCastDistance , _wallClingMask ) ;
176+
177+ if ( rightHit && ( rightHit . collider . CompareTag ( "Platform" ) || rightHit . collider . CompareTag ( "Wall" ) ) && Math . Abs ( _movementInput . x - 1 ) < 0.1f ) {
178+ _wallClingingDirection = - 1 ;
179+
180+ _playerState = PlayerState . WallClinging ;
181+
182+ _jumps = 0 ;
183+ } else if ( leftHit && ( leftHit . collider . CompareTag ( "Platform" ) || leftHit . collider . CompareTag ( "Wall" ) ) && Math . Abs ( _movementInput . x - ( - 1 ) ) < 0.1f ) {
184+ _wallClingingDirection = 1 ;
185+
186+ _playerState = PlayerState . WallClinging ;
187+
188+ _jumps = 0 ;
189+ } else {
190+ _wallClingingDirection = 0 ;
191+ }
139192
140- if ( hit ) {
141- _layer = hit . collider . gameObject . layer ;
193+ if ( bottomHit ) {
194+ _layerBeneath = bottomHit . collider . gameObject . layer ;
142195
143196 _jumps = 0 ;
144197
145198 ControllerUtils . IgnorePlatformCollision ( false ) ;
146199
147200 _playerState = PlayerState . Idle ;
148- }
149- else {
150- _layer = - 1 ;
201+ } else {
202+ _layerBeneath = - 1 ;
151203 }
152204 }
153205 }
154206
155207 // collision detection
156208
157- private const float GroundRayCastRadius = 0.3f ;
158- private const float GroundRayCastDistance = 0.3f ;
209+ private const float RayCastRadius = 0.3f ;
210+ private const float RayCastDistance = 0.3f ;
159211
160212 // gizmos
161213
162214 private void OnDrawGizmos ( ) {
163- GroundRayCastDetection ( ) ;
164- }
165-
166- private void GroundRayCastDetection ( ) {
167- Vector2 origin = transform . position ;
168- Vector2 direction = Vector2 . down ;
215+ RaycastHit2D bottomHit = CastInDirection ( RayCastRadius , Vector2 . down , RayCastDistance , _groundMask ) ;
216+
217+ DrawHit ( bottomHit , Vector2 . down ) ;
218+
219+ RaycastHit2D rightHit = CastInDirection ( RayCastRadius , Vector2 . right , RayCastDistance , _wallClingMask ) ;
220+
221+ DrawHit ( rightHit , Vector2 . right ) ;
169222
170- RaycastHit2D hit = Physics2D . CircleCast ( origin , GroundRayCastRadius , direction , GroundRayCastDistance , _groundMask ) ;
223+ RaycastHit2D leftHit = CastInDirection ( RayCastRadius , Vector2 . left , RayCastDistance , _wallClingMask ) ;
224+
225+ DrawHit ( leftHit , Vector2 . left ) ;
226+
227+ // GroundRayCastDetection();
228+ }
171229
230+ private void DrawHit ( RaycastHit2D hit , Vector2 direction ) {
172231 Gizmos . color = hit ? Color . green : Color . red ;
173- Gizmos . DrawLine ( origin , origin + direction * GroundRayCastDistance ) ;
174- Gizmos . DrawWireSphere ( origin + direction * GroundRayCastDistance , GroundRayCastRadius ) ;
232+ Gizmos . DrawLine ( transform . position , ( Vector2 ) transform . position + direction * RayCastDistance ) ;
233+
234+ Gizmos . DrawWireSphere ( ( Vector2 ) transform . position + direction * RayCastDistance , RayCastRadius ) ;
175235
176236 if ( hit ) {
177237 Gizmos . color = Color . yellow ;
178- Gizmos . DrawWireSphere ( hit . point , GroundRayCastRadius ) ;
238+ Gizmos . DrawWireSphere ( hit . point , RayCastRadius ) ;
179239 }
180240 }
181241
0 commit comments