블럭 중복 조합 방지
public void ValidateCombinations()
{
if (PlacedBlocks.Count == 0) return;
// 모든 블럭 초기화
foreach (var block in PlacedBlocks)
{
block.IsSuccess = false;
}
// 조합에 사용 가능한 블럭 리스트
List<Block> availableBlocks = new List<Block>(PlacedBlocks);
for (int i = 0; i < PlacedBlocks.Count; i++)
{
Block current = PlacedBlocks[i];
if (!availableBlocks.Contains(current)) continue;
bool success = true;
Block prevSuccess = null;
Block nextSuccess = null;
// 선행 검사
if (current.PreCombineRule != null && current.PreCombineRule.RuleType != CombineType.None)
{
success = false;
foreach (var other in availableBlocks)
{
if (other == current) continue;
if (BlockValidator.CanCombineWithPrev(current, other))
{
prevSuccess = other;
success = true;
break;
}
}
if (!success && BlockValidator.RequiresPrevBlock(current))
{
current.IsSuccess = false;
continue;
}
}
// 후속 검사
success = true; // 다시 초기화
if (current.NextCombineRule != null && current.NextCombineRule.RuleType != CombineType.None)
{
success = false;
foreach (var other in availableBlocks)
{
if (other == current) continue;
if (BlockValidator.CanCombineWithNext(current, other))
{
nextSuccess = other;
success = true;
break;
}
}
if (!success && BlockValidator.RequiresNextBlock(current))
{
current.IsSuccess = false;
continue;
}
}
// 조합 성공 처리
current.IsSuccess = true;
if (prevSuccess != null)
{
prevSuccess.IsSuccess = true;
Debug.Log($"[{current.BlockName}] + [{prevSuccess.BlockName}] 조합 결과: 성공");
}
if (nextSuccess != null)
{
nextSuccess.IsSuccess = true;
Debug.Log($"[{current.BlockName}] + [{nextSuccess.BlockName}] 조합 결과: 성공");
}
current.SetGhost();
prevSuccess?.SetGhost();
nextSuccess?.SetGhost();
// 사용된 블럭 제거
availableBlocks.Remove(current);
if (prevSuccess != null) availableBlocks.Remove(prevSuccess);
if (nextSuccess != null) availableBlocks.Remove(nextSuccess);
}
// 실패 블럭들 고스트 처리
foreach (var block in PlacedBlocks)
{
if (!block.IsSuccess)
{
block.SetGhost();
Debug.Log($"[{block.BlockName}] 조합 결과: 실패");
}
}
}
NPC 이동 자연스럽게 수정
public void Move()
{
stateMachine.npc.Agent.updateRotation = true;
stateMachine.npc.Agent.SetDestination(GetRandomPointInArea(stateMachine.npc.Area));
}
public Vector3 GetRandomPointInArea(BoxCollider collider)
{
Vector3 center = collider.bounds.center;
Vector3 size = collider.bounds.size;
float randomX = Random.Range(center.x - size.x / 2, center.x + size.x / 2);
float randomZ = Random.Range(center.z - size.z / 2, center.z + size.z / 2);
return new Vector3(randomX, center.y, randomZ);
}
protected void RotateVelocity()
{
NavMeshAgent agent = stateMachine.npc.Agent;
Vector3 vel = agent.velocity;
if (vel.sqrMagnitude < 0.01f) return;
Quaternion rot = Quaternion.LookRotation(vel.normalized);
Transform trans = stateMachine.npc.transform;
trans.rotation = Quaternion.Slerp(trans.rotation, rot, stateMachine.RotationDamping * Time.deltaTime);
}
public virtual void Update()
{
if (!GameManager.Instance.SimulationMode && GameManager.Instance.SelectedBGM != null)
{
stateMachine.npc.Agent.isStopped = false;
moveTimer += Time.deltaTime;
if (moveTimer >= moveDelay)
{
Move();
moveTimer = 0f;
}
var agent = stateMachine.npc.Agent;
bool isMoving = !agent.pathPending && agent.remainingDistance > agent.stoppingDistance;
if (isMoving)
{
RotateVelocity();
StartAnimation("Walk");
}
else StopAnimation("Walk");
}
else
{
StopAnimation("Walk");
stateMachine.npc.Agent.isStopped = true;
}
}