private void GameOver()
{
game_ongoing = false;
keyInput = 0;
transform.position = initPosition;
transform.rotation = initRotate;
Debug.Log("Game Over");
}
게임오버 되고 나면
int hit1Index = hit1.collider?.GetComponentInParent<NoteBlock>()?.noteBlockIndex ?? -1;
int hit2Index = hit2.collider?.GetComponentInParent<NoteBlock>()?.noteBlockIndex ?? -1;
Debug.Log("Hit1 : " + hit1Index + ", Hit2 : " + hit2Index);
raycast에 collider가 입력되지 않아 hitIndex가 -1로만 고정되는 현상 발생
private void GameOver()
{
game_ongoing = false;
keyInput = 0;
missionBlockIndex = 0;
isInBox = false;
transform.position = initPosition;
transform.rotation = initRotate;
Debug.Log("Game Over");
}
isInBox를 초기화 안해줘서 그랬던 것
private void CheckMusic()
{
if (game_ongoing && !MainMusic.isPlaying)
{
MainMusic.Play();
}
}
update문에서 체크. 간단.
private void TurnWithNewPos()
{
Vector3 nextDirection = Vector3.zero;
if ((missionKeyType & KeyType.Up) != 0) nextDirection += Vector3.up;
if ((missionKeyType & KeyType.Down) != 0) nextDirection += Vector3.down;
if ((missionKeyType & KeyType.Left) != 0) nextDirection += Vector3.left;
if ((missionKeyType & KeyType.Right) != 0) nextDirection += Vector3.right;
float angle = Mathf.Atan2(nextDirection.y, nextDirection.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, 0, angle);
// 중앙과의 거리를 계산한 뒤 어긋난 거리만큼 플레이어 위치 조정
float distance = Vector2.Distance(missionBlockCollider.bounds.center, transform.position);
Debug.Log("Distance : " + distance);
Vector2 nextPos = missionBlockCollider.bounds.center - nextDirection.normalized * distance;
transform.position = new Vector3(nextPos.x, nextPos.y, rayLength / 10);
}
단순 distance로 했더니 빨리 눌러도 늦게 눌러도 똑같이 위치를 조정해버림.
private void TurnWithNewPos()
{
// 다음 방향을 계산만 해놓고, 위치 이동 후 방향 반영
Vector2 nextDirection = Vector3.zero;
if ((missionKeyType & KeyType.Up) != 0) nextDirection += Vector2.up;
if ((missionKeyType & KeyType.Down) != 0) nextDirection += Vector2.down;
if ((missionKeyType & KeyType.Left) != 0) nextDirection += Vector2.left;
if ((missionKeyType & KeyType.Right) != 0) nextDirection += Vector2.right;
nextDirection = nextDirection.normalized;
float angle = Mathf.Atan2(nextDirection.y, nextDirection.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, 0, angle);
// 중앙과의 거리를 계산한 뒤 어긋난 거리만큼 플레이어 위치 조정
// 이전 방향 벡터로 이전 위치에서 중심까지의 변위를 나눈 것은,
// 회전한 방향 벡터로 새로운 위치에서 중심까지의 변위를 나눈 것과 같다.
Vector3 centerPos = missionBlockCollider.bounds.center;
Vector2 displacement = centerPos - transform.position;
Vector2 nextPos;
if (displacement.normalized == nowDirection)
{
Debug.Log("Same Direction");
nextPos = (Vector2)centerPos - displacement.magnitude * nextDirection;
}
else
{
Debug.Log("Different Direction");
nextPos = (Vector2)centerPos + displacement.magnitude * nextDirection;
}
// Debug.Log("displacement :" + displacement);
// Debug.Log("NowDirection : " + nowDirection);
// Debug.Log("Mission Key Type: " + missionKeyType);
transform.position = new Vector3(nextPos.x, nextPos.y, rayLength / 10);
nowDirection = nextDirection;
}
해결책 떠올려내기도 힘들었고, 자료형 때문에 코드 정리하는 것도 힘들었다.
Vector2 nextPos = (Vector2)centerPos + displacement.magnitude
* (displacement.normalized == nowDirection ? -nextDirection : nextDirection);
gpt한테 좀 줄여달라고 해서 if else문도 trim
기본 게임 로직은 진짜 진짜 거의 다 끝났다
그냥 가상악기 추가하고 재생 누르면 midi 트랙에 가상 악기 알아서 적용되는거였다
prochannel에서 gain이나 output 조절해서 째질만큼 음량 키워도
export하면 째지지도 않고 평온하게 아무일도 없었다는듯이 작은 소리로 나옴
컴퓨터 자체 음량은 export에 상관없었다
일단 후순위니까 나중에

http://www.piano-midi.de/faq.htm
다른 midi 사이트들은 전부 상업적 이용 안된다고 했는데,
이 사람만 개인이 취미로 찍어낸거라 그런지 출처만 밝히면 무료로 써도 된다고 함.
문제는 midi 파일이 내가 생각했던 것처럼 기계적으로 박자 찍어내는게 기본인게 아니라,
연주 그 자체를 담은 파일이라 박자를 정확하게 맞출수가 없을수도 있다는거.
일단 적용시켜보자. 얼추 맞기만 하면 사실 엄밀하게 맞진 않아도 됨. 노트 당 길이만 정확하면 되는거니까.
대충 보기에는 나쁘지 않다.
하지만 자세히 보면 박자가 조금씩 어긋나기 시작한다는 걸 알 수 있다.
리듬 게임으로써 성립하기 어려울 정도로.
bpm의 문제일수도 있겠지만...
quantize라는거 있길래 해봤더니 음이 겹쳐져버려서 연주가 이상해져버림.
근데 좀 만지작거리다보니까 갑자기 살짝만 이상해지고 박자는 정확해졌다.
snap을 1/4로 바꿔서 그런건가?
https://www.youtube.com/watch?v=XVc6A6Mg1Ys
정석대로 하자면 이렇게 하면 된다. 마디마다 노가다로 이상한 부분 맞춰주기.
일단 해결책은 알았으니 넘어가자.
근데 이렇게 박자에 맞게 조절하는게 가능하면 그냥 무료 연주 파일 가져와도 될지도?
그건 midi 파일이 아니라 안되려나?
말 그대로 bpm이 높아서 플레이어가 빠르게 이동할 때 raycast가 노트 감지를 못한다.
분명히 잘만 되던게 갑자기 인식을 못해서 왜 그런가 하고 bpm을 내려봤더니 잘만 됨.
o1에게 코드를 긁어 물어봤다.
Raycast 로직을 Update()에서 한 번씩만 쏘고 있는데, speed(=1f / sec_per_quarter)가 너무 커지면(=BPM이 빠르면), 한 프레임에 이동하는 거리가 커집니다. Raycast()로만 체크하면 놓칠 수 있습니다. GameOver()가 호출되어야 할 타이밍을 놓치는 현상이 발생합니다.BPM이 높아지면 sec_per_quarter는 작아지고,
speed = 1f / sec_per_quarter
이 값이 커지므로,
transform.Translate(goingDirection * speed * Time.deltaTime);
를 통해 매 프레임 이동하는 거리가 커집니다.
예를 들어,
sec_per_quarter = 1, speed = 1. 즉, 초당 1유닛. sec_per_quarter = 0.25, speed = 4. 즉, 초당 4유닛. 이렇게 속도가 4배가 되면, 한 프레임(예: 60FPS에서 약 0.0167초)마다 약 0.067유닛씩 이동하던 것이 0.267유닛으로 이동하게 됩니다. rayLength를 고정 1로 두고 있다면, “레이를 쏘는 지점(front/back)에서 -Z 방향 1유닛 안에 충돌체가 있는지” 한 번만 검사하므로 중간에 놓칠 가능성이 높아집니다.
rayLength(현재 1f)를 늘려서 스킵되는 상황을 완화할 수 있습니다.Raycast 대신 Physics.Linecast(oldPos, newPos, out hit, layerMask) 등을 사용하면, “지난 프레임 위치”에서 “현재 프레임 위치”까지 선을 그어 그 사이에 충돌이 있는지 확인할 수 있습니다.private Vector3 _previousPosition;
void Start()
{
_previousPosition = transform.position;
}
void Update()
{
Vector3 currentPosition = transform.position;
// 이동하기 전에 Linecast로 충돌 체크
if (Physics.Linecast(_previousPosition, currentPosition, out RaycastHit hit, /*레이어 마스크*/))
{
// 충돌 로직 처리
}
// 실제 이동
transform.Translate(goingDirection * speed * Time.deltaTime);
// 다음 프레임을 위해 위치 갱신
_previousPosition = transform.position;
}
Physics2D 시스템의 OnTriggerEnter2D, 3D 게임이라면 OnTriggerEnter/OnCollisionEnter 같은 물리 이벤트를 이용하는 방법도 있습니다.Collider(또는 RigidBody)를 세팅하고, “Is Trigger” 등 적절한 모드를 설정해야 합니다.Update()에서 매 프레임마다 Physics.Raycast를 호출하고 있는데, Unity의 물리 연산은 기본적으로 FixedUpdate 타이밍(Physics Step)에서 처리됩니다.Project Settings > Time에서 Fixed Timestep을 더 작게 잡아서(예: 0.02 -> 0.01 등) 물리 연산 빈도를 늘릴 수도 있습니다.FixedUpdate() 안에서 처리하면 조금 더 안정적으로 충돌을 캐치할 수도 있습니다.로직을 갈아 엎어야 하는구나
raycast 쏴서 확인하는게 모든 로직하고 엮여 있는데 어떡하지
이제라도 collider로 갈아타야 되는건가
그거 말곤 방법이 없어보이긴 함
https://discussions.unity.com/t/collision-detection-for-fast-moving-objects/878384
translate도 문제였는듯