<Prefab>
- Tank 만들기
1. 빈 Game Object 'Tank'를 만들고 해당 Tank의 Body, Top, Cannon을 만들어서 drag drop으로 Tank에 둔다 -> 부모 자식 관계
2. 기존에 만들었던 PlayerController를 Add component하여 붙여넣는다. 후에 play를 실행하면 해당 Tank의 위치가 움직인다. Tank의 좌표는 바뀌지만, Tank 아래의 Body, Top, Cannon의 좌표는 Local 좌표로 Tank를 기준으로 하기 때문에 변함이 없다.
3. 이런식으로 하나의 객체를 여러 component를 이용하여 짤 경우 더 유용 ex) Player의 무기와 같은 것을 움직일 때, 간편
- Prefab
1. 위에서 설계한 Tank를 매번 똑같이 만들기는 어렵다 -> Assets 파일 아래에 Prefabs 폴더를 만들어서 Tank를 drag drop하면 Prefabs으로 사용 가능
2. 이제 Prefabs을 사용하여 여러 Tank 객체를 게임 세상에 놓을 수 있다. (아래의 Code 처럼)이때, Prefabs의 PlayerController의서 speed를 바꾸면 모든 Tank 객체에 적용 된다.
class Tank
{
public float speed = 15.0f;
}
public class PlayerController : MonoBehaviour
{
[SerializeField]
float _speed = 10.0f;
// Start is called before the first frame update
void Start()
{
Managers.Input.KeyAction -= OnKeyboard;
Managers.Input.KeyAction += OnKeyboard;
Tank tank1 = new Tank(); // Instance를 만든다.
Tank tank2 = new Tank(); // Instance를 만든다.
Tank tank3 = new Tank(); // Instance를 만든다.
Tank tank4 = new Tank(); // Instance를 만든다.
Tank tank5 = new Tank(); // Instance를 만든다.
}
3. Prefabs를 수정하기 위해선 Prefabs 폴더 아래의 Tank를 더블 클릭하여 선택한 후, 각 Body와 Top, Cannon을 수정하면 auto save로 자동 저장되어 모든 Tank 객체가 바뀐다.
- 각 Tank Instance의 속성을 다르게 할 수 있다.
1. 각 Tank에 변수를 override가 가능하다. 다음 Tank(1)의 Speed를 50으로 override하면 Speed가 Bold체가 된다. 나머지 Tank는 기본값인 10으로 Speed가 설정된다. Prefabs 자체의 Speed를 15로 바꾸어도 overrid한 Tank(1)의 Speed는 변하지않는다.
2. 무엇을 override 했는지에 관한 것은 아래의 override하여 볼 수 있다.
- Nested Prefabs
Prefabs를 중첩하여 사용할 수 있다.
1. 다음과 같이 Player를 태운 Tank를 다시 Prefabs으로 사용할 수 있다.
2. 마찬가지로 Tank의 speed값을 바꾸면 PlayerInTank안의 Tank에도 적용되는 것을 볼 수 있다.
3. 코드로 보면 다음과 같다.
class Tank
{
public float speed = 15.0f;
Player player; // 포함 관계 Nested(중첩된) Prefab
}
- Prefabs 상속
다음 코드와 같이 상속 받은 Prefab을 만들 수 있다.
class Tank
{
public float speed = 15.0f;
Player player; // 포함 관계 Nested(중첩된) Prefab
}
class FastTank : Tank // 상속 받아서 변형
{
}
1. 기존의 Tank를 drag drop하여 Prefabs 폴더로 가져오면 Prefab Variant 선택 버튼이 있다. 그것을 클릭하면 Tank와 모양은 같지만 이름은 다른 Prefab이 만들어진다. 이러한 Prefabs에 다양한 component나 변수값을 변경하여 상속받은 것 처럼 사용할 수 있다.
<Prefab Instance code>
- Prefab Instance code로 구현하기
1. PrefabTest라는 빈 Game Object를 만들고 PlayerController 외의 PrefabTest c# 파일을 만든 후 PrefabTest에 component를 추가한다.
2. PrefabTest c# 파일을 실행한 후, 다음과 같이 코드를 짠다. Update는 필요없기 때문에 지우고 Instantiate()을 이용하여 Instance를 설정해줄 수 있다. public으로 Gameobject를 멤버 변수로 해준후 해당 Instantiate에 변수로 넣어준다.
public class PrefabTest : MonoBehaviour
{
public GameObject prefab;
// Start is called before the first frame update
void Start()
{
Instantiate(prefab);
}
}
3. Prefabs 폴더에 Tank를 drag drop하여 PrefabTest component의 PrefabTest의 prefab에 넣어준다.
4. 그 후 play를 하면 Tank가 나타난다.
5. 삭제는 Destroy(GameObject, float) 함수로 가능하다 -> GameObject를 float(초)후에 삭제한다.
public class PrefabTest : MonoBehaviour
{
public GameObject prefab;
GameObject tank;
// Start is called before the first frame update
void Start()
{
tank = Instantiate(prefab);
Destroy(tank, 3.0f); // 3초 후에 GameObject 삭제
}
}
- 코드로 Prefabs에 접근하기
1. PrefabTest c# script에서 위에서 drag drop으로 Tank를 가져오지 않고 코드에서 바로 가져올수있다.
Resources.Load<GameObject>("경로")를 이용하면됨 -> 이때 기준이 Assets파일 아래의 Resources파일이기 때문에 반드시 Resources파일 아래에 Prefabs 폴더를 만들어야한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PrefabTest : MonoBehaviour
{
public GameObject prefab;
GameObject tank;
// Start is called before the first frame update
void Start()
{
prefab = Resources.Load<GameObject>("Prefabs/Tank"); // 무조건 기준이 Assets 폴더 아래의 Resources폴더 아래를 기준으로 함
tank = Instantiate(prefab);
Destroy(tank, 3.0f); // 3초 후에 GameObject 삭제
}
}
- Resources Manager 만들기
위에서 본 코드와 같이 하나한 Resources를 가져와 Destroy할 수 있지만, 따로 Resources를 관리해주는 Manager를 만들 수 있다.
1. Resource Manager에서 위에서한 Resources, Instantiate, Destroy 정의
<ResourceManager.cs>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResourceManager
{
// ResourceManager에서 instance 불러오고 Instantiate, Destroy를 하는 인터페이스 만들어야함.
public T Load<T>(string path) where T: Object
{
return Resources.Load<T>(path); // 해당 GameObject 반환
}
public GameObject Instantiate(string path, Transform parent = null)
{
// 위에서 정의한 Load를 통해 가져옴
GameObject prefab = Load<GameObject>($"Prefabs/{path}");
// prefab 가져오기 실패 -> 문제가 있는 것
if(prefab == null)
{
// Log를 남김
Debug.Log($"Failed to load prefab : {path}");
return null;
}
return Object.Instantiate(prefab, parent); // 그냥 Instantiate을 사용하지 않고 Object를 붙여서 헷갈리지않게
}
public void Destroy(GameObject go)
{
if (go == null)
return;
Object.Destroy(go); // 그냥 Destroy을 사용하지 않고 Object를 붙여서 헷갈리지않게
}
}
2. Managers.cs 에 추가: ResourceManager 추가 후, instance로
public class Managers : MonoBehaviour
{
static Managers s_instance; // static의 특성을 이용햐여 유일성 보장
static Managers Instance { get { Init(); return s_instance; } } // 외부에서 사용할때는 해당 함수를 이용하여 가져옴
InputManager _input = new InputManager();
ResourceManager _resource = new ResourceManager();
public static InputManager Input { get { return Instance._input; } }
public static ResourceManager Resource { get { return Instance._resource; } }
...
3. PrefabTest.cs를 다음과 같이 수정
: Managers.Resource.Instantiate("Tank")로 GameObject 불러옴
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PrefabTest : MonoBehaviour
{
public GameObject prefab;
GameObject tank;
// Start is called before the first frame update
void Start()
{
tank = Managers.Resource.Instantiate("Tank");
Destroy(tank, 3.0f); // 3초 후에 GameObject 삭제
}
}
'Development > 유니티' 카테고리의 다른 글
[섹션5]Camera(카메라) (0) | 2021.07.13 |
---|---|
[섹션4] Collsion(충돌) (0) | 2021.07.09 |
[섹션2] Transform(트랜스폼) (0) | 2021.07.06 |
[섹션1] 유니티 기본 구성 및 기초 (0) | 2021.06.29 |
환영합니다! (0) | 2021.06.28 |