본문 바로가기
개발/Unity

유니티 - 런타임 시 프리팹에 스크립트 추가하기 (Attach Script when Instantiate a Prefab)

by 피로물든딸기 2022. 5. 29.
반응형

Unity 전체 링크

 

런타임 때 프리팹을 생성하는 경우, 필요한 스크립트를 동적으로 추가해야하는 경우가 있다.

 

빈 오브젝트를 만들고 MakePrefab.cs를 추가한다.

 

MakePrefab.cs은 Raycast로 아무 오브젝트나 찾은 후, 그 지점에 프리팹을 생성한다.

생성할 프리팹은 적당한 게임 오브젝트를 Resources에 추가해서 사용한다.

(또는 public으로 선언해도 된다.)

 

MakePrefab.cs는 아래와 같다.

prefab을 Resources.Load로 불러온 후, Update에서 카메라 시점에서 Raycast를 쏜다.

그리고 Instantiate프리팹을 생성한 후, EmptyScript.cs를 추가하였다. (스크립트는 미리 만들어둔다.)

여기서는 간단하게 평면에다가 테스트를 하였다.

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

public class MakePrefab : MonoBehaviour
{
    GameObject go;
    
    void Start()
    {
        go = Resources.Load<GameObject>("Sphere");
    }

    void Update()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        Debug.DrawRay(ray.origin, ray.direction * 100.0f, Color.red);

        if(Input.GetMouseButtonDown(0))
        {
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, Mathf.Infinity))
            {
                Instantiate(go, hit.point, Quaternion.identity);
                go.AddComponent<EmptyScript>();
            }
        }
    }
}


먼저 위의 코드의 결과를 보자.

프리팹을 선택한 채로 평면을 클릭하면, Empty Script가 계속해서 추가된다.

더 큰 문제는 게임을 종료한 후에도 프리팹에 Script들이 남아있다는 것이다.

 

위 문제는 프리팹 go를 생성하고 프리팹에 Component를 추가하고 있기 때문에 발생한다.

즉 프리팹을 생성하고 프리팹을 수정하고 있는 코드가 된 것이다.

Instantiate(go, hit.point, Quaternion.identity);
go.AddComponent<EmptyScript>();

 

당연히, 프리팹을 수정하면 문제가 발생한다.

프리팹이 변경된 경우, 원래 게임을 시작해야 하는 방식으로 시작된다는 보장이 없다.

 

정상적인 방법은 Instantiate에 대한 결과를 GameObject copy로 받은 후copy에 AddComonent를 하는 것이다.

GameObject copy = Instantiate(go, hit.point, Quaternion.identity);
go.AddComponent<EmptyScript>();

 

이제 프리팹은 변경되지 않고, 생성된 GameObject에 스크립트가 추가된 것을 알 수 있다.

 

AddComponent가 프리팹을 건드리는 것은 스크립트를 추가하는 것 외에도

RigidBody와 같은 추가할 수 있는 모든 Component에 나타나는 현상이므로, 프리팹을 생성할 때 주의할 필요가 있다.

 

수정된 최종 코드는 아래와 같다.

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

public class MakePrefab : MonoBehaviour
{
    GameObject go;
    
    void Start()
    {
        go = Resources.Load<GameObject>("Sphere");
    }

    void Update()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        Debug.DrawRay(ray.origin, ray.direction * 100.0f, Color.red);

        if(Input.GetMouseButtonDown(0))
        {
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, Mathf.Infinity))
            {
                GameObject copy = Instantiate(go, hit.point, Quaternion.identity);
                copy.AddComponent<EmptyScript>();
            }
        }
    }
}

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글