Posted in: Unity, 프로젝트 When the Spring comes

5. 플레이어를 튕겨내는 오브젝트

대부분의 게임에서 플레이어나 다른 게임 오브젝트를 튕겨내는 구조물이 있다. 우리가 제작하는 게임에도 그런 구조물을 넣을려고 했는데 가끔 이해하기 힘든 버그가 일어날때가 있다.

보통 그런 경우가 플레이어 이동을 Rigidbody.velocity에 바로 덮어씌워서 버그가 일어난다. 왜냐하면 유니티에서 플레이어 튕겨내는 기능을 Rigidbody.AddForce로 제작하기 때문이다.

Rigidbody.AddForce는 결론적으로 Rigidbody.velocity 값을 변화 주기 때문에 velocity에 값을 덮어씌워서 캐릭터 이동을 하면 AddForce 값이 대입되긴 하지만 바로 캐릭터 이동 값이 덮어씌워지기 때문에 무시되는 것이다.

이런 버그를 고치기 위해선 캐릭터 이동을 position을 제어하는게 중요하다.

플레이어를 튕겨내는 코드는 Rigidbody.AddForce를 사용하여 만들면 되는데 8방향으로 만들었다. 위 사진의 bool 변수를 통해서 어느 방향으로 튕길건지 제어하는 것이다.

사실 어느 방향으로 튕기느냐가 코드 제작에 가장 힘든 점인데 위 사진처럼 bool 변수를 통해 방향 제어를 하는게 마음 편하다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjBounce : Obj
{
    public float force;

    public bool upLeft;
    public bool up;
    public bool upRight;
    public bool left;
    public bool right;
    public bool downLeft;
    public bool down;
    public bool downRight;


    public override void Bounce()
    {
        if(upLeft)
        {
            GetComponent<Rigidbody>().AddForce(
                new Vector3(-0.7f,0,0.7f) * force, ForceMode.Impulse);

            GameManager.GetInstance().isBounce = false;
            Debug.Log("왼쪽 위로 튕긴다!");
        }
        if(up)
        {
            GetComponent<Rigidbody>().AddForce(
                new Vector3(0,0,1) * force, ForceMode.Impulse);

            GameManager.GetInstance().isBounce = false;
            Debug.Log("위로 튕긴다!");
        }
        if(upRight)
        {
            GetComponent<Rigidbody>().AddForce(
                new Vector3(0.7f,0,0.7f) * force, ForceMode.Impulse);

            GameManager.GetInstance().isBounce = false;
            Debug.Log("오른쪽 위로 튕긴다!");
        }
        if(left)
        {
            GetComponent<Rigidbody>().AddForce(
                Vector3.left * force, ForceMode.Impulse);

            GameManager.GetInstance().isBounce = false;
            Debug.Log("왼쪽으로 튕긴다!");
        }
        if(right)
        {
            GetComponent<Rigidbody>().AddForce(
                Vector3.right * force, ForceMode.Impulse);

            GameManager.GetInstance().isBounce = false;
            Debug.Log("오른쪽으로 튕긴다!");
        }
        if(downLeft)
        {
            GetComponent<Rigidbody>().AddForce(
                new Vector3(-0.7f,0,-0.7f) * force, ForceMode.Impulse);

            GameManager.GetInstance().isBounce = false;
            Debug.Log("왼쪽 아래로 튕긴다!");
        }
        if(down)
        {
            GetComponent<Rigidbody>().AddForce(
                new Vector3(0,0,-1) * force, ForceMode.Impulse);

            GameManager.GetInstance().isBounce = false;
            Debug.Log("아래로 튕긴다!");
        }
        if(downRight)
        {
            GetComponent<Rigidbody>().AddForce(
                new Vector3(0.7f,0,-0.7f) * force, ForceMode.Impulse);

            GameManager.GetInstance().isBounce = false;
            Debug.Log("오른쪽 아래로 튕긴다!");
        }
    }

    void OnCollisionEnter(Collision collision)
    {
        //layer == 8 은 플레이어
        if(collision.gameObject.layer == 8)
        {
            GameManager.GetInstance().isBounce = true;
        }
    }
}

코드는 위와 같지만 맵 디자인에 사용될 오브젝트 코드는 추상 클래스로 제작하였다. 기능이 추가될수록 코드가 훨씬 깔끔해지고 정리하기도 편하기 때문이다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다