-
Unity2D Player 이동 구현Unity 2021. 3. 15. 00:41
1. Transform.position
new Vector2로 위치좌표 받아가지고 그 좌표로 이동시키는 방법이 있다. Transform클래스의 변수 position이 월드 좌표계에서의 위치를 나타내는 값이므로 어떤 특정좌표로 이동시키고 싶다면 이 방법을 사용하면 된다. 작년에 모바일 슈팅게임 만들때 player을 터치한 좌표로 이동시킬때 이 방법을 사용했었다.Vector2 pos = new Vector2(touch.position.x. touch.position.y); transform.position = pos;
슈팅게임의 경우 방향이동이 자유롭고 딱히 장애물도 없기 때문에 Transform으로 구현을 해도 별 문제가 없었는데, 대부분 게임은 Player가 rigidbody를 가지고 있어서 이 방법을 잘 안 쓰는 듯 하다. rigidbody가 있으면 transform클래스 사용보다는 rigidbody내의 velocity를 직접 조작하거나 addForce, moveposition을 사용하는 것 같다. (일종의 권장사항인듯) Velocity를 직접조작하는 경우는 속도를 직접 건드려서 이동을 구현하는거고, MovePosition은 위치를 변경하는거, AddForce는 가속도를 변경하는 방법으로 알고 있다.
2. Rigidbody의 MovePositionprivate Rigidbody2D rigid; private float speed = 3f; void Start() { rigid = GetComponent<Rigidbody2D>(); } void FixedUpdate() { Moving(); } void Moving() { Vector2 direction = new Vector2(Input.GetAxis("Horizontal"), ); Vector2 position = new Vector2(transform.position.x, transform.position.y); // 현 위치 받아옴 rigid.MovePosition(position + direction * speed * Time.deltaTime); }
<코드 설명>
direction을 방향을 지정하기 위한 값이다.
Input.GetAxis는 키보드로 받은 input에서 방향벡터의 x, y 값을 가져온다. -1.0f~1.0f사이 값을 반환하여 그에 따라 수평적인 움직임(왼쪽오른쪽) 방향을 지정해준다.
* 참고 : Input.GetAxisRaw는 정수값으로만 딱 떨어지게 준다. 그래서 좀 더 부드럽게 조작하고싶다면 GetAxis를 사용하고 누르자마자 이동시킬거면 GetAxisRaw를 사용하면 된다.
position은 현재 오브젝트의 위치를 받아온다. 그래서 MovePosition에서 현재 위치에다가 방향 * speed만큼 이동시켜주는 원리이다. MovePosition의 경우 물체를 즉각적으로 특정 위치로 이동시키는 함수이기 때문에 중력이나 저항같은걸 무시할 수 있다. (아래 링크 첫문단에 나와있음) 그래서 중력을 사용하는 경우에는 AddForce로 이동시키는게 나은 방식인것 같다
docs.unity3d.com/2018.2/Documentation/ScriptReference/Rigidbody2D.MovePosition.htmlUnity - Scripting API: Rigidbody2D.MovePosition
Moves the rigidbody to the specified position by calculating the appropriate linear velocity required to move the rigidbody to that position during the next physics update. During the move, neither gravity or linear drag will affect the body. This causes t
docs.unity3d.com
3. Rigidbody AddForce
내가 사용한 방법이다. 힘을 가해서 미는 방법인만큼 최고속도 제한을 안해주면 슝 날아가버릴수도 있다. ㅋㅋㅋpublic class Player : MonoBehaviour { private float maxSpeed = 3f; private float jumpSpeed = 15f; private bool isJump = false; Rigidbody2D rigid; SpriteRenderer render; private void Awake() { rigid = GetComponent<Rigidbody2D>(); render = GetComponent<SpriteRenderer>(); } void Update() { if (Input.GetButtonUp("Horizontal")) //손 떼면 속도 줄임 { // 벡터값이 방향뿐아니라 크기도 가지고 있기 때문에 정규화 필요(방향구할때쓰는거) rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y); } } void FixedUpdate() { float horizontal = Input.GetAxisRaw("Horizontal"); //좌우로만 움직일거기 때문에 horizontal키값으로 받음 rigid.AddForce(Vector2.right * horizontal, ForceMode2D.Impulse); if(rigid.velocity.x > maxSpeed) // 오른쪽 움직이는경우 { render.flipX = false; rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y); //최고속도 넘으면 자동으로 최고속도로 조절해줌 } else if (rigid.velocity.x < maxSpeed *(-1)) //왼쪽움직이는 경우(음수처리 해줘야함) { render.flipX = true; rigid.velocity = new Vector2(maxSpeed *(-1), rigid.velocity.y); } //rigid.velocity.y를 해두는 이유는 얘를 0으로 주면 후에 점프하다 멈춤.. if(Input.GetButtonDown("Jump") && isJump == false) { rigid.AddForce(Vector2.up * jumpSpeed, ForceMode2D.Impulse); isJump = true; } } private void OnCollisionEnter2D(Collision2D collision) { if(collision.gameObject.tag == "Land") { isJump = false; } } }
<코드설명> // 대부분 주석에 있지만
Update
대부분 Rigidbody를 이용한 물리연산은 FixedUpdate에서 진행하지만, 단발적인 Key입력의 경우도 FixedUpdate에서 처리해버리면 가끔 인풋이 무시되는 경우가 생긴다고 한다. 그래서 보통 key입력과 물리연산을 Update, FixedUpdate함수에서 각각 나눠서 처리하는게 베스트라고는 들었다. 쨌든 약간 감속을 주기위해 짠 코드이다.
FixedUpdate
이 방법이 가속도로 조절하는 방법이기때문에 최고속도 제한을 걸어줘야해서 maxSpeed값을 넘으면 자동으로 조절되게끔 만들어주었다. 그리고 점프를 위해 위쪽방향으로 AddForce를 위방향으로 주었다. ForceMode2D.Impulse는 즉각적인 힘을 주는 변수라고 생각하면 된다. 점프의 경우 순간적인 움직임이 필요한거니까 Impulse로 주었다.
CollisionEnter2D
땅에 닿았을 경우 isJump변수 false로 다시 바꾸어주기 위한 함수. 근데 더 좋은 방법이 있을 수도 있을 것 같아서 다음 포스팅에는 이걸 좀 더 공부해보고 적어둘 예정.
참고한 유튜브(골드메탈님 유튜브)
www.youtube.com/playlist?list=PLO-mt5Iu5TeZGR_y6mHmTWyo0RyGgO0N_
'Unity' 카테고리의 다른 글
Unity 2D 애니메이션 공부 (0) 2021.03.20 Unity 날씨 변화 구현하기 (0) 2021.01.05