Unity & C#

[유니티] 간단 실험 : for loop in an update vs. multiple updates

왼손잡이개발자 2022. 7. 6. 13:00

 

유니티 개발을 하면서 "어떻게 작성하는 것이 더 최적화된 코드이지?" 라는 궁금증이 생기는 경우가 많이 있습니다.  그랬던 궁금증 중 한가지는 한 오브젝트가 update문에서 for loop를 돌면서 여러 오브젝트들의 함수를 실행하는 것이 빠를까 아니면 각 오브젝트들이 update문에서 자체적으로 실행하는 것이 빠를까 하는 궁금증이었습니다. 그래서 Unity Profiler를 통해서 어느 것이 더 빠른지 간단하게 실험을 해보았습니다. (Unity Profiler 사용법이 궁금하시다면 지난번 게시물을 확인해보세요 (https://lefthanddeveloper.tistory.com/25)

먼저 씬 배치는 다음과 같습니다. 

Target 오브젝트가 있고 Followers 오브젝트가 있는데 Followers 오브젝트 child로 follower가 생성이 되게 됩니다. Follwer 오브젝트들은 Target 오브젝트 쪽으로 계속 이동을 하게 할 것입니다. 이동 방법으로 한 스크립트의 update문에서 for loop으로 여러 follower를 움직이는게 더 성능적으로 더 빠른지 아니면 각 오브젝트 update문에서 이동을 하는 것이 성능적으로 빠른지 실험을 해보도록 하겠습니다.

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FollowerController : MonoBehaviour
{
    public bool isControllerControlling = false;

    [SerializeField] private Transform target;
    [SerializeField] private Follower followerPrefab;
    [SerializeField] private int numOfFollower = 100;

    private List<Follower> followers = new List<Follower>();
    void Start()
    {
        for(int i=0; i< numOfFollower; i++)
		{
            Follower follower = Instantiate<Follower>(followerPrefab, this.transform);
            follower.Init();
            followers.Add(follower);

			if (!isControllerControlling)
			{
                follower.SetTarget(target);
            }
		}
    }

    // Update is called once per frame
    void Update()
    {
		if (isControllerControlling)
		{
            for(int i=0; i< numOfFollower; i++)
			{
                followers[i].MoveTo(target);
			}
		}
    }
}

FollowerController.cs 에서 bool 값 isControllerControlling 이 true이면 FollowerController.cs에서 for loop문을 돌아 follower를  이동시키게 됩니다 (FollowerController.cs에서 update()부분).

만약 isControllerControlling이 false 이면 각 follower.cs 의 update문에서 target을 향해 이동하게 했습니다 (아래 스크립트 참고)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Follower : MonoBehaviour
{
    private bool isTargetSet = false;
    private Transform target;
    [SerializeField] private float movingSpeed = 1.0f;
    
    public void Init()
	{
        this.transform.position = Random.insideUnitSphere * 30f;
	}
    
    public void SetTarget(Transform target)
	{
        this.target = target;
        isTargetSet = true;
	}

    public void MoveTo(Transform _target)
	{
        transform.LookAt(_target);
        transform.Translate(Vector3.forward * Time.deltaTime * movingSpeed);
    }
    void Update()
    {
		if (isTargetSet)
		{
            transform.LookAt(target);
            transform.Translate(Vector3.forward * Time.deltaTime * movingSpeed);
		}
    }
}

위에 작성된 코드에서는 num of followers가 100으로 되어있는데 인스펙터에서 5000으로 수정하고 테스트를 했습니다.

실험결과는....

(왼) for loop in an update / (오른쪽) multiple updates 

속도는 둘다 거의 비슷하다는 점! 위에 스크린샷에서 한 스크립트 update문에서 for loop문을 돌았던 쪽이 약 2ms 정도 더 빨랐는데 이거는 매 frame마다 조금씩 fluctuation이 있기때문에 이정도 차이는 무시해도 될 차이인듯합니다.

 

 5000 오브젝트를 움직일때 한 update에서 5000번 for loop를 돌던, 5000개의 오브젝트에서 update로 움직이던 크게 차이는 없는 것으로 결론이 났습니다. 

 

아래는 테스트를 하면서 5000개의 sphere가 target을 따라가는 모습을 보는게 재밌어서 gif로 남겨봤습니다