[Unity] Delegate와 Coroutine사용 영웅과 몬스터 공격/피격 애니메이션
APP 2019. 11. 27. 23:41delegate는 static으로 선언함.
App.cs
using System;
using UnityEngine;
using UnityEngine.UI;
public class App : MonoBehaviour
{
public Button btnCreateHero;
public Button btnCreateMonster;
public Button btnAttack;
private Hero hero;
private Monster monster;
public static Action DelHeroMoveComplete;
public static Action DelHeroAttackComplete;
public static Action<int> DelMonsterDamageStart;
public static Action DelAnimMonsterDamageComplete;
// Start is called before the first frame update
void Start()
{
this.btnCreateHero.onClick.AddListener(() => {
CreateHero();
});
this.btnCreateMonster.onClick.AddListener(() => {
CreateMonster();
});
this.btnAttack.onClick.AddListener(() =>
{
this.hero.SetTarget(this.monster);
this.hero.StartMoveCo();
});
DelHeroMoveComplete = () =>
{
Debug.Log("영웅 이동완료");
this.hero.StartAttackCo();
Debug.Log("영웅 공격시작");
};
DelHeroAttackComplete = () =>
{
Debug.Log("영웅 공격완료");
this.hero.PlayAnimIdle();
};
DelMonsterDamageStart = (damage) =>
{
Debug.Log("몬스터 피격시작");
this.monster.StartHitCo(damage);
};
DelAnimMonsterDamageComplete = () =>
{
Debug.Log("몬스터 피격애니메이션 끝");
this.monster.PlayAnimIdle();
};
}
public void CreateHero()
{
//GameObject생성
GameObject go = new GameObject("Hero");
//Hero Script부착
this.hero = go.AddComponent<Hero>();
//prefab 로드
string path = "Prefabs/ch_01_01";
GameObject prefab = Resources.Load<GameObject>(path);
//model생성 및 부착
GameObject model = Instantiate(prefab);
this.hero.SetModel(model);
this.hero.transform.position = Vector3.zero;
}
public void CreateMonster()
{
//GameObject생성
GameObject go = new GameObject("Monster");
//Hero Script부착
this.monster = go.AddComponent<Monster>();
//prefab 로드
string path = "Prefabs/ch_02_01";
GameObject prefab = Resources.Load<GameObject>(path);
//model생성 및 부착
GameObject model = Instantiate(prefab);
this.monster.SetModel(model);
this.monster.transform.position = new Vector3(2, 0, 0);
}
}
Hero.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hero : MonoBehaviour
{
private GameObject model;
private Animation anim;
public int damage = 1;
public float atkRange = 0.5f;
public float speed = 0.05f;
public Coroutine coMove;
public Coroutine coAttack;
public Monster monster;
public void SetModel(GameObject model)
{
if (this.model != null)
{
Destroy(this.model);
}
//Shell에 Model을 자식으로 추가
this.model = model;
this.model.transform.SetParent(this.transform, false);
this.anim = this.model.GetComponent<Animation>();
}
public void SetTarget(Monster monster)
{
this.monster = monster;
}
public void StartMoveCo()
{
coMove = StartCoroutine(Move(monster, App.DelHeroMoveComplete));
}
IEnumerator Move(Monster monster, Action DelHeroMoveComplete)
{
Vector3 v3;
while (true)
{
yield return new WaitForSeconds(0.02f);
v3 = monster.transform.position - this.transform.position;
if (v3.magnitude > atkRange)
{
this.transform.forward = v3;
//애니메이션실행
this.anim.Play("run@loop");
//위치이동
this.transform.position += v3.normalized * speed;
}
else //(v3.magnitude <= atkRange)
{
this.transform.position = monster.transform.position - v3.normalized * atkRange;
this.anim.Play("idle@loop");
StopCoroutine(coMove);
DelHeroMoveComplete();
}
}
}
public void StartAttackCo()
{
coAttack = StartCoroutine(Attack(monster, App.DelMonsterDamageStart, App.DelHeroAttackComplete));
}
public void PlayAnimIdle()
{
this.anim.Play("idle@loop");
}
IEnumerator Attack(Monster monster, Action<int> DelMonsterDamageStart, Action DelHeroAttackComplete)
{
while (monster.hp > 0)
{
this.anim.Play("attack_sword_01");
yield return new WaitForSeconds(0.47f);//타격시점
DelMonsterDamageStart(this.damage);
yield return new WaitForSeconds(0.4f);
DelHeroAttackComplete();
yield return new WaitForSeconds(2f); //공격딜레이
}
}
}
Monster.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Monster : MonoBehaviour
{
public GameObject model;
public Animation anim;
public int hp = 3;
public Coroutine coHit;
public void SetModel(GameObject model)
{
if (this.model != null)
{
Destroy(this.model);
}
//Shell에 Model을 자식으로 추가
this.model = model;
this.anim = this.model.GetComponent<Animation>();
this.model.transform.SetParent(this.transform, false);
}
public void PlayAnimIdle()
{
this.anim.Play("idle@loop");
}
public void StartHitCo(int damage)
{
coHit = StartCoroutine(Hit(damage));
}
IEnumerator Hit(int damage)
{
this.anim.Play("damage");
this.hp -= damage;
Debug.LogFormat("몬스터가 공격받았습니다. {0}", this.hp);
yield return new WaitForSeconds(0.8f);
StopCoroutine(coHit);
if (this.hp > 0)
{
App.DelAnimMonsterDamageComplete();
}
else //(this.hp <= 0)
{
this.anim.Play("die");
}
}
}
'APP' 카테고리의 다른 글
[Unity] Physics.Raycast (0) | 2019.12.06 |
---|---|
[Unity] RayCast (0) | 2019.12.06 |
[Unity] 코루틴을 사용, 캐릭터의 이동과 공격, 몬스터의 피격 애니메이션 실행 (0) | 2019.11.15 |
[Unity] Coroutine 사용해서 공격 애니메이션 실행시 문제, 공격 타이밍이 맞지 않음 (0) | 2019.11.15 |
[Unity] 2019-11-14 코루틴 사용 (0) | 2019.11.14 |