유니티 기초
보스 시야 들어가면 따라오기
노재두내
2023. 8. 14. 17:32
1. 시야 들어가면 색깔 바뀌기 + hero 움직임
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test_Boss
{
public class Bull : MonoBehaviour
{
public System.Action onDetectTarget;
public System.Action onLoseTarget;
public System.Action onMoveComplete;
public System.Action onAttackCancel;
private Transform target;
[SerializeField]
private float sight = 7f;
[SerializeField]
private float range = 3f;
public float Range => this.range;
private Animator anim;
private bool isWithinSight;
private Coroutine stateRoutine;
void Start()
{
this.anim = this.GetComponent<Animator>();
}
//초기화
public void Init()
{
this.FindTarget();//타겟을 찾는다
this.stateRoutine = this.StartCoroutine(this.CoCheckWithinHeroTheRange());
}
//타겟찾기
private void FindTarget()
{
var go = GameObject.Find("HeroPrefab");
if (go != null)
this.target = go.transform;
}
private IEnumerator CoCheckWithinHeroTheRange()//범위내에 히어로 있는지 체크(움직이지 X)
{
while (true) {
var dis = Vector3.Distance(this.transform.position, this.target.transform.position);
//Debug.Log(dis);
this.isWithinSight = dis <= this.sight;//시야내에 들어오면 true 밖이면 false
if (this.isWithinSight) {
this.onDetectTarget();
break;
}
yield return null;
}
}
//탐지하고 움직이기
public void DetectAndMove()
{
if (this.stateRoutine != null) {//범위내에 히어로가 있으면
this.StopCoroutine(this.stateRoutine);//찾는걸 멈춘다.
}
this.stateRoutine = this.StartCoroutine(this.CoDetectAndMove());//범위내에 히어로 없으면 계속 탐지?
}
private IEnumerator CoDetectAndMove()
{
this.transform.LookAt(this.target);
//이동 애니메이션 실행
while (true)
{
var dis = Vector3.Distance(this.transform.position, this.target.transform.position);
//Debug.Log(dis);
this.isWithinSight = dis <= this.sight;
if (this.isWithinSight == false)//시야 내에 없으면 멈춘다
{
this.onLoseTarget();//다켓이 시야에서 나가면 idle()호풀, idle 출력
break;
}
this.transform.Translate(Vector3.forward * 1f * Time.deltaTime);//있으면 움직인다.
yield return null;
}
}
//idle 상태일때
public void Idle()
{
Debug.Log("Idle");
this.StartCoroutine(this.CoCheckWithinHeroTheRange());//범위에 있는지 체크한다(idle상태일때)
}
//public void MoveForward(Transform targetTrans)
//{
// this.targetTrans = targetTrans;
// //this.StartCoroutine(coMoveForward());
// this.StartCoroutine(this.CoMoveForward());
//}
//private IEnumerator CoMoveForward()
//{
// while (true){
// if (targetTrans == null)
// break;
// var dis = Vector3.Distance(this.transform.position, this.targetTrans.position);
// if (dis > 7)//시야 안에 들어오면
// {
// yield return null;
// continue;
// }
// this.transform.LookAt(this.targetTrans);
// this.transform.Translate(Vector3.forward * 1f * Time.deltaTime);
// if (dis <= this.range)//공격사거리안에 들어오면
// {
// Debug.Log("<color=red>공격사거리 안에 들어왔습니다.</color>");
// break;
// }
// yield return null;
// }
// if (this.targetTrans == null)
// {
// Debug.Log("타겟을 잃었습니다.");
// this.anim.SetInteger("State", 0);
// }
// else
// {
// Debug.Log("이동을 완료함");
// this.onMoveComplete();
// }
//}
//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)
// {
// anim.SetInteger("State", 3);
// }
// else
// {
// this.onAttackCancel();
// anim.SetInteger("State", 1);
// }
//}
private void OnDrawGizmos()
{
//시야
if (isWithinSight)//범위 안에 있으면 빨간색
{
Gizmos.color = Color.red;
}
else
{
Gizmos.color = Color.white;
}
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.sight, 20);
//공격사거리
//Gizmos.color = Color.red;
//GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.range, 20);
}
}
}
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
namespace Test_Boss
{
public class HeroController : MonoBehaviour
{
private Vector3 targetPosition;
private Coroutine moveRoutine;
private float radius = 1f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void Move(Vector3 hitPosition)
{
this.targetPosition = hitPosition;
if (this.moveRoutine != null)
{
this.StopCoroutine(this.moveRoutine);
}
this.moveRoutine = StartCoroutine(CoMove());
}
private IEnumerator CoMove()
{
while (true)
{
this.transform.LookAt(this.targetPosition);
this.transform.Translate(Vector3.forward * 2f * Time.deltaTime);
float dis = Vector3.Distance(this.transform.position, this.targetPosition);
if (dis <= 0.1f)
{
break;
}
yield return null;
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.radius, 20);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace Test_Boss
{
public class Test_BossSceneMain : MonoBehaviour
{
//[SerializeField]
//private GameObject bossPrefab;
//[SerializeField]
//private GameObject heroPrefab;
[SerializeField]
private Button btnMove;
[SerializeField]
private Button btnRemove;
[SerializeField]
private Bull bull;
[SerializeField]
private Transform targetTrans;
[SerializeField]
private HeroController heroController;
// Start is called before the first frame update
void Start()
{
this.bull.onDetectTarget = () => {
this.bull.DetectAndMove();
};
this.bull.onLoseTarget = () => {
this.bull.Idle();
};
//this.bull.onAttackCancel = () =>
//{
// this.BullMoveAndAttack();//거리계산
//};
//this.bull.onMoveComplete = () =>
//{
// //Debug.LogError("!");
// this.BullMoveAndAttack();//거리계산
//};
////this.CreateBoss();
////this.CreateHero();
//this.btnMove.onClick.AddListener(() =>
//{
// Debug.Log("move");
// this.bull.MoveForward(targetTrans);
//});
//this.btnRemove.onClick.AddListener(() =>
//{
// Debug.Log("remove");
// //Destroy(this.bull.gameObject);
// //Destroy(this.gameObject);
// Destroy(this.targetTrans.gameObject);
//});
this.bull.Init();
}
//private void BullMoveAndAttack()
//{
// Debug.Log("사거리 계산");
// var dis = Vector3.Distance(this.transform.position, this.targetTrans.position);
// if (dis <= this.bull.Range)
// {
// Debug.Log("공격");
// this.bull.Attack(targetTrans);
// }
// else
// {
// Debug.Log("이동");
// this.bull.MoveForward(targetTrans);
// }
//}
//private void CreateBoss()
//{
// GameObject bossGo = Instantiate(this.bossPrefab);
// bossGo.transform.position = new Vector3(6, 0, -9);
//}
//private void CreateHero()
//{
// GameObject heroGo = Instantiate(this.heroPrefab);
//}
//// Update is called once per frame
private 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)){
this.heroController.Move(hit.point);
}
}
}
}
}
2. 애니메이션 적용(공격빼고)
bull
private IEnumerator CoDetectAndMove()
{
this.transform.LookAt(this.target);
this.anim.SetInteger("State", 1);
//이동 애니메이션 실행
while (true)
{
var dis = Vector3.Distance(this.transform.position, this.target.transform.position);
//Debug.Log(dis);
this.isWithinSight = dis <= this.sight;
if (this.isWithinSight == false)//시야 내에 없으면 멈춘다
{
this.onLoseTarget();//타켓이 시야에서 나가면 idle()호풀, idle 출력
break;
}
this.transform.Translate(Vector3.forward * 1f * Time.deltaTime);//있으면 움직인다.
yield return null;
}
}
//idle 상태일때
public void Idle()
{
Debug.Log("Idle");
this.anim.SetInteger("State", 0);
this.StartCoroutine(this.CoCheckWithinHeroTheRange());//범위에 있는지 체크한다(idle상태일때)
}
public void Attack()
{
//var dis = Vector3.Distance(this.transform.position, this.target.transform.position);
//if (dis <= 1f)
//{
this.anim.SetInteger("State", 3);
//}
}
heroController
private IEnumerator CoMove()
{
while (true)
{
this.transform.LookAt(this.targetPosition);
this.anim.SetInteger("State", 1);
this.transform.Translate(Vector3.forward * 2f * Time.deltaTime);
float dis = Vector3.Distance(this.transform.position, this.targetPosition);
if (dis <= 0.1f)
{
this.anim.SetInteger("State", 0);
break;
}
yield return null;
}
}
bossScneneMain
void Start()
{
this.bull.onDetectTarget = () => {
this.bull.DetectAndMove();
};
this.bull.onLoseTarget = () => {
this.bull.Idle();
};
this.bull.onAttack = () =>
{
this.bull.Attack();
};