C#/Problems

8. ObjectPool 이용해서 데이터 꺼내기 / Scene사이에 데이터 넘기기

dev_sr 2020. 5. 17. 23:29

1. 문제

SceneManager.sceneLoaded += (Scene arg0, LoadSceneMode arg1) => { };

SceneManager.sceneLoaded 를 사용하면 다음 Scene에 넘길 값이 null 이 되어서 제대로 값이 전달되지 않는다.

다음 Scene에서 다시 ObjectPool을 생성해서 불필요하게 이미 생성되어있는 객체들을 다시 로드하고 생성했다.

 

2. 해결방법

DontDestroyOnLoad(ObjectPool.GetInstance());

다음 Scene으로 넘어갈 때 파괴되지 않는 것을 ObjectPool의 인스턴스로 설정하고

데이터들이 전달되기 전에(UIStudo씬이 파괴되기 전에)

ObjectPool에서 꺼내쓴 모델 객체들을 반납한다(다시 ObjectPool에 붙여준다)

다음 Scene에서 다시 객체들을 꺼내쓸 데이터만 넘겨준다( id 나 Hero Class 인스턴스 등)

다시 ObjectPool에서 객체들을 꺼내쓰면 되므로 불필요하게 데이터를 다시 로드하고 생성하지 않을 수 있다.

 

 

*DataManger, 매핑 테이블 코드는 생략했습니다.

 

1. UIStudio 

 

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
99
100
101
102
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
 
public class UIStudio : MonoBehaviour
{
    public Button[] btn;
    public Image weaponIconImage;
    public Sprite[] arrSprite;
    public Button attackBtn;
    public Button nextBtn;
 
    private Hero hero;
    private GameObject weaponGo;
    private GameObject fxGo;
    private int characterId;
    private WeaponData weaponData;
 
    private void Awake()
    {
        DontDestroyOnLoad(ObjectPool.GetInstance());
    }
 
    void Start()
    {
 
        ObjectPool.GetInstance().Load();
 
        this.characterId = 103;
 
        CharacterData heroData = DataManager.GetInstance().GetCharacterDataById(characterId);
        GameObject heroGo = ObjectPool.GetInstance().GetCharacterAsset(characterId);
        this.hero = heroGo.AddComponent<Hero>();
 
        this.hero.Init(heroGo, heroData);
 
 
        int count = 0;
 
        
 
        for (int i=0; i<this.btn.Length; i++)
        {
            int capturedIndex = i;
            int weaponId = i + 200;
 
            this.btn[capturedIndex].onClick.AddListener(() =>
            {
                this.weaponIconImage.gameObject.GetComponent<Image>().sprite = this.arrSprite[capturedIndex];
 
                if (count > 0)
                {
                    ObjectPool.GetInstance().ReleaseAsset(weaponGo);
                    ObjectPool.GetInstance().ReleaseFxAsset(fxGo);
                }
 
                //objectPool에서 weaponGo를 가져옴
                weaponGo = ObjectPool.GetInstance().GetWeaponAsset(weaponId);
 
                //objectPool에서 fxGo를 가져옴
                weaponData = DataManager.GetInstance().GetWeaponDataById(weaponId);
                fxGo = ObjectPool.GetInstance().GetFxAsset(weaponData.fx_id);
 
                this.hero.GetWeapon(weaponGo, weaponData);
 
              
                count++;
 
 
            });
 
        }
 
        this.nextBtn.onClick.AddListener(() =>
        {
            ObjectPool.GetInstance().ReleaseAsset(this.weaponGo);
            ObjectPool.GetInstance().ReleaseFxAsset(this.fxGo);
            ObjectPool.GetInstance().ReleaseAsset(heroGo);
 
            SceneManager.sceneLoaded += (Scene arg0, LoadSceneMode arg1) =>
            {
 
                Debug.LogFormat("넘겨줄 거 {0} {1} {2} {3}", heroData.id, weaponData.id, weaponData.fx_id, this.hero);
                Stage01 stage01 = GameObject.FindObjectOfType<Stage01>();
                stage01.Init(heroData.id, weaponData.id, weaponData.fx_id, this.hero);
 
            };
            SceneManager.LoadScene("Stage01");
        });
 
        this.attackBtn.onClick.AddListener(() =>
        {
            this.hero.Attack();
        });
 
        
    }
 
}

 

 

 

2. 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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class ObjectPool : MonoBehaviour
{
    private static ObjectPool instance;
    private List<GameObject> AssetList;
 
    private void Awake()
    {
        ObjectPool.instance = this;
        this.AssetList = new List<GameObject>();
    }
 
    public static ObjectPool GetInstance()
    {
        return ObjectPool.instance;
    }
 
    public void Load()
    {
        DataManager.GetInstance().Load();
 
        List<WeaponData> weaponDataList = DataManager.GetInstance().GetWeaponData();
 
        foreach(var data in weaponDataList)
        {
            string weaponPath = string.Format("Prefabs/{0}", data.res_name);
            GameObject weapon = Resources.Load(weaponPath) as GameObject;
            weapon.name = data.name;
            GameObject weaponGo = Instantiate(weapon) as GameObject;
            this.AssetList.Add(weaponGo);
 
            weaponGo.transform.SetParent(this.transform);
            weaponGo.SetActive(false);
        }
 
        List<FxData> fxDataList = DataManager.GetInstance().GetFxData();
 
        foreach (var data in fxDataList)
        {
            string fxPath = string.Format("Effect/{0}", data.res_name);
            GameObject fx = Resources.Load(fxPath) as GameObject;
            fx.name = data.name;
            GameObject fxGo = Instantiate(fx) as GameObject;
            this.AssetList.Add(fxGo);
 
            fxGo.transform.SetParent(this.transform);
            fxGo.SetActive(false);
        }
 
        List<CharacterData> characterDataList = DataManager.GetInstance().GetCharacterData();
 
        foreach (var data in characterDataList)
        {
            string characterPath = string.Format("Prefabs/{0}", data.res_name);
            GameObject character = Resources.Load(characterPath) as GameObject;
            character.name = data.name;
            GameObject characterGo = Instantiate(character) as GameObject;
            this.AssetList.Add(characterGo);
 
            characterGo.transform.SetParent(this.transform);
            characterGo.SetActive(false);
        }
    }
 
    public GameObject GetCharacterAsset(int id)
    {
        CharacterData characterData = DataManager.GetInstance().GetCharacterDataById(id);
        string CharacterName = string.Format("{0}(Clone)", characterData.name);
 
        foreach (GameObject data in this.AssetList)
        {
            if (CharacterName == data.name)
            {
                this.GetAsset(data);
 
                return data;
            }
        }
        return null;
 
    }
 
 
    public GameObject GetWeaponAsset(int id)
    {
        WeaponData weaponData = DataManager.GetInstance().GetWeaponDataById(id);
        string weaponName = string.Format("{0}(Clone)", weaponData.name);
 
        foreach(GameObject data in this.AssetList)
        { 
 
            if (weaponName == data.name)
            {
                this.GetAsset(data);
 
                return data;
            }
        }
        return null;
    }
 
    public GameObject GetFxAsset(int id)
    {
        FxData fxData = DataManager.GetInstance().GetFxDataById(id);
        string fxName = string.Format("{0}(Clone)", fxData.name);
 
        foreach (GameObject data in this.AssetList)
        {
 
            if (fxName == data.name)
            {
 
                this.GetAsset(data);
 
                return data;
            }
        }
        return null;
    }
 
 
    public void GetAsset(GameObject gameObject)
    {
        if (gameObject != null)
        {
            gameObject.transform.parent = null;
            //gameObject.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
            gameObject.SetActive(true);
        }
    }
 
 
    public void ReleaseAsset(GameObject gameObject)
    {
        gameObject.transform.SetParent(this.transform);
        gameObject.transform.position = this.transform.position;
        gameObject.transform.localRotation = Quaternion.Euler(Vector3.zero);
        gameObject.SetActive(false);
 
    }
 
    public void ReleaseFxAsset(GameObject gameObject)
    {
        gameObject.transform.SetParent(this.transform);
        gameObject.transform.position = this.transform.position;
        gameObject.SetActive(false);
 
    }
 
 
}
 

 

 

 

3. Level

 

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
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.Events;
 
public class Level : MonoBehaviour
{
    public GameObject portal;
    public Monster monster;
    public List<Monster> monsterList;
 
    private Hero hero;
 
 
    void Start()
    {
        
    }
 
    public virtual void Init(int heroId, int weaponId, int fxId, Hero hero)
    {
        Debug.Log("초기화");
 
        this.hero = hero;
 
        GameObject heroGo = ObjectPool.GetInstance().GetCharacterAsset(heroId);
        GameObject weaponGo = ObjectPool.GetInstance().GetWeaponAsset(weaponId);
        WeaponData weaponData = DataManager.GetInstance().GetWeaponDataById(weaponId);
        ObjectPool.GetInstance().GetFxAsset(fxId);
        
        Debug.LogFormat("{0} {1} {2}"this.hero, this.hero.attack_damage, this.hero.move_speed);
 
        this.hero.GetWeapon(weaponGo, weaponData);
        
    }
 
}

 

 

 

4. Stage01

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.Events;
 
public class Stage01 : Level
{
 
    private void Awake()
    {
        Debug.Log("stage01");
    }
 
    public override void Init(int heroId, int weaponId, int fxId, Hero hero)
    {
        base.Init(heroId, weaponId, fxId, hero);
    }
 
}

 

 

 

5. Hero

 

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Hero : MonoBehaviour
{
    private Animation anim;
    private AnimationState animstate;
    private bool isAttack;
    private float elapsedTimeCompareAttackEnd;
    private GameObject model;
    private Transform dummyRHand;
    private float impactTime;
 
    public float attack_damage;
    public float attack_range;
    public float attack_speed;
    public float move_speed;
 
 
 
    void Start()
    {
        Debug.Log("hi");
 
    }
 
    public void Init(GameObject model, CharacterData data)
    {
        this.model = model;
 
        this.attack_damage = data.attack_damage;
        this.attack_range = data.attack_range;
        this.attack_speed = data.attack_speed;
        this.move_speed = data.move_speed;
 
        this.anim = model.GetComponent<Animation>();
        this.animstate = this.anim["attack_sword_01"];
        float animAttackFrameRate = this.animstate.clip.frameRate;
        float totalFrame = this.animstate.length * animAttackFrameRate;
        float impactFrame = 8f;
 
        this.impactTime = impactFrame * this.animstate.length / totalFrame;
 
    }
    public void GetWeapon(GameObject weaponGo, WeaponData weaponData)
    {
        this.attack_damage = weaponData.attack_damage;
        this.attack_range = weaponData.attack_range;
        this.attack_speed = weaponData.attack_speed;
 
        this.dummyRHand = this.model.GetComponent<HeroModel>().dummyRHand;
        weaponGo.transform.SetParent(dummyRHand, false);
 
        if(weaponGo.transform.rotation.y != 180)
        {
            weaponGo.transform.Rotate(new Vector3(01800));
        }
        weaponGo.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
        weaponGo.SetActive(true);
 
    }
 
    public void Attack()
    {
        this.anim.Play("attack_sword_01");
        this.isAttack = true;
    }
 
    private void Stop()
    {
        this.anim.Play("idle@loop");
        this.isAttack = false;
    }
 
 
    void Update()
    {
        if (this.isAttack)
        {
            this.elapsedTimeCompareAttackEnd += Time.deltaTime;
 
            if (this.elapsedTimeCompareAttackEnd >= this.animstate.length)
            {
                Debug.LogFormat("공격 경과된 시간 {0}", elapsedTimeCompareAttackEnd);
                Debug.LogFormat("공격 시간 {0}"this.animstate.length);
                this.elapsedTimeCompareAttackEnd = 0;
                this.Stop();
 
            }
        }
 
    }   
}