[Unity] Coroutine 사용해서 공격 애니메이션 실행시 문제, 공격 타이밍이 맞지 않음

APP 2019. 11. 15. 08:38

문제 해결

https://koolwin1.tistory.com/249

 

코루틴을 사용, 캐릭터의 이동과 공격, 몬스터의 피격 애니메이션 실행

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using Newtonsoft.Json; public class App : MonoBehaviour { public Button btnStage; public Button b..

koolwin1.tistory.com

 

 

코루틴 사용시 Attack()메서드 안에 elapsedTime을 계산해서 몬스터와 상호작용하고 있다. 

 

이걸 각각의 코루틴을 사용하도록 고치면 될듯하다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Newtonsoft.Json;
 
public class App : MonoBehaviour
{
    public Button btnStage;
    public Button btnHero;
    public Button btnMonster;
    public Button btnAttack;
    public Dictionary<int, CharacterData> dicCharacterData;
    public Dictionary<int, StageData> dicStageData;
    Dictionary<int, GameObject> dicPrefab;
    private Stage stage;
    private Dictionary<int, Character> dicCharacter;
    private Vector3 heroPos;
    private float speed = 0.05f;
    private Hero hero;
    private Monster monster;
    private Animation heroAnim;
    private Animation monsterAnim;
    private bool IsHeroAnimPlaying = false;
    private bool IsMonsterAnimPlaying = false;    
    float elapsedTime;
    float monsterDmgElapsedTime;
    int cnt;
    Coroutine coMoveCharacter;
 
    private void Awake()
    {
 
        this.dicCharacterData = new Dictionary<int, CharacterData>();
        this.dicStageData = new Dictionary<int, StageData>();
        this.dicPrefab = new Dictionary<int, GameObject>();
        this.dicCharacter = new Dictionary<int, Character>();
 
        CharacterData[] arrCharacterData = JsonConvert.DeserializeObject<CharacterData[]>(Resources.Load<TextAsset>("Data/character_data").text);
 
        foreach (CharacterData data in arrCharacterData)
        {
            this.dicCharacterData.Add(data.id, data);
        }
 
        StageData[] arrStageData = JsonConvert.DeserializeObject<StageData[]>(Resources.Load<TextAsset>("Data/stage_data").text);
        foreach (StageData data in arrStageData)
        {
            this.dicStageData.Add(data.id, data);
        }
 
        LoadCharacterPrefabs();
        LoadStagePrefabs();
    }
    public void LoadCharacterPrefabs()
    {
        foreach (KeyValuePair<int, CharacterData> keyValuePair in dicCharacterData)
        {
            this.dicPrefab.Add(keyValuePair.Key, Resources.Load<GameObject>($"Prefabs/{keyValuePair.Value.prefab_name}"));
        }
    }
    public void LoadStagePrefabs()
    {
        foreach (KeyValuePair<int, StageData> keyValuePair in dicStageData)
        {
            this.dicPrefab.Add(keyValuePair.Key, Resources.Load<GameObject>($"Prefabs/{keyValuePair.Value.prefab_name}"));
        }
    }
 
    //Start is called before the first frame update
    void Start()
    {
 
        btnStage.onClick.AddListener(() =>
        {
            Debug.Log("Stage버튼");
            this.CreateStage(dicStageData[1000]);
        });
 
        btnHero.onClick.AddListener(() =>
        {
            Debug.Log("Hero버튼");
            this.hero = this.CreateCharacter<Hero>(dicCharacterData[100]);
            this.heroAnim = this.hero.GetComponentInChildren<Animation>();
            dicCharacter[100].transform.SetParent(GameUtils.SearchHierarchyForBone(this.stage.transform, "HeroInitPos"), false);
            this.btnAttack.gameObject.SetActive(true);
        });
 
        btnMonster.onClick.AddListener(() =>
        {
            Debug.Log("Monster버튼");
            this.monster = this.CreateCharacter<Monster>(dicCharacterData[200]);
            dicCharacter[200].transform.SetParent(GameUtils.SearchHierarchyForBone(this.stage.transform, "MonsterInitPos"), false);
            this.monsterAnim = this.monster.GetComponentInChildren<Animation>();
        });
 
        btnAttack.onClick.AddListener(() =>
        {
            Debug.Log("Attack버튼");
            //Debug.Log(Time.deltaTime);
            coMoveCharacter = StartCoroutine("MoveCharacter");
 
            StartCoroutine(Attack());
 
        });
 
    }
 
    //Coroutine coroutine1;
    //Coroutine coroutine2;
    //float el1;
    //float el2;
    //public void Start()
    //{
 
    //    coroutine1 = StartCoroutine(LoopA());
    //    coroutine2 = StartCoroutine(LoopB());      
 
    //   // StartCoroutine(Stopp());
 
    //}
 
    //IEnumerator LoopA()
    //{
    //    for (int i = 0; i < 20; i++)
    //    {
    //        print("i의 값 = " + i);
    //        print($"               i: {el1 += Time.deltaTime}");
    //        yield return new WaitForEndOfFrame();
    //    }
    //}
    //IEnumerator LoopB()
    //{
    //    for (int x = 0; x < 20; x++)
    //    {
    //        print("x의 값 = " + x);
    //        print($"               x: {el2+=Time.deltaTime}");
    //        yield return new WaitForSeconds(1f);
    //    }
    //}
    //IEnumerator Stopp()
    //{
    //    yield return new WaitForSeconds(1f);
    //    StopCoroutine(coroutine1);
 
    //    yield return new WaitForSeconds(2f);
    //    StopCoroutine(coroutine2);
    //}
    public void CreateStage(StageData stageData)
    {
        GameObject go = new GameObject(stageData.name);
        Stage stage = go.AddComponent<Stage>();
        GameObject model = Instantiate(dicPrefab[stageData.id]);
        model.transform.SetParent(stage.transform, false);
        model.transform.localPosition = Vector3.zero;
        this.stage = stage;
    }
    public T CreateCharacter<T>(CharacterData characterData) where T : Character
    {
        GameObject go = new GameObject(characterData.name);
        T character = go.AddComponent<T>();
        GameObject model = Instantiate(dicPrefab[characterData.id]);
        model.transform.SetParent(character.transform, false);
        model.transform.localPosition = Vector3.zero;
        dicCharacter.Add(characterData.id, character);
        return character;
    }
 
    IEnumerator MoveCharacter()
    {
        while (true)
        {
            yield return new WaitForSeconds(0.02f);
            //Debug.Log($"{Time.deltaTime}{Vector3.Distance(hero.transform.position, monster.transform.position) > dicCharacterData[100].atk_range} {Vector3.Distance(hero.transform.position, monster.transform.position)}  {dicCharacterData[100].atk_range}");
            if(Vector3.Distance(hero.transform.position, monster.transform.position) > dicCharacterData[100].atk_range)
            {
                this.hero.transform.position = Vector3.MoveTowards(this.hero.transform.position, this.monster.transform.position, speed);
                if (IsHeroAnimPlaying == false)
                {
                    this.heroAnim.Play("run@loop");
                    IsHeroAnimPlaying = true;                    
                }
                //Debug.LogFormat("Distance: {0}", Vector3.Distance(hero.transform.position, monster.transform.position));
                if (Vector3.Distance(hero.transform.position, monster.transform.position) <= dicCharacterData[100].atk_range)
                {
                    IsHeroAnimPlaying = false;
                    StopCoroutine(coMoveCharacter);
                    Debug.Log("StopCoroutine");                  
                }              
            }  
        }        
    }
    IEnumerator Attack()
    {
        while(true)
        {
            yield return new WaitForSeconds(0.02f);            
            if(Vector3.Distance(hero.transform.position, monster.transform.position) <= dicCharacterData[100].atk_range)
            {
                if (IsHeroAnimPlaying == false)
                {
                    this.heroAnim.Play("attack_sword_02");
                    elapsedTime += Time.deltaTime;
                }
                if(IsHeroAnimPlaying==true)
                {
                    elapsedTime += Time.deltaTime;
                }
               
                if (0.59f < elapsedTime && elapsedTime < 0.61f)
                {
                    this.monsterAnim.Play("Anim_Damage");
                    IsMonsterAnimPlaying = true;
                    monsterDmgElapsedTime += Time.deltaTime;
                    //Debug.LogFormat("몬스터 애니메이션 ElapsedTime2 : {0}", elapsedTime2);
                }
                if(IsMonsterAnimPlaying)
                {
                    monsterDmgElapsedTime += Time.deltaTime;
                }
                if (0.79f < elapsedTime && elapsedTime < 0.81f)
                {
                    IsHeroAnimPlaying = false;
                    elapsedTime = 0;
                }
                if (0.447f < monsterDmgElapsedTime && monsterDmgElapsedTime < 0.477f)
                {
                    //Debug.LogFormat("초기화시간   {0}", elapsedTime2);
                    this.monsterAnim.Play("Anim_Idle");
                    monsterDmgElapsedTime = 0;                    
                }
            }
        }
    }
    //IEnumerator MoveCharacter()
    //{
 
    //    while (true)
    //    {
    //        yield return new WaitForSeconds(0.02f);
    //        //Debug.Log($"Dist:{Vector3.Distance(hero.transform.position, monster.transform.position)}  atk_range:{dicCharacterData[100].atk_range}");
    //        if (Vector3.Distance(hero.transform.position, monster.transform.position) > dicCharacterData[100].atk_range)
    //        {
    //            this.hero.transform.position = Vector3.MoveTowards(this.hero.transform.position, this.monster.transform.position, speed);
    //            if (IsHeroAnimPlaying == false)
    //            {
    //                IsHeroAnimPlaying = true;
    //                this.heroAnim.Play("run@loop");
    //            }
    //        }
    //        else if (Vector3.Distance(hero.transform.position, monster.transform.position) <= dicCharacterData[100].atk_range)
    //        {
 
 
    //            if (IsMonsterAnimPlaying == true)
    //            {
    //                elapsedTime2 += Time.deltaTime;
    //            }
    //            if (cnt == 0)
    //            {
    //                cnt++;
    //                this.heroAnim.Play("attack_sword_01");
    //                elapsedTime += Time.deltaTime;
    //            }
    //            elapsedTime += Time.deltaTime;
    //            if (0.256f < elapsedTime && elapsedTime < 0.276f)
    //            {
    //                this.monsterAnim.Play("Anim_Damage");
    //                IsMonsterAnimPlaying = true;
    //                elapsedTime2 += Time.deltaTime;
    //                Debug.LogFormat("맞는시간{0}", elapsedTime2);
    //            }
    //            if (0.447f < elapsedTime2 && elapsedTime2 < 0.477f)
    //            {
    //                Debug.LogFormat("초기화시간{0}", elapsedTime2);
    //                this.monsterAnim.Play("Anim_Idle");
    //                elapsedTime2 = 0;
    //                Debug.LogFormat("Time2초기화되었다");
    //            }
    //            if (0.723f < elapsedTime && elapsedTime < 0.743f)
    //            {
    //                IsHeroAnimPlaying = false;
    //                elapsedTime = 0;
    //                cnt = 0;
    //            }
    //        }
    //    }
    //}
    // Update is called once per frame
    //void Update()
    //{
    //    if (hero != null && monster != null)
    //    {
    //        if (Vector3.Distance(hero.transform.position, monster.transform.position) <= dicCharacterData[100].atk_range)
    //        {
    //            monsterDmgElapsedTime += Time.deltaTime;
    //            this.heroAnim.Play("attack_sword_02");
    //            IsHeroAnimPlaying = true;
    //            elapsedTime += Time.deltaTime;
    //            Debug.Log($"첫번째elapsedTime:{elapsedTime}");
    //            if (IsHeroAnimPlaying == true)
    //            {
    //                Debug.Log(elapsedTime);
    //                elapsedTime += Time.deltaTime;
    //            }
    //            if (IsHeroAnimPlaying == false)
    //            {
    //                if (cnt < 5)
    //                {
    //                    cnt++;
    //                    this.heroAnim.Play("attack_sword_02");
    //                    IsHeroAnimPlaying = true;
    //                    elapsedTime += Time.deltaTime;
    //                    Debug.Log($"첫번째elapsedTime:{elapsedTime}");
    //                }
    //            }
    //            영웅이 칼을 타점에 맞추는 시간
    //            if (0.59f < elapsedTime && elapsedTime < 0.61f)
    //            {
    //                monsterDmgElapsedTime = 0;
    //                IsMonsterAnimPlaying = true;
    //                Debug.LogFormat("몬스터 애니메이션 ElapsedTime2 : {0}", elapsedTime2);
    //            }
    //            if (IsMonsterAnimPlaying)
    //            {
    //                this.monsterAnim.Play("Anim_Damage");
    //                monsterDmgElapsedTime += Time.deltaTime;
    //            }
    //            영웅의 공격 동작이 끝나는 시간
    //            if (0.79f < elapsedTime/* && elapsedTime < 0.81f*/)
    //            {
    //                IsHeroAnimPlaying = false;
    //                elapsedTime = 0;
    //                IsMonsterAnimPlaying = false;
    //            }
 
    //            몬스터의 피격 동작이 끝나는 시간
    //            if (0.467f < monsterDmgElapsedTime)
    //            {
    //                this.monsterAnim.Play("Anim_Idle");
    //                IsMonsterAnimPlaying = false;
    //                monsterDmgElapsedTime = 0;
    //                if (IsMonsterAnimPlaying != true)
    //                {
 
    //                    IsMonsterAnimPlaying = true;
    //                }
    //            }
    //        }
    //    }
    //}
}

 

 

: