TIL

20231205 TIL / 게임개발 / 오브젝트 움직임

도도9999 2023. 12. 5. 09:46

그동안 이것저것 많은것을 추가, 수정했다.

 

 기존에 NPC들이 화면에 단발적으로 띡띡 등장했는데 이것을 자연스럽게 수정하고자 왼쪽에서부터 자연스럽게 나오도록 수정했다.

 

using UnityEngine;

public class NPCMovement : MonoBehaviour
{
    public float speed = 1.0f;
    public Vector3 startPositionOffScreen = new Vector3(-100, 0, 0);
    public Vector3 centerScreenPosition = new Vector3(0, 0, 0);
    public Vector3 endPositionOffScreen = new Vector3(-100, 0, 0);

    private Transform _transform;
    private Animator animator;
    private Vector3 targetPosition;
    public Transform visualRepresentation;
    private float arrivalThreshold = 0.1f; 

    private void Awake()
    {
        _transform = GetComponent<Transform>(); 
        animator = GetComponent<Animator>();
    }

    public void OnEnable()
    {
        SetStartPosition();
        MoveToCenter();
        ResetDirection();
    }

    private void Update()
    {
        _transform.position = Vector3.MoveTowards(_transform.position, targetPosition, speed * Time.deltaTime);
        animator.SetBool("isWalking", _transform.position != targetPosition);

        if (Vector3.Distance(_transform.position, targetPosition) < arrivalThreshold)
        {
            OnReachedDestination();
        }
    }


    private void MoveToCenter()
    {
        SetTargetPosition(centerScreenPosition);
    }

    public void WalkOutOfScreen()
    {
        SetTargetPosition(endPositionOffScreen);
    }

    public void SetStartPosition()
    {
        _transform.position = startPositionOffScreen;
    }

    private void OnReachedDestination()
    {
        animator.SetBool("isWalking", false); 

        if (targetPosition == centerScreenPosition)
        {
        }
        else if (targetPosition == endPositionOffScreen)
        {
            gameObject.SetActive(false); 
        }
    }

    private void OnDisable()
    {
        ResetDirection();
    }

    public void TurnAround()
    {
        if (_transform.eulerAngles.y != -180)
        {
            Vector3 rotation = _transform.eulerAngles;
            rotation.y = -180; // Y축 기준 -180도 회전
            _transform.eulerAngles = rotation;
        }
    }


    private void ResetDirection()
    {
        if (_transform.eulerAngles.y != 0)
        {
            Vector3 rotation = _transform.eulerAngles;
            rotation.y = 0; // Y축을 0도로 리셋
            _transform.eulerAngles = rotation;
        }
    }

    private void SetTargetPosition(Vector3 target)
    {
        targetPosition = target;
        animator.SetBool("isWalking", true);
    }
}

 

NPCMovement이라는 스크립트를 만들고 해당 오브젝트에 할당시켜, 오브젝트의 생성과 이동을 설정했다.

 

    private void SpawnNPC()
    {
        foreach (var npcObject in npcObjects)
        {
            if (!npcObject.activeInHierarchy)
                if (!npcObject.activeInHierarchy)
                {
                    NPCMovement npcMovement = npcObject.GetComponent<NPCMovement>();
                    npcMovement.SetStartPosition(); 

                    NPC npcComponent = npcObject.GetComponent<NPC>();
                    NPCImageController npcImageController = npcObject.GetComponent<NPCImageController>();
                    Animator npcAnimator = npcObject.GetComponent<Animator>();
                    NPCData selectedNPCData = ChooseRandomNPCData();
                    ItemSO selectedItem = ChooseRandomItem();

                    if (npcComponent != null && npcImageController != null && selectedNPCData != null && selectedItem != null)
                    {
                        npcComponent.NPCInit(selectedNPCData, selectedItem);
                        npcImageController.Initialize(selectedNPCData.npcID, selectedItem.itemID);
                        AnimatorOverrideController overrideController = new AnimatorOverrideController(npcAnimator.runtimeAnimatorController);
                        overrideController["Base Layer.Idle"] = selectedNPCData.idleAnimation;
                        overrideController["Base Layer.Walk"] = selectedNPCData.walkAnimation;
                        npcAnimator.runtimeAnimatorController = overrideController;
                    }

                    npcObject.SetActive(true); 
                    spawnedNPCsCount++;

                }
        }
    }

NPCSpawner이라는 NPC 생성을 담당하는 스크립트에서 해당 내용을 참조했다.

 

    public void OnClickRestButton()
    {
        SoundManager.Instance.SfxPlay(Enums.SFX.Button);

        if (npcSpawner != null)
        {
            foreach (var npcObject in npcSpawner.npcObjects)
            {
                NPCMovement npcMovement = npcObject.GetComponent<NPCMovement>();
                if (npcMovement != null)
                {
                    npcMovement.TurnAround();
                    npcMovement.WalkOutOfScreen();
                }
            }
            npcSpawner.ResetDay(); 
        }

NPC가 생성되는 것 뿐 아니라 의뢰를 완료하고 돌아가는 시점에도 뒤돌아서 잘 돌아가도록 BedUI(하루를 마무리하는 버튼)에서 해당 내용을 참조했다.