오늘 학습 키워드
유니티 입문 팀 프로젝트 4일차
오늘 학습 한 내용을 나만의 언어로 정리하기
사운드 매니저 만들기
- 기본적인 틀은 저번에 만들었던 TopDown에서 가져왔음.
// SoundManager.cs
public class SoundManager : MonoBehaviour
{
public static SoundManager instance;
[SerializeField][Range(0f, 1f)] private float soundEffectVolume;
[SerializeField][Range(0f, 1f)] private float musicVolume;
private AudioSource musicAudioSource;
public AudioClip musicClip;
public SoundSource soundSourcePrefab;
private void Awake()
{
instance = this;
DontDestroyOnLoad(gameObject);
musicAudioSource = GetComponent<AudioSource>();
musicAudioSource.volume = musicVolume;
musicAudioSource.loop = true;
}
private void Start()
{
ChangeBackGroundMusic(musicClip);
}
public void ChangeBackGroundMusic(AudioClip clip)
{
musicAudioSource.Stop();
musicAudioSource.clip = clip;
musicAudioSource.Play();
}
public static AudioSource PlayClip(AudioClip clip, bool loop)
{
SoundSource obj = Instantiate(instance.soundSourcePrefab);
SoundSource soundSource = obj.GetComponent<SoundSource>();
return soundSource.Play(clip, instance.soundEffectVolume, loop);
}
}
public class SoundSource : MonoBehaviour
{
private AudioSource _audioSource;
public AudioSource Play(AudioClip clip, float soundEffectVolume, bool loop)
{
if (_audioSource == null)
_audioSource = GetComponent<AudioSource>();
CancelInvoke();
_audioSource.clip = clip;
_audioSource.volume = soundEffectVolume;
_audioSource.loop = loop;
_audioSource.Play();
if(!loop) Invoke("Disable", clip.length + 2);
return _audioSource;
}
public void Disable()
{
_audioSource?.Stop();
Destroy(this.gameObject);
}
}
슬라이드 소리 처리
- 슬라이드는 키를 누르고 있으면 계속 함수를 호출하다보니 AudioSource가 너무 많이 생성되는 문제가 있었음.
- 그래서 차라리 AudioSource를 플레이어가 가지고 있게 하도록 했음.
- 플레이어가 Slide Source를 가지고 있으면 슬라이드 소리를 출력하지 않도록 함
// 슬라이드 키 누르고 있을 때 작동되는 부분
public void StartSliding()
{
// Debug.Log("Slide");
if (slideSource == null) slideSource = SoundManager.PlayClip(slideSound, true);
isSlide = true;
StartSlide();
jumpCount = 0;
}
// 슬라이드 키 뗄 때 작동되는 부분
public void StopSliding(InputAction.CallbackContext context)
{
// Debug.Log("Stop Slide");
isSlide = false;
OnSlideAnimationEnd();
if(slideSource != null)
{
slideSource.gameObject.GetComponent<SoundSource>()?.Disable();
slideSource = null;
}
}
맞으면 다른 행동 못하게 잠깐 막기
- 이거 어떻게 해야하나 고민 많이 했는데, 같은 팀원분들이 이런 코드가 있다고 해서 좀 찾아봄
InputAction targetAction = inputActions.FindAction(actionName); // 이걸로 특정 액션 찾고
targetAction.Disable(); // 비활성화
targetAction.Enable();
- 그래서 좀 더 찾아봐서, 모든 입력이 안되도록 만들어봄
// 그냥 맞은거
public void StartInvincible()
{
CancelInvoke("EndInvincible");
if (!isInvincible) aniHandler.StartInvincible();
isInvincible = true;
playerInput.currentActionMap.Disable(); // 그냥 맞은거면 Disable
Invoke("EndInvincible", invincibleTime);
}
// 아이템 써서 무적 시작부분
public void StartInvincible(float itemInvincibleTime)
{
CancelInvoke("EndInvincible");
if (!isInvincible) aniHandler.StartInvincible();
isInvincible = true;
Invoke("EndInvincible", itemInvincibleTime);
}
public void EndInvincible()
{
// 무적 끝나는 부분
// Debug.Log("End Invincible");
playerInput.currentActionMap.Enable();
isInvincible = false;
aniHandler.EndInvincible();
}
학습하며 겪었던 문제점 & 에러
문제 1
- 문제&에러에 대한 정의
플레이어가 공격 판정을 할 때 Attack Pivot을 활성화 시켜, 그 안에 있는 콜라이더와의 접촉 여부를 체크하려 했음. 하지만 Attack Pivot의 OnTriggerEnter와 플레이어의 OnTriggerEnter가 동시에 일어나는 것으로 보임
- 해결 방법
Player의 자식 오브젝트로 Attack Pivot이 있어서 생긴 일입니다. 자식에서 충돌이 일어나면 부모도 그 충돌을 감지하기 때문에, Attack Pivot을 Player의 자식 오브젝트가 아닌 형제 오브젝트로 있도록 변경하기
- 새롭게 알게 된 점
자식 오브젝트의 콜라이더에 부딪혀도 부모도 인지한다!!!
문제 2
- 문제&에러에 대한 정의
애니메이터가 싹 다 사라졌다.. 그리고는 오류가 났다.
NullReferenceException: Object reference not set to an instance of an object
UnityEditor.Graphs.AnimationStateMachine.Graph.GenerateConnectionKey (UnityEditor.Graphs.Node srcNode, UnityEditor.Graphs.Node dstNode) (at <4017f98979a4402db3b23276f8a9e04e>:0)
- 내가 한 시도
일단 애니메이터를 복붙해서 그 파일은 괜찮은지 확인해 보았으나 여전히 오류가 남.
- 해결 방법
껏다 키니 나았음.
- 새롭게 알게 된 점
애니메이터 파일은 YAML 형식으로 되어있다. 그러니 깨진 것 같으면 한번 메모장으로 열어보자.
- 이 문제&에러를 다시 만나게 되었다면?
애니메이터 파일 열어보고 별 문제 없으면 그냥 껐다 켜보자.
문제 3
- 문제&에러에 대한 정의
슬라이드 키를 뗐을 때 빠르게 일어나지 않았음. + 제대로 끝나지 않았을 때 버벅임
원래 코드는 아래와 같았음. 기존의 슬라이드는 키가 입력되고 있을 때 계속 부르는 방식이었음 (fixed update에서 키 확인받고 호출)
private void FixedUpdate()
{
...
if (slideAction.action.IsPressed()) StartSliding();
}
- 내가 한 시도
기존의 방식에서 바꿔서 action.started 에 StartSlide를 할당했음
private void Start()
{
...
// 슬라이드 액션 설정
slideAction.action.started += StartSliding;
slideAction.action.canceled += StopSliding;
}
- 해결 방법
저 시도를 하니까 자연스럽게 됐음!
- 새롭게 알게 된 점
어차피 키가 눌리는 동안 실행되는거라면 키가 눌렸을 때 (Started), 키를 뗐을 때 (Canceled) 각각 설정해 두는 것도 답이다.
- 이 문제&에러를 다시 만나게 되었다면?
내가 구현할 애니메이션의 형태에 따라 방법을 잘 생각해 봐야겠다.
내일 학습 할 것은 무엇인지
속도 증가 / 맞으면서 딜넣는거 막기 / 피 감소