250424 TIL

박소희·2025년 4월 24일

Unity_7기

목록 보기
76/94

블럭 중복 조합 방지

  • 블럭마다 후속/선행 조합을 이미 검사했는지 bool값을 넣고 true일 때는 검사를 패스하려고 했지만 어떻게 해도 안됐다..
  • 그래서 타임라인 배치된 순서대로 블럭을 검사하니, 배치된 블럭의 리스트를 새로 만들어서 검사한 블럭의 조합과 맞춰진 블럭은 리스트에서 제거하고 그 후에 나오는 블럭과 조합 검사를 안하도록 했다.
    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 이동 자연스럽게 수정

  • NPC들이 SetDestination을 해서 목적지를 정한 뒤 그 곳을 바라보게 하고, 이동하게 수정했다.
    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;
        }
    }

0개의 댓글