본문 바로가기

유니티/Hunting게임[2D]

2D 미니게임 만들기 연습 3 ] 물체에 움직임 부여하기

지난 포스팅까지는 물체를 클릭하게 되면 반응하게끔 만들어 보았다.

 

이제 해당 물체에 움직임을 부여 해 보도록 하겠다.

 

우선 RigidBody2D - BodyType에서 Kinematic을 Dynamic으로 바꾸어 주도록 하겠다.

이렇게 하면 물체가 다시 중력의 영향을 받게 된다.

 

여기서 처음에는 Spawn()함수를 만들어서 해당 물체가 생성될 때 그 물체에 AddForce를 주어서 중력과 함께 움직임을 주게 되었다.

 

그렇게 되면 아래 움짤과 같이 된다.

 

 

생성이 되면서 Force를 받는 장면

 

코드는 아래와 같다.

 

public void SpawnTarget()
{
    UnityEngine.Random.InitState(DateTime.Now.Millisecond);
    RandomFloatX = UnityEngine.Random.Range(-8.2f, 8.4f);
    RandomFloatY = UnityEngine.Random.Range(-4.4f, 4.4f);

    Target = Instantiate(TargetPrefab, new Vector2(RandomFloatX, RandomFloatY), Quaternion.identity) as GameObject;

    if(RandomFloatX > 0)
        Target.GetComponent<Rigidbody2D>().AddForce(new Vector2(-500, 0));
    else
        Target.GetComponent<Rigidbody2D>().AddForce(new Vector2(500, 0));
}

 

그렇지만 이러한 움직임은 한 번 좌/우로 힘을 받고 나서 중력의 영향밖에 받지 못한다는 단점이 존재한다.

 

따라서 주기적으로 랜덤으로 Force를 주어 상/하/좌/우 로 움직이게끔 하는 것을 구현하려 한다.

 

이에, TargetMove.cs 코드를 만들어 타겟 속에 넣어 주도록 한다.

 

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

public class TargetMove : MonoBehaviour
{
    Rigidbody2D rigid;
    float changeTime = 0f;
    int RandomMove;

    // Start is called before the first frame update
    void Start()
    {
        rigid = GetComponent<Rigidbody2D>();        
    }

    // Update is called once per frame
    void Update()
    {
        UnityEngine.Random.InitState(DateTime.Now.Millisecond);
        changeTime += Time.deltaTime;

        if (changeTime > 0.5f)
        {
            RandomMove = UnityEngine.Random.Range(0, 4);

            switch (RandomMove)
            {
                case 0:
                    ToRight();
                    changeTime = 0f;
                    break;
                case 1:
                    ToLeft();
                    changeTime = 0f;
                    break;
                case 2:
                    ToUp();
                    changeTime = 0f;
                    break;
                case 3:
                    ToDown();
                    changeTime = 0f;
                    break;
            }

        }


    }

    public void ToRight()
    {
        rigid.AddForce(new Vector2(500, 0));
    }

    public void ToLeft()
    {
        rigid.AddForce(new Vector2(-500, 0));
    }

    public void ToUp()
    {
        rigid.AddForce(new Vector2(0,500));
    }

    public void ToDown()
    {
        rigid.AddForce(new Vector2(0,-500));
    }


}

deltaTime을 이용하여 일정 시간마다 랜덤으로 상/하/좌/우에 힘을 받게 만들어서 움직임을 부여 하기로 하였다.

 

그런데 위 코드를 그대로 사용하면 문제가 생기게 된다.

 

바로 화면 밖으로 나가게 되면 아예 맞추지 못하는 사태가 발생하게 되는 것이다.

 

따라서 대상의 좌표가 화면 특정 지점을 벗어나게 되면 무조건 반대 방향으로 힘을 받는 것이 우선하여 발동되게 하였다.

 

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

public class TargetMove : MonoBehaviour
{
    Rigidbody2D rigid;
    float changeTime = 0f;
    int RandomMove;
    float TargetA_MaxVel = 10f;

    // Start is called before the first frame update
    void Start()
    {
        rigid = GetComponent<Rigidbody2D>();        
    }

    // Update is called once per frame
    void Update()
    {
        UnityEngine.Random.InitState(DateTime.Now.Millisecond);
        changeTime += Time.deltaTime;

        if (transform.position.x < -8.3f)
        {
            ToRight();

        }

        if (transform.position.x > 8.3f)
        {
            ToLeft();

        }

        if (transform.position.y > 4.4f)
        {
            ToDown();

        }

        if (transform.position.y < -4.4f)
        {
            ToUp();
        }



        if (changeTime > 2.0f)
        {
            Debug.Log(rigid.velocity);
            RandomMove = UnityEngine.Random.Range(0, 3);

            switch (RandomMove)
            {
                case 0:
                    ToRight();
                    changeTime = 0f;
                    break;
                case 1:
                    ToLeft();
                    changeTime = 0f;
                    break;
                case 2:
                    ToDown();
                    changeTime = 0f;
                    break;
                case 3:
                    ToUp();
                    changeTime = 0f;
                    break;
            }

        }

    }

    public void ToRight()
    {

        if(rigid.velocity.x < TargetA_MaxVel) // 오른쪽 방향(+ x 방향)으로 최대 속도 미만일 경우, 
        {
            rigid.AddForce(new Vector2(50, 0));
        }
        else
        {
            rigid.velocity = new Vector2(TargetA_MaxVel, rigid.velocity.y);
        }


    }

    public void ToLeft()
    {
        if (rigid.velocity.x > TargetA_MaxVel*(-1))
        {
            rigid.AddForce(new Vector2(-50, 0));
        }
        else
        {
            rigid.velocity = new Vector2(TargetA_MaxVel*(-1), rigid.velocity.y);
        }
    }

    public void ToUp()
    {
        if(rigid.velocity.y < TargetA_MaxVel)
        {
            rigid.AddForce(new Vector2(0, 100));
        }
        else
        {
            rigid.velocity = new Vector2(rigid.velocity.x, TargetA_MaxVel);
        }

    }

    public void ToDown()
    {
        if (rigid.velocity.y > TargetA_MaxVel*(-1))
        {
            rigid.AddForce(new Vector2(0, -100));
        }
        else
        {
            rigid.velocity = new Vector2(rigid.velocity.x, TargetA_MaxVel*(-1));
        }
    }

}