유니티/수업 내용

[3D RPG 프로토타입] 몬스터와 전투 이벤트기반, 가장 가까운 적 찾기

hyunjin-dev-log 2021. 12. 23. 16:55
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestAttackMain : MonoBehaviour
{
    public UIInGame uiInGame;
    public TestHero hero;
    public TestMonster monster;

    void Start()
    {
        this.Init();
        this.InitUI();
    }

    private void Init()
    {
        this.monster.OnHit = (id, hp, maxHp) => {
            this.uiInGame.UpdateMonsterHp(hp, maxHp);
        };
        this.monster.OnDieEvent.AddListener((id) => {
            this.monster.Die();
        });

        this.monster.OnDieComplete = () => {
            Destroy(this.monster.gameObject);
            this.monster = null;
            this.uiInGame.HideUIMonsterHp();
        };

        this.monster.Init(100, 10);

        //게임 초기화 
        this.hero.OnAttackImpactEvent.AddListener((damage) =>
        {
            Debug.LogErrorFormat("OnAttackImpactEvent : {0}", damage);
            this.monster.Hit(damage);
        });
        this.hero.OnAttackComplete = (damage) => {
            Debug.LogErrorFormat("OnAttackComplete : {0}", damage);
        };
        //this.hero.OnAttackCompleteEvent.AddListener(() =>
        //{
        //    Debug.LogError("attack complete");
        //    this.hero.Idle();
        //});
        //this.hero.OnAttackImpact = () => {
        //    Debug.LogError("impact!");
        //};
        //this.hero.OnAttackComplete = () => {
        //    Debug.LogError("attackComplete");
        //    this.hero.Idle();
        //};
    }

    private void InitUI()
    {
        this.uiInGame.btn.onClick.AddListener(() => {
            this.hero.Attack(this.monster);
        });
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class TestHeroAttackImpactEvent : UnityEvent<float>
{

}

public class TestHero : MonoBehaviour
{
    private float damage = 11f;
    private TestMonster target;
    public Animation anim;
    //public System.Action OnAttackImpact;
    //public System.Action OnAttackComplete;
    //public UnityAction OnAttackImpact;
    //public UnityAction OnAttackComplete;
    public TestHeroAttackImpactEvent OnAttackImpactEvent = new TestHeroAttackImpactEvent();
    //public UnityEvent OnAttackCompleteEvent = new UnityEvent();
    public UnityAction<float> OnAttackComplete;

    public void SetTarget(TestMonster target)
    {
        this.target = target;
    }

    public void Attack(TestMonster target)
    {
        if (target == null) return;

        this.anim.Play("attack_sword_01");

        StartCoroutine(this.WaitForAttack());
    }

    private IEnumerator WaitForAttack()
    {
        yield return new WaitForSeconds(0.3f);
        //이벤트 
        //this.OnAttackImpact();
        OnAttackImpactEvent.Invoke(this.damage);

        yield return new WaitForSeconds(0.733f - 0.3f);

        this.OnAttackComplete(this.damage);
        //this.OnAttackCompleteEvent.Invoke();
    }

    public void Idle()
    {
        this.target = null;
        this.anim.Play("idle@loop");
    }


}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class TestMonster : TestMonsterBase
{
    public Animator anim;
    public UnityAction<int, float, float> OnHit;

    public override void Attack()
    {

    }

    public override void Hit(float damage)
    {
        base.Hit(damage);

        this.OnHit(this.Id, this.hp, this.maxHp);

        this.anim.SetTrigger("GetHit");
    }

    public override void Die()
    {
        this.anim.SetTrigger("Die");

        StartCoroutine(this.WaitForDieAnimation());
    }

    private IEnumerator WaitForDieAnimation()
    {
        yield return new WaitForSeconds(1.333f);

        this.OnDieComplete();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class TestMonsterBase : MonoBehaviour
{
    public int Id {
        get;
        protected set;
    }

    protected float hp;
    protected float maxHp;
    public UnityEvent<int> OnDieEvent = new UnityEvent<int>();
    public System.Action OnDieComplete;

    public virtual void Init(int id, float maxHp)
    {
        this.Id = id;
        this.maxHp = maxHp;
        this.hp = this.maxHp;
    }

    public virtual void Attack()
    { 

    }

    public virtual void Hit(float damage)
    {
        if (this.IsDie()) return;

        this.hp -= damage;
        if (this.hp <= 0) {
            this.hp = 0;
            this.OnDieEvent.Invoke(this.Id);
        }
    }

    public bool IsDie() {
        return this.hp <= 0;
    }

    public virtual void Die() { }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class TestMonsterBase : MonoBehaviour
{
    public int Id {
        get;
        protected set;
    }

    protected float hp;
    protected float maxHp;
    public UnityEvent<int> OnDieEvent = new UnityEvent<int>();
    public System.Action OnDieComplete;

    public virtual void Init(int id, float maxHp)
    {
        this.Id = id;
        this.maxHp = maxHp;
        this.hp = this.maxHp;
    }

    public virtual void Attack()
    { 

    }

    public virtual void Hit(float damage)
    {
        if (this.IsDie()) return;

        this.hp -= damage;
        if (this.hp <= 0) {
            this.hp = 0;
            this.OnDieEvent.Invoke(this.Id);
        }
    }

    public bool IsDie() {
        return this.hp <= 0;
    }

    public virtual void Die() { }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestSlime : TestMonsterBase
{
    public override void Hit(float damage)
    {
        base.Hit(damage);

        Debug.Log("play hit animation");
        this.transform.GetComponentInChildren<Animator>().SetTrigger("GetHit");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestBeholder : TestMonsterBase
{
    public override void Hit(float damage)
    {
        base.Hit(damage);

        Debug.Log("play hit animation");
        this.transform.GetComponentInChildren<Animator>().SetTrigger("GetHit");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class TestHeroAttackImpactEvent : UnityEvent<TestMonsterBase, float>
{

}

public class TestHero : MonoBehaviour
{
    private float damage = 11f;
    private TestMonsterBase target;
    public Animation anim;
    //public System.Action OnAttackImpact;
    //public System.Action OnAttackComplete;
    //public UnityAction OnAttackImpact;
    //public UnityAction OnAttackComplete;
    public TestHeroAttackImpactEvent OnAttackImpactEvent = new TestHeroAttackImpactEvent();
    //public UnityEvent OnAttackCompleteEvent = new UnityEvent();
    public UnityAction<float> OnAttackComplete;

    public void SetTarget(TestMonsterBase target)
    {
        this.target = target;
    }

    public void Attack(TestMonsterBase target)
    {
        if (target == null) return;

        this.target = target;

        this.anim.Play("attack_sword_01");

        StartCoroutine(this.WaitForAttack());
    }

    private IEnumerator WaitForAttack()
    {
        yield return new WaitForSeconds(0.3f);
        //이벤트 
        //this.OnAttackImpact();
        OnAttackImpactEvent.Invoke(this.target, this.damage);

        yield return new WaitForSeconds(0.733f - 0.3f);

        this.OnAttackComplete(this.damage);
        //this.OnAttackCompleteEvent.Invoke();
    }

    public void Idle()
    {
        this.target = null;
        this.anim.Play("idle@loop");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestAttackMain : MonoBehaviour
{
    public UIInGame uiInGame;
    public TestHero hero;
    public TestSlime slime;
    public TestBeholder beholder;
    private List<TestMonsterBase> monsters;

    void Start()
    {
        this.Init();
        this.InitUI();
    }

    private void Init()
    {
        this.monsters = new List<TestMonsterBase>();
        this.monsters.Add(this.slime);
        this.monsters.Add(this.beholder);

        this.hero.OnAttackImpactEvent.AddListener((target, damage) => {
            target.Hit(damage);
        });

        this.hero.OnAttackComplete = (damage) => { 

        };
    }

    private void InitUI()
    {
        this.uiInGame.btn.onClick.AddListener(() => {

            Debug.Log("find nearest monster");
            var min = float.MaxValue;
            TestMonsterBase target = null;
            foreach (var monster in this.monsters)
            {
                var distance = Vector3.Distance(this.hero.transform.position, monster.transform.position);
                if (min > distance)
                {
                    min = distance;
                    target = monster;
                }
            }

            Debug.Log(target);

            Debug.DrawLine(this.hero.transform.position, target.transform.position, Color.red, 100);

            this.hero.Attack(target);
        });
    }
}