노래찍기 기능추가 및 박스 파괴가 아니라 베이도록 수정
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18614e0561d48a748a839a354f0ff42a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
[System.Serializable]
|
||||
public class NoteData
|
||||
{
|
||||
public float time;
|
||||
public int position;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class BeatMapData
|
||||
{
|
||||
public List<NoteData> notes = new List<NoteData>();
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67b13dfc4dac3674380379246b8f6220
|
||||
@@ -0,0 +1,40 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
public class MapRecorder : MonoBehaviour
|
||||
{
|
||||
public AudioSource audioSource;
|
||||
private List<NoteData> recordedNotes = new List<NoteData>();
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (audioSource.isPlaying && Keyboard.current != null)
|
||||
{
|
||||
// 키패드 4, 5, 1, 2를 각각 0, 1, 2, 3번 인덱스에 매핑
|
||||
if (Keyboard.current.numpad4Key.wasPressedThisFrame) RecordNote(0); // 좌상
|
||||
if (Keyboard.current.numpad5Key.wasPressedThisFrame) RecordNote(1); // 우상
|
||||
if (Keyboard.current.numpad1Key.wasPressedThisFrame) RecordNote(2); // 좌하
|
||||
if (Keyboard.current.numpad2Key.wasPressedThisFrame) RecordNote(3); // 우하
|
||||
}
|
||||
}
|
||||
|
||||
void RecordNote(int pos)
|
||||
{
|
||||
NoteData note = new NoteData { time = audioSource.time, position = pos };
|
||||
recordedNotes.Add(note);
|
||||
|
||||
// 로그로 어떤 키를 눌렀는지 확인하기
|
||||
string posName = (pos == 0) ? "좌상(4)" : (pos == 1) ? "우상(5)" : (pos == 2) ? "좌하(1)" : "우하(2)";
|
||||
Debug.Log($"기록됨: {note.time:F2}초 / 위치: {posName}");
|
||||
}
|
||||
|
||||
public void SaveBeatMap()
|
||||
{
|
||||
BeatMapData data = new BeatMapData { notes = recordedNotes };
|
||||
string json = JsonUtility.ToJson(data, true);
|
||||
string path = Path.Combine(Application.streamingAssetsPath, "Map_Life.json");
|
||||
File.WriteAllText(path, json);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3dde370502e0759409a88f7bbe9f6f00
|
||||
@@ -0,0 +1,52 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
public class MusicSpawner : MonoBehaviour
|
||||
{
|
||||
public AudioSource audioSource;
|
||||
public GameObject[] cube;
|
||||
public Transform[] point;
|
||||
|
||||
// List<float> 대신 List<NoteData>를 사용합니다.
|
||||
private List<NoteData> spawnNotes = new List<NoteData>();
|
||||
private int nextSpawnIndex = 0;
|
||||
|
||||
void Start()
|
||||
{
|
||||
string filePath = Path.Combine(Application.streamingAssetsPath, "Map_Life.json");
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
string jsonString = File.ReadAllText(filePath);
|
||||
// JSON을 읽어서 NoteData 리스트로 가져옵니다.
|
||||
BeatMapData data = JsonUtility.FromJson<BeatMapData>(jsonString);
|
||||
spawnNotes = data.notes;
|
||||
}
|
||||
if (audioSource != null) audioSource.Play();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// 리스트가 비어있지 않은지 확인
|
||||
if (audioSource.isPlaying && nextSpawnIndex < spawnNotes.Count)
|
||||
{
|
||||
// 이제 리스트의 요소는 NoteData 객체이므로 .time과 .position에 접근 가능합니다.
|
||||
var currentNote = spawnNotes[nextSpawnIndex];
|
||||
|
||||
if (audioSource.time >= currentNote.time)
|
||||
{
|
||||
SpawnCube(currentNote.position);
|
||||
nextSpawnIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnCube(int pos)
|
||||
{
|
||||
// pos가 point 배열의 범위를 넘지 않도록 예외 처리
|
||||
if (pos >= 0 && pos < point.Length)
|
||||
{
|
||||
Instantiate(cube[0], point[pos].position, point[pos].rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9e23740cc2c239489d946a0270e4ffd
|
||||
@@ -1,33 +1,111 @@
|
||||
using System.ComponentModel.Design.Serialization;
|
||||
using UnityEngine;
|
||||
using EzySlice;
|
||||
|
||||
public class Saber : MonoBehaviour
|
||||
{
|
||||
|
||||
public LayerMask layer;
|
||||
Vector3 prevPos;
|
||||
//손잡이랑 검끝 사이를 레이 쏠 예정(검날)
|
||||
[Header("슬라이스용 직렬화")]
|
||||
public Transform startSlicePoint;
|
||||
public Transform endSlicePoint;
|
||||
public VelocityEstimator velocityEstimator; //속도측정기(검 끝에 달림)
|
||||
public LayerMask sliceableLayer; //하는김에 얘도 그냥 직렬화
|
||||
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
[Header("이펙트 세팅")]
|
||||
public Material cuttingMaterial; //절단면
|
||||
public float cutForce = 100f; //잘린 조각 튕기기
|
||||
|
||||
void Update()
|
||||
[Header("슬라이스 조건 설정")]
|
||||
[Range(60f, 160f)]
|
||||
public float sliceAngle = 100f; // 필요 각도 (직렬화해서 인스펙터에서 조절 가능하게)
|
||||
|
||||
[Tooltip("이 속도보다 빨라야만 슬라이싱이 작동합니다.")]
|
||||
public float swingSpeedThreshold = 2.0f; // 필요 최소 속도 (이 값을 조절해서 '갖다 대기'를 방지)
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
RaycastHit hit;
|
||||
|
||||
if(Physics.Raycast(transform.position, transform.forward, out hit, 1, layer))
|
||||
//Raycast는 위치값을 받는 클래스로 뒤의 인수는 위치, 방향, 저장되는 변수, 거리, layer에 해당되는것만
|
||||
//손잡이와 검 끝 사이에 선을 그어 체크
|
||||
bool hasHit = Physics.Linecast(
|
||||
startSlicePoint.position,
|
||||
endSlicePoint.position,
|
||||
out RaycastHit hit,
|
||||
sliceableLayer);
|
||||
|
||||
//체크됐으면
|
||||
if (hasHit)
|
||||
{
|
||||
Vector3 v1 = transform.position - prevPos; // 현재위치 - 이전 위치 = 이동방향
|
||||
|
||||
if(Vector3.Angle(v1, hit.transform.up) > 130)
|
||||
//두 벡터 사이의 벌어진 각도를 구하는 함수 이동방향v1과 충돌한 물체의 위쪽방향
|
||||
//hit 된 오브젝트를 타겟으로 자르기 메서드 실행
|
||||
GameObject target = hit.transform.gameObject;
|
||||
|
||||
Vector3 swingVelocity = velocityEstimator.Velocity;
|
||||
|
||||
float currentSwingSpeed = swingVelocity.magnitude;
|
||||
|
||||
if (currentSwingSpeed > swingSpeedThreshold) // 1단계: 속도 체크
|
||||
{
|
||||
Destroy(hit.transform.gameObject);
|
||||
// 5. 각도 체크
|
||||
// swingVelocity.normalized를 쓰면 크기를 무시하고 방향만 비교할 수 있어 더 정확합니다.
|
||||
float angle = Vector3.Angle(swingVelocity.normalized, target.transform.up);
|
||||
|
||||
if (angle > sliceAngle) // 2단계: 각도 체크
|
||||
{
|
||||
Slice(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prevPos = transform.position;
|
||||
}
|
||||
|
||||
//자르는 메서드
|
||||
public void Slice(GameObject target)
|
||||
{
|
||||
//1. 자를 평면 방향 구하기
|
||||
//1-1. 검 방향 벡터
|
||||
Vector3 saberDirection = endSlicePoint.position - startSlicePoint.position;
|
||||
|
||||
//1-2. 검 속도벡터(velocityEstimator.Velocity)
|
||||
Vector3 velocity = velocityEstimator.Velocity;
|
||||
|
||||
//1-3. 두 벡터의 수직인 벡터를 구해서 정규화 = 자르는 면의 방향
|
||||
Vector3 planeNormal = Vector3.Cross(saberDirection, velocity).normalized;
|
||||
|
||||
//2. 자르기
|
||||
SlicedHull hull = target.Slice(endSlicePoint.position, planeNormal, cuttingMaterial);
|
||||
if (hull == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//3. 위아래조각 생성(여기부턴 동일)
|
||||
GameObject upperHull = hull.CreateUpperHull(target, cuttingMaterial);
|
||||
GameObject lowerHull = hull.CreateLowerHull(target, cuttingMaterial);
|
||||
|
||||
//4. 조각들에 SetupHull 물리부여
|
||||
SetupHull(upperHull);
|
||||
SetupHull(lowerHull);
|
||||
|
||||
|
||||
//5. 원본은 삭제
|
||||
Destroy(target);
|
||||
}
|
||||
|
||||
|
||||
//물리 부여
|
||||
//얜 거의 안 건드리고 레이어 바꾸는 거만 추가
|
||||
void SetupHull(GameObject hull)
|
||||
{
|
||||
Rigidbody rb = hull.AddComponent<Rigidbody>();
|
||||
MeshCollider collider = hull.AddComponent<MeshCollider>();
|
||||
collider.convex = true;//물리충돌용
|
||||
|
||||
//잘린 면 방향으로 힘을 가해 튕기게
|
||||
rb.AddExplosionForce(cutForce, hull.transform.position, 1f);
|
||||
|
||||
//레이어 바꿔서 계속 잘리는 거 방지(소리엉킴)
|
||||
hull.layer = LayerMask.NameToLayer("Default");
|
||||
|
||||
Destroy(hull, 3f); // 3초 뒤 삭제
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,13 +7,6 @@ public class Spawner : MonoBehaviour
|
||||
public float beat = 1;
|
||||
float timer = 0f;
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if(timer > beat)
|
||||
@@ -21,10 +14,14 @@ public class Spawner : MonoBehaviour
|
||||
int c = Random.Range(0, 2);
|
||||
int p = Random.Range(0, 4);
|
||||
|
||||
GameObject obj = Instantiate(cube[c], point[p]); //beatBox를 랜덤하게 생성
|
||||
|
||||
obj.transform.localPosition = Vector3.zero; //박스의 벡터(방향을 초기화)
|
||||
obj.transform.Rotate(transform.forward, 90 * Random.Range(0, 4)); //박스의 회전(방향, 회전률)
|
||||
GameObject obj = Instantiate(cube[c], point[p].position, point[p].rotation);
|
||||
//GameObject obj = Instantiate(cube[c], point[p]); //beatBox를 랜덤하게 생성
|
||||
|
||||
obj.transform.Rotate(transform.forward, 90 * Random.Range(0, 4));
|
||||
|
||||
//obj.transform.localPosition = Vector3.zero; //박스의 벡터(방향을 초기화)
|
||||
//obj.transform.Rotate(transform.forward, 90 * Random.Range(0, 4)); //박스의 회전(방향, 회전률)
|
||||
|
||||
|
||||
timer -= beat;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
|
||||
//검 끝에 붙일 스크립트
|
||||
public class VelocityEstimator : MonoBehaviour
|
||||
{
|
||||
//속도값 전달용
|
||||
public Vector3 Velocity { get; private set; }
|
||||
|
||||
private Vector3 previousPosition;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
previousPosition = transform.position;
|
||||
}
|
||||
|
||||
//물리 연산 주기에 맞춰 속도 계산
|
||||
private void FixedUpdate()
|
||||
{
|
||||
//(현재 위치 - 이전 위치) / 시간 = 속도
|
||||
Velocity = (transform.position - previousPosition) / Time.fixedDeltaTime;
|
||||
previousPosition = transform.position;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c611db3f29508604b8d70ad30f9b4f3c
|
||||
Reference in New Issue
Block a user