260903 Unity(4) prefab, 생성과 파괴, audio

무알콜 삼다수·2026년 9월 6일
post-thumbnail

1. prefab

1.1. 개요

  • 자주 쓰게 될 주제 1.
  • 클래스처럼 게임 오브젝트계의 클래스의 느낌.
  • 설계도를 짜서 복제품을 사용하는 느낌이다.
  • 작업을 하더라도 Scene 안에서만 돌 수 있는데 설계도를 만들면 어떤 Scene에서든 사용할 수 있다.
  • 공유할 수 있는 작업물의 형태를 만든다는 장점이 있다.
  • 게임이란 것은 프로그램이고 재활용 할 것을 파일로 준비해놓고 그것을 활용 가능하게끔 해야 한다.
  • 같은 캐릭터를 어느 Scene에서나 사용할 수 있어야 한다.
  • 그런데 계속 복사 붙여넣기 등을 할 순 없는 노릇이다.
  • 미리 데이터로 저장하는 것을 사용해야 한다.

1.2. 사용

  • 드래그 드랍으로 프로젝트 창에 둔다.
  • 이제 Hierachy에 있는 것을 지우고 다시 프로젝트 안에 아까 만든 것을 넣어줄 수 있다.
  • 그래서 프리팹을 기반으로 만들어진 것들을 사용한다.
  • 게임을 만들 때는 특정 맵을 Prefab, UI 등을 미리 설계된 오브젝트 단위를 재활용 할 수 있도록 하는 것이 프리팹, 게임 오브젝트의 설계도이다. 이렇게 원본을 수정하면 일괄 적용된다.
    다른 객체 하나를 고치다가 일괄 적용도 되는데 하지만 구분되어 생성하는 것이 중요하다. 원본이 훼손되면 안될 경우가 있기 때문.
    이번엔 다른 예제로 만들어보자.이것을 오브젝트에 아까처럼 객체 하나에다가 넣고 일괄 적용하면 원본에도 적용됨을 볼 수 있음.
    게임 오브젝트에 대한 것을 Prefab으로 관리가 가능하다.이것을 통해 생성을 해볼 것이다. Update로.이런 형식일 것인데 로 생성할 수 있고 엄청나게 많은 수가 생성이 된다.
    그러나 Destroy를 적용하면파괴가 안된다.
  • Player 변수에 어떤 것이 들어가있냐면 Player의 프리팹이 들어가있다.
  • 그런데 객체를 없애야 하는데 설계도를 없애봐야 소용이 없다.
  • 내부적으로 List를 써야 한다.파괴하는 시점에서는 반대로 게임 오브젝트를 꺼내서 제거해야 한다.p를 꺼내오지 않으면 어떤 것을 파괴할지 모르기 때문에 두 줄이 핵심인 셈.
    실행은 되는데 한가지 걸린다. 배열 밖으로 벗어나는 것이 찍히기 때문이다.
    벗어나면 return을 하면 된다.

2. 생성과 파괴

2.1. 개요

  • 자주 쓰게 될 것 2.
  • 생성 당시에 옵션을 줄 수 있으나 기억해야 할 함수 이름은 Instantiate와 Destroy이다.

2.2. 사용

터렛을 예시로 만들어볼 것이다.프리팹으로까지의 과정을 진행.
탄환까지 프리팹으로 진행.Bullet을 만들었을 때 무엇이 필요할까? 이렇게 필요할 것이고 적용을 시키면이제 TurretController로 이동.하지만 충돌 처리를 배우고 나면 이런 느낌은 아닐 것이다.

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

public class TurretController : MonoBehaviour
{
    // 탄환 소환
        // 총구 위치에
    [SerializeField] private GameObject _bulletPrefab;
    [SerializeField] private Transform _muzzlePoint;
    [SerializeField] private float _coolTime;
    [SerializeField] private Transform _playerTransform;
    [SerializeField] private float _rotateSpeed;
    [SerializeField] private float _detectionRange;
    
    //private float _timer;
    // 플레이어가 특정 거리 밖에 있을 때 돈다.
    // 일정 거리 안이면 플레이어 응시.
    private void Update()
    {
        
        //_timer += Time.deltaTime;
        _coolTime += Time.deltaTime;
        
        float distance = Vector3.Distance(transform.position, _playerTransform.position);
        if (distance <= _detectionRange)
        {
            LookAtPlayer();
            if (_coolTime >= 1)
            {
                SpawnBullet();
                _coolTime = 0;
            }
        }
        else
        {
            RotateTurret();
        }
    }

    private void RotateTurret()
    {
        transform.Rotate(Vector3.up, _rotateSpeed * Time.deltaTime);
    }

    private void LookAtPlayer()
    {
        transform.LookAt(_playerTransform);
    }

    private void SpawnBullet()
    {
        // 쿨타임. deltaTime 누적
        /*if(_coolTime >= _timer)
            return;*/
        
        Instantiate(_bulletPrefab, transform);
        
        /*GameObject bullet = Instantiate(_bulletPrefab);
        bullet.transform.position = _muzzlePoint.position;
        bullet.transform.rotation = _muzzlePoint.rotation;*/
        
        //_timer = 0;
    }
        
    
    // 격발음
}

3. Audio

3.1. 설명

  • 오디오 소스와 리스너로 페어지금 격발음이 한 번에 들어와야 하는데 음원 파일이라는 것이 나고 유지되는 시간이 필요하고 하나로만 처리하면 끊기고 소리가 나니 여러개가 있을 필요가 있음.
    터렛이 아닌 총알이 오디오 소스를 갖는 상황으로 생각해볼 것.그럼 소스 코드에서 해보자.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletController : MonoBehaviour
{
    // 앞으로 날아가는 것
    [SerializeField] private float _speed;
    [SerializeField] private float _destroyTime;
    
    [SerializeField] private AudioSource _audioSource;
    [SerializeField] private AudioClip _audioClip;
    
    private void Awake()
    {
        // 오디오 접근
        _audioSource = GetComponent<AudioSource>();
        _audioSource.loop = false;
        _audioSource.Stop();
        _audioSource.clip = _audioClip;
        _audioSource.Play();
        
        
        Destroy(gameObject, _destroyTime);
    }

    private void Update()
    {
        MoveForward();
    }

    private void MoveForward()
    {
        transform.Translate(Vector3.forward * _speed * Time.deltaTime);
    }
    
    
    // 충돌 체크
    
}
  • 오디오 리스너가 없으면 콘솔에서 경고를 띄워준다.

4. 정리

  • 힙, 메모리에 축적이 되었다가 관리되는 힙 영역을 청소하는데 Frame이 튈 수 있고 그것을 조심해야 한다.
  • 생성 파괴를 최소화하는 운용 기법이 필요함.
  • 에셋 스토어에서 에셋을 볼 때 빌트인 환경이 되는지를 확인할 것.
  • 무료 에셋이라고 해도 .gitignore 단에서 차단되게끔 Import라고 폴더를 별도로 만들어 거기에 에셋들을 두고 이 폴더의 하위들이 git에 올라가지 않도록 관리를 하는 것이 좋을 것이다.
profile
아주몹시매우엄청대왕초보 게임 개발자의 끄적

0개의 댓글