728x90
Test_BossMain
using System.Collections;
using System.Collections.Generic;
using Test4;
using UnityEngine;
using UnityEngine.UI;
namespace Test_Boss
{
public class Test_BossMain : MonoBehaviour
{
//[SerializeField]
//private Button btnMove;
//[SerializeField]
//private Button btnRemove;
[SerializeField]
private Bull bull;
[SerializeField]
private Hero hero;
void Start()
{
this.bull.onAttackComplete = () =>
{
this.bull.DetectAndMove();
};
this.bull.onMoveComplete = (nextState) =>
{
switch (nextState)
{
case "MOVE_BACK":
this.bull.MoveBack();
break;
case "ATTACK":
this.bull.Attack();
break;
case "DETECT_AND_MOVE":
this.bull.DetectAndMove();
break;
case "IDLE":
this.bull.Idle();
break;
}
};
this.bull.Init();
}
void Update()
{
//화면을 클릭하면 Ray를 만든다
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * 1000f, Color.red, 3f);
//Ray를 사용해서 충돌체크를 한다
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1000f))
{
//충돌을 감지해서
Debug.LogFormat("hit.collider: {0}", hit.collider);
this.hero.MoveForward(hit.point);
}
}
}
}
}
Bull
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test_Boss
{
public class Bull : MonoBehaviour
{
public enum eState
{
Idle, DetectAndMove, Attack, MoveBack
}
public System.Action<string> onMoveComplete;
public System.Action onAttackComplete;
[SerializeField]
private float sight = 5f;
[SerializeField]
private float range = 1f;
[SerializeField]
private float speed = 1f;
private Animator anim;
private Hero target;
private bool isWithinSight;
public float Range => this.range;
private Coroutine routine;
private Vector3 initPos;
private eState state = eState.Idle;
void Awake()
{
this.initPos = this.transform.position;
this.anim = GetComponent<Animator>();
}
public void Init()
{
this.DetectAndMove();
}
public void DetectAndMove()
{
//상태 -> Idle
this.state = eState.DetectAndMove;
if(this.routine != null)
StopCoroutine(this.routine);
this.anim.SetInteger("State", 0);
}
public void Idle()
{
this.state = eState.Idle;
if(this.routine != null)
StopCoroutine(this.routine);
this.anim.SetInteger("State", 0);
}
private IEnumerator CoDetectAndMove()
{
//매프레임마다 앞으로 이동
while (true)
{
//타겟을 검색
this.target = GameObject.FindObjectOfType<Hero>();
//거리를 계산하고
var distance = Vector3.Distance(this.transform.position, this.target.transform.position);
//시야안에 있는지 확인
if (distance <= this.sight)
{
Debug.DrawLine(this.transform.position, this.target.transform.position, Color.red);
this.isWithinSight = true;
}
else
{
this.target = null;
this.isWithinSight = false;
}
//시야에 들어왔다면
if (isWithinSight == true)
{
//이동 애니메이션 실행
this.anim.SetInteger("State", 1);
//대상을 바라보고
this.transform.LookAt(this.target.transform);
//이동
this.transform.Translate(Vector3.forward * this.speed * Time.deltaTime);
//거리를 계산하고
//var distance = Vector3.Distance(this.transform.position, this.target.transform.position);
//공격사거리 안에 들어오면
if (distance <= this.range)
{
//공격시작
this.onMoveComplete("ATTACK");
break;
}
var d = Vector3.Distance(this.transform.position, this.initPos);
Debug.Log(d);
if (d > 4f)
{
this.onMoveComplete("MOVE_BACK");
break;
}
}
else
{
//idle 애니메이션 실행
this.anim.SetInteger("State", 0);
}
yield return null;
}
}
public void Attack()
{
this.state = eState.Attack;
//루틴이 실행중이면 멈추기
if (this.routine != null)
StopCoroutine(this.routine);
this.routine = this.StartCoroutine(this.CoAttack());
}
private IEnumerator CoAttack()
{
this.anim.SetInteger("State", 2);
yield return new WaitForSeconds(1.0f);
this.onAttackComplete();
}
private void OnDrawGizmos()
{
//시야
Gizmos.color = Color.yellow;
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.sight, 20);
//공격사거리
Gizmos.color = Color.red;
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 350, this.range, 20);
}
public void MoveBack()
{
this.state = eState.MoveBack;
}
}
}
Hero
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test_Boss
{
public class Hero : MonoBehaviour
{
public System.Action onMoveComplete;
public System.Action onAttackCancel;
private Transform targetTrans;
private Vector3 tpos;
[SerializeField]
private float range = 1f;
public float Range => this.range;
void Start()
{
}
void Update()
{
}
public void MoveForward(Vector3 tpos)
{
this.tpos = tpos;
//방향 바라보기
this.transform.LookAt(this.tpos);
//코루틴 실행
this.StartCoroutine(this.CoMoveForward()); //문제없음
}
private IEnumerator CoMoveForward()
{
while (true)
{
//이동로직
this.transform.Translate(Vector3.forward * 2f * Time.deltaTime);
//거리구하기
float dis = Vector3.Distance(this.tpos, this.transform.position);
Debug.Log(dis);
if(dis <= 0.1f)
{
//도착
break;
}
yield return null;
}
Debug.Log("도착");
}
public void Attack(Transform targetTrans)
{
this.targetTrans = targetTrans;
this.StartCoroutine(this.CoAttack());
}
private IEnumerator CoAttack()
{
yield return null;
var dis = Vector3.Distance(this.transform.position, this.targetTrans.position);
//시야안에 있는지 확인
if(dis <= this.range)
{
//사거리안에 있다면 공격 애니메이션
}
else
{
this.onAttackCancel(); //공격 취소됨
}
}
private void OnDrawGizmos()
{
//공격사거리
Gizmos.color = Color.red;
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.range, 20);
}
}
}
TestMono
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test_Boss
{
public class TestMono : MonoBehaviour
{
void Start()
{
}
void Update()
{
}
}
}
'KDT > 유니티 기초' 카테고리의 다른 글
23/08/15 [광복절 과제] (0) | 2023.08.15 |
---|---|
23/08/13 [주말과제] SimpleRPG 통합하기 (1) | 2023.08.13 |
23/08/12 [주말과제] 복소수와 사원수 (1) | 2023.08.12 |
23/08/11 할거 (0) | 2023.08.11 |
23/08/10 내용 복습 (0) | 2023.08.10 |