C#/수업내용

2020.05.12. 수업내용 - 생성된 캐릭터가 서로 달려와서 공격하기(상속)

dev_sr 2020. 5. 12. 17:38

 

★★★

Character : MonoBehaviour 

-> Hero : Character

-> Monster : Character

 

==> Hero와 Monster는 Character와 MonoBehaviour 를 모두 상속받는다.

 

 

 

1. App

 

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
 
public class App : MonoBehaviour
{
    private void Awake()
    {
        DontDestroyOnLoad(this.gameObject);
    }
    void Start()
    {
        //이벤트 등록
        SceneManager.sceneLoaded += SceneManager_sceneLoaded;
        //씬로드
        SceneManager.LoadScene("InGame");
    }
 
    private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
    {
        //첫번째 활성화된 로드된 타입의 오브젝트 반환
        //타입으로 객체 찾기
        InGame inGame = GameObject.FindObjectOfType<InGame>();
        Debug.LogFormat("InGame: {0}", inGame);
        inGame.Init();
    }
 
    
}
 

 

 

2. InGame

 

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
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
 
public class InGame : MonoBehaviour
{
    public Button btn;
    private List<Character> characterList;
    private float distance;
    //private GameObject modelGo;
    //private GameObject monsterGo;
    //private Animation heroAnim;
    //private Animation monsterAnim;
 
    private void Awake()
    {
        Debug.Log("InGame::Awake");
        this.characterList = new List<Character>();
    }
 
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("InGame::Start");
    }
 
    //App에서 Ingame씬이 로드되는 순서: Awake-Init-Start
    public void Init()
    {
        Debug.Log("InGame::Init");
 
        //껍데기 생성
        GameObject shellGo = this.CreateShell("Hero");
        //모델생성
        GameObject modelGo = this.CreateModel("Prefabs/ch_04_01");
        //히어로 생성
        Hero hero = this.CreateHero(shellGo, modelGo);
 
        GameObject monsterShellGo = this.CreateShell("Monster");
        GameObject monsterGo = this.CreateModel("Prefabs/ch_05_01");
        Monster monster = this.CreateMonster(monsterShellGo, monsterGo);
 
        hero.Init(Vector3.zero,modelGo);
        monster.Init(new Vector3(1,0,2),monsterGo);
 
        hero.transform.LookAt(monster.transform);
        monster.transform.LookAt(hero.transform);
 
        //이렇게 해도 됨
        //hero.transform.LookAt(monster.transform.position);
        //monster.transform.LookAt(hero.transform.position);
 
        this.characterList.Add(hero);
        this.characterList.Add(monster);
 
        this.btn.onClick.AddListener(() => 
        {
            Debug.LogFormat("list: {0}"this.characterList.Count);
            foreach(var character in this.characterList)
            {
                character.Attack();
                
            }
 
            //this.characterList.ForEach(x => x.Attack());
        });
 
    }
 
    private Monster CreateMonster(GameObject monsterShellGo, GameObject monsterGo)
    {
        Monster monster = monsterShellGo.AddComponent<Monster>();
        //등록된 태그 설정해주기
        monster.gameObject.tag = "Monster";
        monsterGo.transform.SetParent(monsterShellGo.transform, false);
        return monster;
    }
    private Hero CreateHero(GameObject shellGo, GameObject modelGo)
    {
        //껍데기에 Hero컴포넌트 부착
        Hero hero = shellGo.AddComponent<Hero>();
        //등록된 태그 설정해주기
        hero.tag = "Hero";
        //모델을 껍데기에 넣기
        modelGo.transform.SetParent(shellGo.transform, false);
        //Hero 컴포넌트 반환
        return hero;
    }
 
    private GameObject CreateModel(string path)
    {
        //메모리 상에 올라감
        var prefab = Resources.Load(path) as GameObject;
 
        //프리팹 복사본 생성(게임오브젝트 생성)
        var model = Instantiate<GameObject>(prefab);
 
        return model;
    }
 
    private GameObject CreateShell(string name)
    {
        //동적으로 게임오브젝트 생성
        var shellGo = new GameObject();
        //게임오브젝트의 이름을 설정
        shellGo.name = name;
        return shellGo;
    }
 
    private void Update()
    {
        
        
 
    }
 
 
}
 

 

 

3. Character 

 

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Character : MonoBehaviour
{
    public float attackRange;
    public Animation anim;
    public bool isReady;
    public bool isRun;
 
    private void Awake()
    {
        Debug.Log("Character::Awake");
    }
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Character::Start");
 
    }
 
    public void Init(Vector3 initPos, GameObject model)
    {
        Debug.Log("Character::Init");
        this.transform.position = initPos;
        this.attackRange = 0.3f;
        this.anim = model.GetComponent<Animation>();
    }
 
    public virtual void Attack()
    {
 
    }
 
    public virtual void AttackAct()
    {
        
    }
 
    public virtual void Run()
    {
        this.anim.Play("run@loop");
    }
 
    // Update is called once per frame
    void Update()
    {
        
    }
}
 

 

4. 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
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Timeline;
 
public class Hero : Character
{
    public GameObject target;
    private float distance;
 
 
    private void Awake()
    {
        Debug.Log("Hero::Awake");
    }
 
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Hero::Start");
 
        
    }
 
    public override void Attack()
    {
        ////태그로 찾기
        //var target = GameObject.FindWithTag("Monster");
        //Debug.LogFormat("target: {0}", target);
 
        ////타입으로 찾기
        //var target = GameObject.FindObjectOfType<Monster>();
        //Debug.LogFormat("target: {0}", target);
 
        //게임오브젝트 이름으로 찾기
        target=GameObject.Find("Monster");
        Debug.LogFormat("target: {0}", target);
 
        this.isReady = true;
        
    }
 
    private void Update()
    {
        if(isReady)
        {
            this.distance = Vector3.Distance(this.transform.position, this.target.transform.position);
            
            if(this.distance<=this.attackRange)
            {
                this.isRun = false;
                this.AttackAct();
                
            }
            else
            {
                this.isRun = true;
                
            }
        }
 
        if(this.isRun)
        {
            this.transform.Translate(Time.deltaTime * 1f * Vector3.forward);
            this.Run();
 
            if (this.distance <= this.attackRange)
            {
                this.AttackAct();
                this.isRun = false;
                
            }
 
        }
    }
 
    public override void AttackAct()
    {
        Debug.Log("attack");
        this.anim.Play("attack_sword_01");
 
    }
 
    public override void Run()
    {
        base.Run();
       
    }
    // Update is called once per frame
 
}
 

 

 

5. Monster 

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Monster : Character    //Monster<-characer<-Mono
{
    public GameObject target;
    private float distance;
 
    private void Awake()
    {
        Debug.Log("Monster::Awake");
    }
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Monster::Start");
    }
 
    public override void Attack()
    {
        target = GameObject.FindWithTag("Hero");
        Debug.LogFormat("target: {0}", target);
 
        Debug.Log(this.transform.position);
        Debug.Log(this.target.transform.position);
 
        this.isReady = true;
    }
 
    private void Update()
    {
        if (isReady)
        {
            this.distance = Vector3.Distance(this.transform.position, this.target.transform.position);
 
            if (this.distance <= this.attackRange)
            {
                this.isRun = false;
                this.AttackAct();
 
            }
            else
            {
                this.isRun = true;
 
            }
        }
 
        if (this.isRun)
        {
            this.transform.Translate(Time.deltaTime * 1f * Vector3.forward);
            this.Run();
 
            if (this.distance <= this.attackRange)
            {
                this.AttackAct();
                this.isRun = false;
 
            }
 
        }
    }
 
    public override void AttackAct()
    {
        Debug.Log("attack");
        this.anim.Play("attack_sword_01");
 
    }
 
    public override void Run()
    {
        base.Run();
 
    }
 
    // Update is called once per frame
 
}