

처음에 this.targetPosition을 넣어놓지 않아서 Hero캐릭터가 몬스터를 중간에 누르면 가던 와중에 공격을 해서 왜 그런지 몰랐고 머리 아팠는데 저거를 넣어놓지 않아서 그랬던 것이었다.


공격을 한번만 해서 왜 그러지.. 했는데 Move가 끝나고 target이 있으면 공격하는 대리자를 입력하나만 해놔서 움직이지 않으면 공격도 안했었다.
그래서 거리에 들어왔을 때 공격 메서드를 넣어줘서 움직이지 않아도 누르면 공격하게 되었다.

float distance부터 아래 4줄을 if (distance <= 2f 랑 0.1f) 안에다 넣어놨었는데 밖에다 놔둬도 break문으로 나오게하면 되서 불필요한 코드를 안쓸 수 있었다.
GameEnums
csharp
닫기using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Real
{
public class GameEnums
{
public enum eHeroType
{
Idle, Run, Attack
}
public enum eMonsterType
{
Idle, Hit, Die
}
}
}
HeroController
csharp
닫기using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace Real
{
public class HeroController : MonoBehaviour
{
[SerializeField]
private float radius = 1f;
private float moveSpeed = 3f;
private float impact = 0.39984f;
private MonsterController target;
private GameEnums.eHeroType state;
private Vector3 targetPosition;
private Coroutine moveRoutine;
private Coroutine attackRoutine;
private Animator anim;
public Action<MonsterController> onMoveComplete;
public float Radius
{
get
{
return this.radius;
}
}
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
}
//몬스터타겟이 들어오면 거기로 움직이기
public void Move(MonsterController target)
{
this.target = target;
this.targetPosition = this.target.gameObject.transform.position;
if (this.moveRoutine != null)
{
this.StopCoroutine(this.moveRoutine);
}
this.moveRoutine = this.StartCoroutine(this.CoMove());
}
//땅을 타겟하면 거기로 움직이기
public void Move(Vector3 targetPosition)
{
this.target = null;
this.targetPosition = targetPosition;
if(this.moveRoutine != null)
{
this.StopCoroutine(this.moveRoutine);
}
this.moveRoutine = this.StartCoroutine(this.CoMove());
}
//코루틴으로 움직이기
private IEnumerator CoMove()
{
while (true)
{
float distance = Vector3.Distance(this.transform.position, this.targetPosition);
this.transform.LookAt(this.targetPosition);
this.PlayAnimation(GameEnums.eHeroType.Run);
this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
//몬스터 타겟이 있을경우
if (this.target != null)
{
if (distance <= 2f)
{
break;
}
}
else //몬스터 타겟이 없을경우
{
//거리가 0.1f라면
if (distance <= 0.1f)
{
break;
}
}
yield return null;
}
this.PlayAnimation(GameEnums.eHeroType.Idle);
this.onMoveComplete(this.target);
}
//공격
public void Attack(MonsterController target)
{
if (this.attackRoutine != null)
{
this.StopCoroutine(this.attackRoutine);
}
this.attackRoutine = this.StartCoroutine(this.CoAttack());
}
//코루틴 공격
private IEnumerator CoAttack()
{
this.PlayAnimation(GameEnums.eHeroType.Attack);
yield return new WaitForSeconds(this.impact);
Debug.Log("impact");
AnimatorStateInfo animStateInfo = this.anim.GetCurrentAnimatorStateInfo(0);
yield return new WaitForSeconds(animStateInfo.length);
this.PlayAnimation(GameEnums.eHeroType.Idle);
}
//애니메이션 멤버메서드
private void PlayAnimation(GameEnums.eHeroType state)
{
if(this.state != state)
{
this.state = state;
this.anim.SetInteger("State", (int)state);
}
}
private void OnDrawGizmos()
{
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, 1, 40);
}
}
}
Real_SimpleRpgSceneMain
csharp
닫기using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static UnityEngine.GraphicsBuffer;
namespace Real
{
public class Real_SimpleRpgSceneMain : MonoBehaviour
{
[SerializeField]
private HeroController heroController;
private MonsterController monsterController;
// Start is called before the first frame update
void Start()
{
this.heroController.onMoveComplete = (target) => {
//타겟이 있다면
if (target != null)
{
this.heroController.transform.LookAt(target.transform);
this.heroController.Attack(target);
this.monsterController.HitDamage();
}
};
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 2f);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, 100f)) {
//몬스터라면
if (hit.collider.tag == "Monster")
{
MonsterController monsterController = hit.collider.gameObject.GetComponent<MonsterController>();
this.monsterController = monsterController;
//두 원점사이의 거리
float distance = Vector3.Distance(this.heroController.transform.position, hit.collider.gameObject.transform.position);
//반지름의 합
float sumRadius = this.heroController.Radius + this.monsterController.Radius;
Debug.LogFormat("distance, sumRadius: {0}, {1}", distance, sumRadius);
Debug.LogFormat("hit.collider.tag : {0}", hit.collider.tag);
//distance <= sumRadius 가 true라면
if (distance <= sumRadius)
{
this.heroController.Attack(this.monsterController);
this.monsterController.HitDamage();
}
else
{
this.heroController.Move(this.monsterController);
}
}
//땅이라면
else if (hit.collider.tag == "Ground")
{
Debug.LogFormat("hit.collider.tag : {0}", hit.collider.tag);
this.heroController.Move(hit.point);
}
}
}
}
}
}
MonsterController
csharp
닫기using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Real
{
public class MonsterController : MonoBehaviour
{
[SerializeField]
private float radius = 1f;
private float impact = 0.39984f;
private Coroutine hitRoutine;
private Animator anim;
private GameEnums.eMonsterType state;
public float Radius
{
get
{
return this.radius;
}
}
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
}
public void HitDamage()
{
if (this.hitRoutine != null)
{
this.StopCoroutine(this.hitRoutine);
}
this.hitRoutine = this.StartCoroutine(this.CoWaitCompleteHitDamage());
}
private IEnumerator CoWaitCompleteHitDamage()
{
yield return null;
yield return new WaitForSeconds(this.impact);
this.PlayAnimation(GameEnums.eMonsterType.Hit);
AnimatorStateInfo animStateInfo = this.anim.GetCurrentAnimatorStateInfo(0);
yield return new WaitForSeconds(animStateInfo.length - this.impact * 2);
this.PlayAnimation(GameEnums.eMonsterType.Idle);
}
public void PlayAnimation(GameEnums.eMonsterType state)
{
if (this.state != null)
{
this.state = state;
this.anim.SetInteger("State", (int)state);
}
}
private void OnDrawGizmos()
{
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, 1, 40);
}
}
}

'유니티 기초' 카테고리의 다른 글
디자인패턴 (0) | 2023.08.14 |
---|---|
[주말과제] 복소수와 사원수 (1) | 2023.08.14 |
FadeIn, FadeOut (0) | 2023.08.11 |
무기, 방패 장착, 제거 - 생성 시 부모를 지정, 생성 후 부모를 지정 (0) | 2023.08.11 |
몬스터 2초 후 삭제, 아이템 드랍, 아이템 씬에서 제거 후 아이템 로그 출력 (0) | 2023.08.10 |