using UnityEngine;
[System.Serializable]
public class Sound
{
public string name;//사운드 이름
public AudioClip clip;//사운드 파일
private AudioSource source;//사운드 플레이어
public float volumn;
public bool loop;
public void SetSource(AudioSource _source)
{
source = _source;
source.clip = clip;
source.loop = loop;
}
public void SetVolumn()
{
source.volume = volumn;
}
public void Play()
{
source.Play();
}
public void Stop()
{
source.Stop();
}
public void SetLoop()
{
source.loop = true;
}
public void SetLoopCancel()
{
source.loop = false;
}
}
public class AudioManager : MonoBehaviour
{
static public AudioManager instance;
[SerializeField]
public Sound[] sounds;
private void Awake()
{
if (instance == null)
{
DontDestroyOnLoad(this.gameObject);
instance = this;
}
else
{
Destroy(this.gameObject);
}
}
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
for (int i = 0; i < sounds.Length; i++)
{
GameObject soundObjcet = new GameObject("사운드 파일 이름 : " + i + " = " + sounds[i].name);
sounds[i].SetSource(soundObjcet.AddComponent<AudioSource>());
soundObjcet.transform.SetParent(this.transform);
}
}
public void Play(string _name)
{
for(int i = 0; i < sounds.Length; i++)
{
if(_name == sounds[i].name)
{
sounds[i].Play();
return;
}
}
}
public void Stop(string _name)
{
for (int i = 0; i < sounds.Length; i++)
{
if (_name == sounds[i].name)
{
sounds[i].Stop();
return;
}
}
}
public void SetLoop(string _name)
{
for (int i = 0; i < sounds.Length; i++)
{
if (_name == sounds[i].name)
{
sounds[i].SetLoop();
return;
}
}
}
public void SetLoopCancel(string _name)
{
for (int i = 0; i < sounds.Length; i++)
{
if (_name == sounds[i].name)
{
sounds[i].SetLoopCancel();
return;
}
}
}
public void SetVolumn(string _name, float _Volumn)
{
for (int i = 0; i < sounds.Length; i++)
{
if (_name == sounds[i].name)
{
sounds[i].volumn = _Volumn;
sounds[i].SetVolumn();
return;
}
}
}
}
using System.Collections;
using UnityEngine;
public class MovingObjcet : MonoBehaviour
{
static public MovingObjcet instance;
public string currentMapName;//transferMap 스크립트에 있는 transferMapName변수의 값을 저장
private BoxCollider2D boxCollider;//박스콜라이더
public LayerMask layerMask;//통과불가 에이리어 설정
public string walkSound_1;
public string walkSound_2;
public string walkSound_3;
public string walkSound_4;
private AudioManager theAudio;
//public AudioClip walkSound_1;//사운드 파일
//public AudioClip walkSound_2;
private AudioSource audioSource;//사운드 플레이어
//케릭터 이동속도
public float speed;
//벡터(케릭터의 이동 방향)
private Vector3 vector;
//뛰기,평범하게 걷기
public float runSpeed;
private float applyRunSpeed;
private bool applyRunFlag = false;
//픽셀 단위로 움직이기 구현
public int walkCount;
private int currentWalkCount;
//한칸한칸 이동할때 플레그 형식으로 구현
private bool canMove = true;
private Animator animator;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
if(instance == null)
{
DontDestroyOnLoad(this.gameObject);
boxCollider = GetComponent<BoxCollider2D>();
//audioSource = GetComponent<AudioSource>();
animator = GetComponent<Animator>();
theAudio = FindAnyObjectByType<AudioManager>();
instance = this;
}
else
{
Destroy(this.gameObject);
}
}
//코루틴으로 이동제어 한칸 한칸 이동하게
IEnumerator MoveCoroutine()
{
while(Input.GetAxisRaw("Vertical") !=0 || Input.GetAxisRaw("Horizontal") != 0)
{
//시프트 키 입력 여부에 따라 뛰기 걷기 구분
if (Input.GetKey(KeyCode.LeftShift))
{
applyRunSpeed = runSpeed;
applyRunFlag = true;
}
else
{
applyRunSpeed = 0;
applyRunFlag = false;
}
//이동방향 벡터 움직임 구현
vector.Set(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"), transform.position.z);
//좌상,좌하 등 대각선 방향이동 장금
if(vector.x !=0)
vector.y = 0;
//에니메이터 불러오기
animator.SetFloat("DirX", vector.x);
animator.SetFloat("DirY", vector.y);
RaycastHit2D hit;//레이케스트
Vector2 start = transform.position; //캐릭터의 현제 위치 값
Vector2 end = start + new Vector2(vector.x * speed * walkCount, vector.y * speed * walkCount);
//캐릭터가 이동하고자하는 위치 값 그리고 사이즈
boxCollider.enabled = false;
hit = Physics2D.Linecast(start, end, layerMask);
boxCollider.enabled = true;
if (hit.transform != null)
break;
animator.SetBool("Walking", true);
int temp = Random.Range(1, 4);
switch (temp)
{
case 1:
theAudio.Play(walkSound_1);
break;
case 2:
theAudio.Play(walkSound_2);
break;
case 3:
theAudio.Play(walkSound_3);
break;
case 4:
theAudio.Play(walkSound_4);
break;
}
theAudio.SetVolumn(walkSound_2, 0.5f);
//캐릭터 이동구현 코드
while (currentWalkCount < walkCount)
{
if (vector.x != 0)
{
//Translate는 현제 값에서 +를 해주는 코드
transform.Translate(vector.x * (speed + applyRunSpeed), 0, 0);
}
else if (vector.y != 0)
{
transform.Translate(0, vector.y * (speed + applyRunSpeed), 0);
}
if (applyRunFlag)
currentWalkCount++;//위의 applyRunFlas가 되면 추가되는 카운트 만약 아니라면 더해지지 않음
currentWalkCount++;//위의 카운트와는 별개의 카운트로 구분 됨
yield return new WaitForSeconds(0.01f);//0.01초마다 대기
/*if(currentWalkCount % 9 == 2)
{
int temp = Random.Range(1, 2);
switch (temp)
{
case 1:
//audioSource.clip = walkSound_1;
//audioSource.Play();
break;
case 2:
//audioSource.clip = walkSound_2;
//audioSource.Play();
break;
}
}*/
}
currentWalkCount = 0;//0을 넣어서 반복문 초기화
}
animator.SetBool("Walking", false);
//한칸한칸 이동할때 bool값
canMove = true;
}
//매 프레임마다 이동명령을 받음
void Update()
{
if (canMove)
{
//이동 방향키 입력을 할때 쯔구르 처럼 상하좌우 구분하게 하는 코드
if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
{
//한칸 한칸 이동할때 bool값으로 canMove를 이용함
canMove = false;
StartCoroutine(MoveCoroutine());
}
}
}
}
오늘 시간에는 게임효과를 내기 위해 오디오매니져를 만들어보겠다
각각의 객체가 사운드를 관리하는 법을 알아본다
일단 MovingObject 스크립트에 들어간다
이렇게 작성해준다
그러면 인스팩터에 변수로 뜨게되는데 여기서 Audio칩을 추가해 줄 수 있다
그리고 사운드를 관리해주기 위해서는
오디오 소드 컴포넌트를 추가해줘야한다
컴포넌트를 추가해줬으니 당연히 오디오 소스를 GetComponent해준다
그뒤 움직일때 재생이 되게해준다
맨위에 if문에 있는 공식은 currentWalkCount를 9로 나눌때 2가 나온다면 이라는 조건인데
인스팩터에 WalkCount가 20이고 이걸 9로 나누면 18을 빼고 2가 남으므로 소리가 재생된다
int temp로 변수를 만들고 랜덤함수 2개를 1,2만들어 넣고
그리고 스위치 문으로 소리를 2가지로 만들어 놓는다 그럼 랜덤하게 발자국 소리가 들린다
이제 마지막으로 사운드 재생인
코드를 적어 넣는다
이렇게 하면 소리가 난다
단 아직은 씬을 이동하면 오디오소스가 같이 안온다
다음은 오디오 매니져로 통합 관리하는 법을 알아본다
오디오 매니져(AudioManager)스크립트를 만든다
일단 사운드를 배열로 넣고
이렇게 작성해준다
볼륨(volum)과 반복(loop)도 작성해준다
source에 _source를 넣어주고 소스 칩(source.clip)을 설정해주면서 반복(loop)를 넣어주는 함수를 만들어 준다
여기서 주의할 점이 있는데 커스텀 클레스는 public로 만들어도 인스펙터에 나오지 않는다
따라서 강제로 인스팩터에 나오기하기 위해
위 두가지 함수를 이용해서 인스펙터에 나오게 한다
이제 이 소스를 오디오 메니져에서 이용하게 코드를 작성해준다
1째 줄
게임 오브젝트 변수를 만들어주고 뉴게임 오브젝트 이름은 이름+숫자+사운드 숫자 이름으로 만들어준다
2째줄
사운드[숫자].세팅 사운드(SetSource) (사운드 오브젝트.AddComponent<AudioSource>());로 만들어서
겟컴포넌트를 잡아준다
여기까지 작성하면
오디오 메니져에 이렇게 나올탠데 발자국 소리 4개를 전부 넣어주자
볼륨크기는 1이 최대이다
그런데 이렇게 작성해주면 하이러키 창에 이렇게 지저분하게 한꺼번에 뜨게 된다
스크립트 상으로 다른 오브젝트의 하위에 넣기 위해
SetParent(this.transform)을 넣어주자
그러면 이렇게 이동된다
이제 플레이어가 이동할때마다 사운드가 들리게 만들어 준다
MovingObject에 string로 코드를 아래처럼 작성해준다
코드를 문자열(string)로 작성한 이유는 문자열로 받아오기 위함이다
void start에 오디오 매니저를 찾아와 장착한다
if문을 작성해주고
아래같이 작성해준다
그리고 오디오 매니져로 들어가서
Play를 작성해준다
함수 이름은 Play이고 (문자열로 값을 받아와서)
반복문으로 잡아오고 이름이 인스팩터에 해당하는 이름을 바아와서
사운드를 플레이 해준다
찾와왔으니 return으로 함수를 끝내준다
위쪽 클레스에는 플레이 함수가 없으므로
작성해준다
MovingObject에 마저 작성해준다
인스팩터에 들어와서 이렇게 순서대로 똑같이 적어준다
이렇게 하면 걷는 소리가 잘 들린다
이제 나머지 기능들도 작성해준다
재생,중지,반복,반복중지
그리고 호출될 함수들이다
재생,정지,반복,반복정지, 볼륨
그리고 MovingObject에서 이렇게 코드를 넣어주면 소리를 줄일 수 있다
그리고 오디오메니져에도 씬을 이동할때 파괴됨을 방지하기 위해 void Awake에 인스턴스를 작성해준다
'쯔꾸르식 유니티 게임 공부' 카테고리의 다른 글
6.개량 씬과 씬 이동하면서 위치 지정하기 (0) | 2025.01.05 |
---|---|
09.BGM매니져(배경음) (1) | 2025.01.03 |
7개량.카메라 영역 제한하기 개량(OnTrigger인식) (0) | 2025.01.02 |
07.카메라를 영역을 맵 화면으로 제한하기 (0) | 2025.01.01 |
06.맵과 맵을 이동하기 (0) | 2024.12.31 |