티스토리 뷰

어제 에니메이터랑 뭐여러가지에서 놓치는 부분이 많았는데 이제 아주 익숙해졌다 하하 그래서 오늘은 사진이 없다 티스토리에 올리기 편해서 좋다..

그리고 과제도 나름 빠르게 하는 것 같다 뿌듯…


💻 Unity

Update vs FixedUpdate

구분  Update() FixedUpdate()
실행 빈도 프레임마다 실행 (FPS에 따라 변동) 물리 업데이트마다 일정한 시간 간격으로 실행
사용 목적 입력 처리, 애니메이션, UI 업데이트 등 물리 엔진을 사용하는 오브젝트(Rigidbody) 업데이트
시간 간격 Time.deltaTime 사용 Time.fixedDeltaTime 사용 (기본값 0.02초)
예제 사용처 transform.position += Vector3.forward * speed * Time.deltaTime; rigidbody.velocity = new Vector3(1, 0, 0);

Rigidbody와 Collider

Rigidbody 물리 연산(중력, 힘, 충돌 등)을 적용하기 위한 물리 엔진 컴포넌트
Collider 물리적인 충돌 영역을 정의하는 컴포넌트 (실제 렌더링되지 않음)
  • Rigidbody 없이 Collider만 있으면: 충돌 감지는 가능하지만 물리적인 반응 없음
  • Collider 없이 Rigidbody만 있으면: 물리 연산 적용되지만, 충돌 감지 불가능
  • 둘 다 있으면 : 정상적인 물리 연산(중력, 충돌, 반응) 수행 가능

🕹️ 게임 만들기

1945

Player

public float moveSpeed = 5f;
public Animator MyAnimator;

// 총알
public GameObject MyBullet;
public Transform pos = null;

// 아이템

// 레이저

private Vector2 minBounds;
private Vector2 maxBounds;

void Start()
{
    MyAnimator = GetComponent<Animator>();
    SetCameraBound();
}

private void SetCameraBound()
{
    // 화면 경계 설정
    Camera cam = Camera.main;
    Vector3 bottomLeft = cam.ViewportToWorldPoint(new Vector3(0, 0, 0));
    Vector3 topRight = cam.ViewportToWorldPoint(new Vector3(1, 1, 0));

    minBounds = new Vector2(bottomLeft.x, bottomLeft.y);
    maxBounds = new Vector2(topRight.x, topRight.y);
}

void Update()
{
    MovePlayer();
    SetAnimation();
    FireBullet();
}

private void MovePlayer()
{
    float moveX = Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime;
    float moveY = Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime;

    Vector3 newPosition = transform.position + new Vector3(moveX, moveY, 0);

    // 경계를 벗어나지 않도록 위치 제한
    newPosition.x = Mathf.Clamp(newPosition.x, minBounds.x, maxBounds.x);
    newPosition.y = Mathf.Clamp(newPosition.y, minBounds.y, maxBounds.y);

    transform.position = newPosition;
}

private void FireBullet()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Instantiate(MyBullet, pos.position, Quaternion.identity);
    }
}

private void SetAnimation()
{
    if (Input.GetAxis("Horizontal") <= -0.25f)
    {
        MyAnimator.SetBool("left", true);
    }
    else
    {
        MyAnimator.SetBool("left", false);
    }

    if (Input.GetAxis("Horizontal") >= 0.25f)
    {
        MyAnimator.SetBool("right", true);
    }
    else
    {
        MyAnimator.SetBool("right", false);
    }

    if (Input.GetAxis("Vertical") >= 0.25f)
    {
        MyAnimator.SetBool("up", true);
    }
    else
    {
        MyAnimator.SetBool("up", false);
    }
}

HomingBullet

public GameObject Target; // 플레이어
public float moveSpeed = 3f;
Vector2 homingVector;
Vector2 normalizedHomingVector;

void Start()
{
    SetHomingVector();
}

void Update()
{
    transform.Translate(normalizedHomingVector * moveSpeed * Time.deltaTime);
}

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.CompareTag("Player"))
    {
        Destroy(gameObject);
        // 플레이어 지우기
    }
}

private void SetHomingVector()
{
    Target = GameObject.FindGameObjectWithTag("Player");
    homingVector = Target.transform.position - transform.position; // A - B : A를 바라보는 벡터 (Player - HBullet)
    normalizedHomingVector = homingVector.normalized; // Normalize

    //transform.position = Vector3.MoveTowards(transform.position, Target.transform.position, moveSpeed * Time.deltaTime);
}

private void OnBecameInvisible()
{
    Destroy(gameObject);
}

SpawnManager

public float spawnStartX = -2;
public float spawnEndX = 2;
public float spawnStartTime = 1;
public float spawnStopTime = 10;
public GameObject MyMonster;
public GameObject MyMonster2;

private bool isMonster1 = true;
private bool isMonster2 = true;

void Start()
{
    StartCoroutine("RandomSpawn");
    Invoke("Stop", spawnStopTime);
}

IEnumerator RandomSpawn()
{
    while (isMonster1)
    {
        yield return new WaitForSeconds(spawnStartTime);
        float x = Random.Range(spawnStartX, spawnEndX);
        Vector2 pos = new Vector2(x, transform.position.y);
        Instantiate(MyMonster, pos, Quaternion.identity);
    }
}

IEnumerator RandomSpawn2()
{
    while (isMonster2)
    {
        yield return new WaitForSeconds(spawnStartTime + 2);
        float x = Random.Range(spawnStartX, spawnEndX);
        Vector2 pos = new Vector2(x, transform.position.y);
        Instantiate(MyMonster2, pos, Quaternion.identity);
    }
}

private void Stop()
{
    isMonster1 = false;
    StopCoroutine("RandomSpawn");

    isMonster2 = true;
    StartCoroutine("RandomSpawn2");
    Invoke("Stop2", spawnStopTime + 20);
}

private void Stop2()
{
    isMonster2 = false;
    StopCoroutine("RandomSpawn2");

    // 보스
}

📝 과제

적 사망시 아이템 드롭, 데미지 강화 구현

public static GameManager Instance;

private int _gainedItemCnt;
public int GainedItemCnt
{
    get { return _gainedItemCnt;  }
    set
    {
        if (_gainedItemCnt != value)
        {
            _gainedItemCnt = value;
        }
    }
}
public int DropedItemCnt = 0;

public float AttackPower = 10;

private void Awake()
{
    if (Instance == null)
    {
        Instance = this;
    }

    GainedItemCnt = 0;
}
public float moveSpeed = 5f;
public Animator MyAnimator;

// 총알
public GameObject MyBullet;
public GameObject MyBullet2;
public GameObject MyBullet3;
public GameObject MyBullet4;
public Transform pos = null;

// 아이템

// 레이저
private Vector2 minBounds;
private Vector2 maxBounds;

void Start()
{
    MyAnimator = GetComponent<Animator>();
    SetCameraBound();
}

private void SetCameraBound()
{
    // 화면 경계 설정
    Camera cam = Camera.main;
    Vector3 bottomLeft = cam.ViewportToWorldPoint(new Vector3(0, 0, 0));
    Vector3 topRight = cam.ViewportToWorldPoint(new Vector3(1, 1, 0));

    minBounds = new Vector2(bottomLeft.x, bottomLeft.y);
    maxBounds = new Vector2(topRight.x, topRight.y);
}

void Update()
{
    MovePlayer();
    SetAnimation();
    FireBullet();
}

private void MovePlayer()
{
    float moveX = Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime;
    float moveY = Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime;

    Vector3 newPosition = transform.position + new Vector3(moveX, moveY, 0);

    // 경계를 벗어나지 않도록 위치 제한
    newPosition.x = Mathf.Clamp(newPosition.x, minBounds.x, maxBounds.x);
    newPosition.y = Mathf.Clamp(newPosition.y, minBounds.y, maxBounds.y);

    transform.position = newPosition;
}

private void FireBullet()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        switch (GameManager.Instance.GainedItemCnt)
        {
            case 0:
                Instantiate(MyBullet, pos.position, Quaternion.identity);
                break;
            case 1:
                Instantiate(MyBullet2, pos.position, Quaternion.identity);
                break;
            case 2:
                Instantiate(MyBullet3, pos.position, Quaternion.identity);
                break;
            case 3:
                Instantiate(MyBullet4, pos.position, Quaternion.identity);
                break;
            default:
                break;
        }
    }
}

private void SetAnimation()
{
    if (Input.GetAxis("Horizontal") <= -0.25f)
    {
        MyAnimator.SetBool("left", true);
    }
    else
    {
        MyAnimator.SetBool("left", false);
    }

    if (Input.GetAxis("Horizontal") >= 0.25f)
    {
        MyAnimator.SetBool("right", true);
    }
    else
    {
        MyAnimator.SetBool("right", false);
    }

    if (Input.GetAxis("Vertical") >= 0.25f)
    {
        MyAnimator.SetBool("up", true);
    }
    else
    {
        MyAnimator.SetBool("up", false);
    }
}
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함