-
Parrying Sword #8 : [기획][프로그래밍] 와이어 액션 구현유니티 게임 개발/메인 프로젝트: Parrying Sowrd 2023. 2. 17. 11:56
벽 잡기를 만들고 나서도 y축을 활용하는 액션이 부족하다는 생각이 들어
와이어 액션을 구현하였습니다
마법을 쓴다는 이미지로 구상을 했고, 그 결과 위 이미지처럼 제작하게 되었습니다.
// 와이어 액션 ************************************** if ( Input.GetKey(KeyCode.S) && playerCtrl.actionActive && wire != 0 ) { prevWire = wire; wire = playerCtrl.ActionWireJump(); if( prevWire != -1 && wire == 0 || (prevWire == 1 && wire == -1) ) { playerCtrl.ActionWireInertia(); } } if( Input.GetKeyUp(KeyCode.S) ) { if( wire > 0 ) { wire = -1; playerCtrl.ActionWireInertia(); } else if( wire == 0 ) { wire = -1; } } if (wire > 0) return; // ************************************************
PlayerMain 클래스에서의 와이어 액션 코드입니다.
여기서 wire 변수가 1이면 잡기 성공, 0이면 너무 가까워서 실패, -1이면 잡을 벽이 없음 판정입니다.
잡을 벽이 가까이에 없으면 아예 실패하고
중간에 키 입력을 놓거나, 너무 가까워지면 와이어가 끊기도록 설정합니다.
가능하면 리턴을 bool 변수로 다루고 싶었으나, 각각의 상황을 전부 제대로 다루어 놓지 않으면 의도대로 작동하지 않습니다.
다른 클래스와 너무 깊게 엮이는 것 같아 그렇게 마음에 들지는 않지만, 그래도 버그가 나는 대로 내버려 둘 수는 없습니다.
// 와이어액션 public int ActionWireJump() { int success = wireAction.ActionWireJump(); if( success > 0 ) { usingWire = true; animator.SetTrigger("WireAction"); } return success; } public void ActionWireInertia() { usingWire = false; wireAction.inactiveWire(); rb.velocity = new Vector2(rb.velocity.x * 1.3f, 40.0f); }
위에서 언급된 wire 변수의 값을 위 함수에서 제공합니다.
WireAction 클래스에서 값을 받아오고, 애니메이션 상태를 변경 해 줍니다.
중요한 것은, 와이어가 끊어졌을 때 반동으로 가해지는 힘을 억지로 바꿔주어야 합니다.
그렇지 않으면 와이어액션 중 가해지는 힘에 의해 저 멀리 날아가는 문제가 생깁니다.
그렇다고 아예 없으면 안되니 velocity를 바꾸어 반동을 조절합니다.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class WireAction : MonoBehaviour { private PlayerController playerCtrl; private GameObject player; private Transform wire; private Transform wireHook; private SpriteRenderer[] sprites; private Transform wirePosition; private float distance = 0; private void Awake() { player = GameObject.Find("Player"); playerCtrl = player.GetComponent<PlayerController>(); sprites = GetComponentsInChildren<SpriteRenderer>(); wire = transform.Find("Wire"); wireHook = transform.Find("WireHook"); wirePosition = player.transform.Find("WirePosition"); } // 템플릿 메소드 ********************************************************* // -1 탐색 실패, 0 너무 가까움 1 가능 public int ActionWireJump() { moveAtPlayer(); int check = checkDistance(); if (check < 1) return check; modifyTransform(); activeWire(); addForce(); return check; } // ******************************************************************** private void moveAtPlayer() { transform.position = wirePosition.position; } // -1 탐색 실패, 0 너무 가까움 1 가능 private int checkDistance() { Collider2D[] colliders; for( int i = 0; i < 2; i++ ) { colliders = Physics2D.OverlapPointAll(new Vector2(transform.position.x + i * playerCtrl.dir, transform.position.y + i)); // Debug.Log(i); foreach (Collider2D collider in colliders) { if (collider.tag == "Road") { return 0; } } } for( int i = 1; i < 26; i++ ) { colliders = Physics2D.OverlapPointAll(new Vector2(transform.position.x + i * playerCtrl.dir, transform.position.y + i)); // Debug.Log(i); foreach( Collider2D collider in colliders ) { if( collider.tag == "Road" ) { distance = i; return 1; } } } return -1; } private void modifyTransform() { wire.localScale = new Vector3(distance * 1.4f, wire.localScale.y, wire.localScale.z); transform.localScale = new Vector3( Mathf.Abs( transform.localScale.x ), transform.localScale.y, transform.localScale.z); wireHook.transform.position = new Vector3(transform.position.x + ( distance + 1 ) * playerCtrl.dir, transform.position.y + distance, transform.position.z); } private void activeWire() { foreach( SpriteRenderer sprite in sprites ) { sprite.enabled = true; } } private void addForce() { player.GetComponent<Rigidbody2D>().velocity = new Vector2(70.0f * playerCtrl.dir, 60.0f); } // 스프라이트 끄기 public void inactiveWire() { foreach (SpriteRenderer sprite in sprites) { sprite.enabled = false; } } }
WireAction 클래스입니다.
순서가 중요한 관계로 템플릿 메소드 패턴을 적용하였습니다.
시작 지점을 기준으로 x, y축을 대각선으로 1만큼 이동하며 잡을 벽이 있나를 체크하고, 있으면 벽을 잡고 쭉 진행합니다.
추가로 와이어를 끊기 위해 스프라이트를 꺼주는 함수를 하나 더 만들어 줍니다.
'유니티 게임 개발 > 메인 프로젝트: Parrying Sowrd' 카테고리의 다른 글
Parrying Sword #10 : [아트][기획] 벽 잡기, 와이어 액션, 폭탄 스프라이트 / 플레이어 애니메이션 현황 (0) 2023.02.17 Parrying Sword #9 : [기획][프로그래밍] 폭탄 구현 중 (0) 2023.02.17 Parrying Sword #7 : [기획][프로그래밍] 벽 잡기 (등반) 구현 (0) 2023.02.17 Parrying Sword #6 : [기획] 플레이어 액션 구현 (0) 2022.11.21 Parrying Sword #5 : [프로그래밍] 맵의 가장자리를 벽으로 둘러 싸기 (0) 2022.11.13