C#/Problems

7. Unity 애니매이션 딜레이 실행 연습 ( attack -> idle -> attack..->idle) , 대리자를 이용해서 이펙트 생성하기

dev_sr 2020. 5. 15. 13:15

 

1. 문제

한번 공격하면 Idle 애니메이션을 실행하지 않거나, 딜레이 없이 연속으로 공격하거나 아무것도 안함..

몬스터를 공격할 경우 체력이나 카운터로 숫자를 표현할 경우, 한번 공격에 연속으로 숫자가 변경됨.

 

2. 해결방법

한번 공격하고 다시 공격하는 부분에서 새로운 공격판정을 하는 bool 변수를 새로 만든다. (bool isAttackAgain)

다시 공격하는 부분에서 딜레이 시간을 나타내는 float 변수를 증가시키고

원하는 딜레이 시간보다 길어졌을 경우에 다시 공격 메서드를 호출한다.

 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.UI;
 
public class App : MonoBehaviour
{
    public Button button;
    public GameObject heroShell;
    public GameObject monsterShell;
 
    private Hero hero;
    private Monster monster;
 
    void Start()
    {
        this.hero = heroShell.AddComponent<Hero>();
        this.monster = monsterShell.AddComponent<Monster>();
 
        
 
        this.button.onClick.AddListener(() =>
        {
 
            this.hero.Move();
        });
 
        this.hero.onAttack = () =>
        {
            this.CreateFx();
        };
    }
 
    private void CreateFx()
    {
        GameObject fxShell = new GameObject();
        fxShell.name = "fx_01";
 
        GameObject fxPrefabs = Resources.Load("Prefabs/fx_01"as GameObject;
        GameObject fxGo = Instantiate(fxPrefabs) as GameObject;
        fxGo.transform.SetParent(fxShell.transform);
 
        fxShell.transform.position = new Vector3
            (this.monster.transform.position.x, this.monster.transform.position.y + 0.3f, this.monster.transform.position.z - 0.3f);
    }
 
}
 

 

 

2. 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
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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
 
public class Hero : MonoBehaviour
{
    private GameObject model;
    private Animation anim;
    private AnimationState animState;
 
    private GameObject target;
    private Monster monster;
 
    private bool isMove;
    private bool isAttack;
    private bool isAttackAgain;
    private bool isImpact;
 
    private float elapsedTime;
    private float delayTime;
    private float distance;
    private float impactTime;
    private float elapsedTimeForImpact;
 
    public UnityAction onAttack;
 
    void Start()
    {
        this.model = GameObject.Find("ch_01_01");
        this.anim = this.model.GetComponent<Animation>();
        this.animState = this.anim["attack_sword_01"];
 
        float totalFrame = this.animState.clip.frameRate * this.animState.length;
        this.impactTime = 8 * this.animState.length / totalFrame;
 
        this.target = GameObject.Find("Monster");
        this.monster = this.target.GetComponent<Monster>();
 
        this.isImpact = true;
    }
 
    public void Move()
    {
        this.anim.Play("run@loop");
        this.isMove = true;
        this.isImpact = true;
    }
 
    public void Stop()
    {
        this.anim.Play("idle@loop");
        this.isMove = false;
        this.isAttack = false;
        this.isAttackAgain = true;
        this.isImpact = true;
    }
 
    public void Attack()
    {
        this.anim.Play("attack_sword_01");
        Debug.Log("몬스터를 공격함");
 
        this.isMove = false;
        this.isAttack = true;
        this.isAttackAgain = false;
        this.isImpact = false;
    }
 
    void Update()
    {
        if(this.isMove)
        {
            this. distance = Vector3.Distance(this.transform.position, this.target.transform.position);
 
            this.transform.Translate(Time.deltaTime * 1f * Vector3.forward);
 
            if(this.distance <= 0.5f )
            {
                this.Attack();
            }
        }
 
        if(!this.isImpact)
        {
            this.elapsedTimeForImpact += Time.deltaTime;
 
            if(this.elapsedTimeForImpact >= this.impactTime)
            {
                this.elapsedTimeForImpact = 0;
                this.monster.Damage();
                this.isImpact = true;
 
                if(this.onAttack!=null)
                {
                    this.onAttack();
                }
            }
        }
 
 
        if(this.isAttack)
        {
            this.elapsedTime += Time.deltaTime;
 
            if(this.elapsedTime >= this.animState.length)
            {
                this.Stop();
                this.elapsedTime = 0;
            }
        }
 
        if(this.isAttackAgain)
        {
            this.delayTime += Time.deltaTime;
 
            if(this.delayTime >= 2f)
            {
                this.Attack();
                this.delayTime = 0;
            }
 
            if(this.monster.DamageCount>=5)
            {
                this.monster.Die();
                this.isAttackAgain = false;
            }    
        }
    }
}
 

 

 

3.  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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Monster : MonoBehaviour
{
    private GameObject model;
    private Animation anim;
    private AnimationState animState;
 
    private bool isDamage;
 
    private float elapsedTime;
 
    public int DamageCount;
 
    void Start()
    {
        this.model = GameObject.Find("StoneMonster");
        this.anim = this.model.GetComponent<Animation>();
        this.animState = this.anim["Anim_Damage"];
 
    }
 
    public void Damage()
    {
        this.anim.Play("Anim_Damage");
        this.isDamage = true;
        Debug.Log("몬스터가 데미지를 입음");
        this.DamageCount++;
      
    }
 
    public void Die()
    {
        this.anim.Play("Anim_Death");
        this.isDamage = false;
    }
 
    public void Stop()
    {
        this.anim.Play("Anim_Idle");
        this.isDamage = false;
    }
 
    void Update()
    {
        if(this.isDamage)
        {
            this.elapsedTime += Time.deltaTime;
 
            if(this.elapsedTime>=this.animState.length)
            {
                this.Stop();
                this.elapsedTime = 0;
            }
        }
    }
}