본문 바로가기
c#/수업내용

캐릭터, 무기 선택해서 씬로드 실행하기

by Luna_O 2020. 5. 15.

캐릭터 선택해서 무기 고르고 씬전환하면 생성한 캐릭터 전달까지 완료

ObjectPool 사용해서 무기랑 캐릭터 반환시켜서 코드 다시 작성하느라 좀 오래걸림

DataManger로 Json 파일 불러와서 관리하는 건 이제 괜찮은 것 같다

이제 캐릭터와 몬스터 포탈 등 위치 정해서 보이게하고 

몬스터 달려가고 애니메이션 설정하고 타격시점 맞춰서 효과만들고 몬스터 없으면

포탈로 가야하는 거 해야함

 

움직이는 시간과 프레임 계산해서 타격때 효과 넣는게 좀 헷갈림

더 연습해야함 

 

 

InGame 코드

ObjectPool 사용해서 필요한 프리팹을 붙였다 떼었다 함

버튼에 따라서 캐릭터 5, 무기 3 선택할 수 있고 캐릭터 선택 후에 무기 선택하면

캐릭터의 dummyRHand 찾아서 무기를 붙여줌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
 
public class InGame : MonoBehaviour
{
    public Button[] weaponBtns;
    public Button[] characterBtn;
    public Button nextBtn;
    public GameObject character;
    public GameObject characterEffect;
    public GameObject stage;
    public Character hero;
 
    private DataManger dataManger;
    private ObjectPool objectPool;
 
    private void Awake()
    {
        dataManger = DataManger.GetInstance();
        dataManger.LoadDatas();
        this.objectPool = ObjectPool.GetInstance();
        this.objectPool.LoadAllAssets();
    }
 
    void Start()
    {
        for (int j = 0; j < this.characterBtn.Length; j++)
        {
            int idIdx = j + 100;
            this.characterBtn[j].onClick.AddListener(() =>
            {
                this.characterEffect.SetActive(true);
                if(this.character != null)
                {
                    this.objectPool.ReleaseAsset(this.character);
                    
                }
                this.character = this.objectPool.GetCharacter(dataManger.GetCharacterData(idIdx).res_name);
                this.character.transform.SetParent(hero.transform);
                this.character.SetActive(true);
                hero.dummyRHand = GameObject.FindWithTag("dummy");
            });
        }
        for (int i = 0; i < this.weaponBtns.Length; i++)
        {
            int idIdx = i + 200;
            this.weaponBtns[i].onClick.AddListener(() =>
            {
                if(this.hero.weapon != null)
                {
                    this.objectPool.ReleaseAsset(this.hero.weapon);
                }
                this.hero.weapon = this.objectPool.GetWeapon(dataManger.GetWeaponData(idIdx).res_name);
                this.hero.weapon.transform.SetParent(hero.dummyRHand.transform);
                this.hero.weapon.SetActive(true);
                this.hero.weapon.transform.localPosition = hero.dummyRHand.transform.localPosition;
                this.hero.weapon.transform.rotation = hero.dummyRHand.transform.localRotation;
            });
        }
        this.nextBtn.onClick.AddListener(() =>
        {
            this.hero.model = this.character;
            SceneManager.sceneLoaded += SceneManager_sceneLoaded;
            SceneManager.LoadScene("Stage_01");
        });
    }
 
    private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
    {
        Stage_01 stage = GameObject.FindObjectOfType<Stage_01>();
        stage.Init();
    }
}
cs

ObjectPool 코드

캐릭터와 무기 프리팹을 전부 붙여놓았다가

밖에서 필요하면 해당 프리팹을 찾아서 떼어내 반환시켜준다

밖에서 필요없어진 프리팹은 다시 받아서 비활성화 후 다시 붙임

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class ObjectPool : MonoBehaviour
{
    private static ObjectPool instance;
    private string[] weaponNames = {"axe""hammer""machete"}; //프리팹 이름 배열
    private List<GameObject> weaponList; //나중에 찾아서 반환시켜야하니까 배열 만들어서 찾기 편하게 한 것
    private string[] characterNames = {"ch_01_01""ch_02_01" , "ch_03_01" , "ch_04_01" , "ch_05_01" };
    private List<GameObject> characterList;
 
    private void Awake()
    {
 
        ObjectPool.instance = this;
        this.weaponList = new List<GameObject>();
        this.characterList = new List<GameObject>();
    }
    public static ObjectPool GetInstance()//싱글톤
    {
        return ObjectPool.instance;//인스턴스는 하나만 만들어서 한개의 인스턴스만 반환
    }
 
    public void LoadAllAssets() //프리팹을 찾아서 게임오브젝트로 만들어서 로드
    {
        foreach(var weaponName in this.weaponNames)
        {
            //프리팹 이름 배열을 이용하여 경로를 만든다
            string path = "Prefab/" + weaponName;
            //경로를 이용하여 Resources 안에 있는 프리팹을 변수에 할당(게임오브젝트로 타입 변경)
            var prefab = Resources.Load(path) as GameObject;
            //찾은 프리팹을 게임오브젝트로 만들어서 할당
            var asset = Instantiate<GameObject>(prefab);
            //찾기 편하게 만든 무기오브젝트 배열에 만든 프리팹 게임오브젝트를 추가
            this.weaponList.Add(asset);
            //위에서 찾은 프리팹을 게임오브젝트 만든 것의 이름을 설정
            asset.name = weaponName;
            //게임오브젝트 만든 것의 부모로 지금 오브젝트로 설정
            asset.transform.SetParent(this.transform);
            //만든 게임오브젝트 비활성화    => 나중에 쓸때 따로 활성화 시켜서 사용
            asset.SetActive(false);
        }
 
        foreach(var characterName in this.characterNames)
        {
            string path = "Prefab/" + characterName;
            var prefab = Resources.Load(path) as GameObject;
            var asset = Instantiate<GameObject>(prefab);
            this.characterList.Add(asset);
            asset.name = characterName;
            asset.transform.localScale = new Vector3 (222);
            asset.transform.SetParent(this.transform);
            asset.SetActive(false);
        }
 
    }
    public GameObject GetWeapon(string name)  //이름을 전달받으면 게임오브젝트 찾아서 반환시켜 줌
    {
        //무기오브젝트 배열에서 전달받은 매개변수와 같은 게임오브젝트를 찾는다.
        var asset = this.weaponList.Find(x => x.name == name);
        //찾은 게임오브젝트를 떼어서 반환시켜줘야하기 때문에 
        //지금 오브젝트에서 찾은 자식을 떼어준다
        if(asset != null)
        {
            asset.transform.SetParent(null);
        }
        //붙여준 부모에서 떼어냈으니 값을 반환시킨다
        return asset;
    }
    public GameObject GetCharacter(string name)
    {
        var asset = this.characterList.Find(x => x.name == name);
        if (asset != null)
        {
            asset.transform.SetParent(null);
        }
        return asset;
    }
 
    public void ReleaseAsset(GameObject asset) //다 사용하고 떼어 낼 매개변수인 게임오브젝트를 전달받아 자식으로 다시 붙여준다
    {
        //게임오브젝트를 비활성화 시킨다
        asset.SetActive(false);
        //비활성화 시킨 게임오브젝트를 다시 붙여준다
        //지금 오브젝트를 부모로 전달 받은 걸 자식으로 넣기
        //하지만 바로 부모로 붙히고 위치를 바꾸면 초기화가 안됨
        //먼저 떼어준다
        asset.transform.parent = null;
        //오브젝트의 위치를 다시 원상태로 초기화시킨다 Vector3 (0, 0, 0)
        asset.transform.localPosition = Vector3.zero;
        //Rotation을 바꿔주면 칼등으로 때린다 함, 밑에는 안해도되므로 주석
        //asset.transform.localRotation = Quaternion.Euler(Vector3.zero);
        //위치도 초기화 시켰으니 다시 전달받은 오브젝트를 자식으로 지금 오브젝트를 부모로 설정
        asset.transform.SetParent(this.transform);
    }
 
}
cs

DataManger 코드 

Json 파일 업로드 후 사전에 담아서 데이터 필요한 것만 반환시켜 줌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using UnityEngine;
 
 
public class DataManger
{
    private static DataManger instance;
    private Dictionary<int, CharacterData> dicCharacterDatas;
    private Dictionary<int, WeaponData> dicWeaponDatas;
    private Dictionary<int, EffectData> dicEffectDatas;
 
    private DataManger()
    {
        this.dicCharacterDatas = new Dictionary<int, CharacterData>();
        this.dicWeaponDatas = new Dictionary<int, WeaponData>();
        this.dicEffectDatas = new Dictionary<int, EffectData>();
    }
 
    public static DataManger GetInstance()
    {
        if( DataManger.instance == null)
        {
            DataManger.instance = new DataManger();
        }
        return DataManger.instance;
    }
 
    public void LoadDatas()
    {
        var characterJson = Resources.Load<TextAsset>("character_data");
       this.dicCharacterDatas = JsonConvert.DeserializeObject<CharacterData[]>(characterJson.ToString()).ToDictionary(x => x.id);
 
        var weaponJson = Resources.Load<TextAsset>("weapon_data");
        this.dicWeaponDatas = JsonConvert.DeserializeObject<WeaponData[]>(weaponJson.ToString()).ToDictionary(x => x.id);
 
        var effectJson = Resources.Load<TextAsset>("effect_data");
        this.dicEffectDatas = JsonConvert.DeserializeObject<EffectData[]>(effectJson.ToString()).ToDictionary(x => x.id);
    }
 
    public CharacterData GetCharacterData(int id)
    {
        return this.dicCharacterDatas[id];
    }
 
    public WeaponData GetWeaponData(int id)
    {
        return this.dicWeaponDatas[id];
    }
}
cs

Character 코드

DontDestroyOnLoad 사용해서 안사라지게 한다

왜냐하면 생성한 캐릭터를 반환시켜야하기 때문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Character : MonoBehaviour
{
    public GameObject dummyRHand;
    public GameObject weapon;
    public GameObject model;
 
    private void Awake()
    {
        DontDestroyOnLoad(this.gameObject);
    }
cs

Stage_01 코드

안사라지게 한 Character 게임오브젝트를 찾아서 캐릭터를 할당한다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Stage_01 : MonoBehaviour
{
    public Transform hero;
 
public void Init()
    {
        var hero = GameObject.Find("Character");
        this.hero = hero.transform.GetChild(1);
        Debug.Log(this.hero);
    }
cs