using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HeroController : MonoBehaviour
{
private Animator anim;
private Vector3 targetPosition;
private float moveSpeed = 1f;
private bool isMove = false;
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (isMove)
{
//이동하기
this.anim.SetInteger("State", 1);
this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
//위치 distance로 바꿔주기
float distance = Vector3.Distance(this.transform.position, this.targetPosition);
if(distance <= 0.1f)
{
this.isMove = false;
}
}
else
{
this.anim.SetInteger("State", 0);
this.transform.Translate(Vector3.zero);
}
}
//목표 : targetPosition까지 가기
public void Move(Vector3 targetPosition)
{
//위치 저장
this.targetPosition = targetPosition;
//목표 바라보기
this.transform.LookAt(targetPosition);
this.isMove = true;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SimpleRpgSceneMain : MonoBehaviour
{
[SerializeField]
private HeroController heroController;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
//마우스 왼쪽 클릭시
if (Input.GetMouseButtonDown(0))
{
//Ray로 마우스 위치 전달받기
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//마우스위치 찍어보기
Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 2f);
//찍은 위치 저장하기
RaycastHit hit;
//충돌햇다면 true ,, 아니면 false
if(Physics.Raycast(ray, out hit, 100f))
{
//이동하기.. 하지만 이 위치(hit.point)는 목표이고 이동해야함
this.heroController.Move(hit.point);
}
}
}
}
HeroController에서 목표위치와 Hero캐릭터 위치랑 거리를 어떻게 해주지.. 생각해보고 뭐로하더라 기억이 안나서 한번 봤다.
코루틴 + 대리자 사용
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HeroController : MonoBehaviour
{
private Animator anim;
private Vector3 targetPosition;
private Coroutine moveRoutine;
public System.Action onMoveComplete;
private float moveSpeed = 1f;
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
}
//코루틴 사용
private IEnumerator CoMove()
{
while(true)
{
//목표 바라보기
this.transform.LookAt(this.targetPosition);
//이동하기
this.anim.SetInteger("State", 1);
this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
//위치 distance로 바꿔주기
float distance = Vector3.Distance(this.transform.position, this.targetPosition);
if (distance <= 0.1f)
{
break;
}
yield return null;
}
this.anim.SetInteger("State", 0);
this.transform.Translate(Vector3.zero);
this.onMoveComplete();
}
//목표 : targetPosition까지 가기
public void Move(Vector3 targetPosition)
{
//위치 저장
this.targetPosition = targetPosition;
//코루틴이 실행중이라면
if(this.moveRoutine != null)
{
this.StopCoroutine(this.CoMove());
}
this.moveRoutine = this.StartCoroutine(this.CoMove());
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SimpleRpgSceneMain : MonoBehaviour
{
[SerializeField]
private HeroController heroController;
// Start is called before the first frame update
void Start()
{
this.heroController.onMoveComplete = (() => {
Debug.Log("이동완료");
});
}
// Update is called once per frame
void Update()
{
//마우스 왼쪽 클릭시
if (Input.GetMouseButtonDown(0))
{
//Ray로 마우스 위치 전달받기
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//마우스위치 찍어보기
Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 2f);
//찍은 위치 저장하기
RaycastHit hit;
//충돌햇다면 true ,, 아니면 false
if(Physics.Raycast(ray, out hit, 100f))
{
//이동하기.. 하지만 이 위치(hit.point)는 목표이고 이동해야함
this.heroController.Move(hit.point);
}
}
}
}
코루틴 .. yield return null이 처음에 이해가 안됐는데 distance가 <= 0.1f에 도달해서 while문을 빠져나가기 전까지 계속 실행해주는 것 같다. distance가 거리에 도달하면 멈추고 State 상태를 0으로 만들어서 Idle 상태로 만들어준다.
대리자 .. 학교에서할 때는 뭔지도 잘 모르는 상태로 사용했었는데 State 0 상태일 때 this.onMoveComplete();를 호출해서 대리자로 사용하는것을 이해했다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HeroController : MonoBehaviour
{
private Animator anim;
private Vector3 targetPosition;
private MonsterController target;
private Coroutine moveRoutine;
public System.Action<MonsterController> onMoveComplete;
private float moveSpeed = 1f;
public float radius = 1f;
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
}
//코루틴 사용
private IEnumerator CoMove()
{
while(true)
{
//목표 바라보기
this.transform.LookAt(this.targetPosition);
//이동하기
this.anim.SetInteger("State", 1);
this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
//위치 distance로 바꿔주기
float distance = Vector3.Distance(this.transform.position, this.targetPosition);
//타겟이 있을 경우
if (this.target != null)
{
if (distance <= 2f)
{
break;
}
}
else
{
if(distance <= 0.1f)
{
break;
}
}
yield return null;
}
this.anim.SetInteger("State", 0);
this.onMoveComplete(this.target);
}
//Method Overload
public void Move(MonsterController target)
{
this.target = target;
this.targetPosition = this.target.gameObject.transform.position;
//코루틴이 실행중이라면
if (this.moveRoutine != null)
{
this.StopCoroutine(this.CoMove());
}
this.moveRoutine = this.StartCoroutine(this.CoMove());
}
//목표 : targetPosition까지 가기
public void Move(Vector3 targetPosition)
{
//타겟 지움
this.target = null;
//위치 저장
this.targetPosition = targetPosition;
//코루틴이 실행중이라면
if(this.moveRoutine != null)
{
this.StopCoroutine(this.CoMove());
}
this.moveRoutine = this.StartCoroutine(this.CoMove());
}
public void Attack()
{
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(this.transform.position, this.radius);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SimpleRpgSceneMain : MonoBehaviour
{
[SerializeField]
private HeroController heroController;
// Start is called before the first frame update
void Start()
{
this.heroController.onMoveComplete = ((target) => {
Debug.Log("이동완료");
});
}
// Update is called once per frame
void Update()
{
//마우스 왼쪽 클릭시
if (Input.GetMouseButtonDown(0))
{
//Ray로 마우스 위치 전달받기
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//마우스위치 찍어보기
Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 2f);
//찍은 위치 저장하기
RaycastHit hit;
//충돌햇다면 true ,, 아니면 false
if(Physics.Raycast(ray, out hit, 100f))
{
//충돌 tag 정보 확인
Debug.Log(hit.collider.tag);
if(hit.collider.tag == "Monster")
{
MonsterController monsterController = hit.collider.gameObject.GetComponent<MonsterController>();
//거리 합 구하기
float distance = Vector3.Distance(this.transform.position, hit.collider.gameObject.transform.position);
//반지름의 합 구하기
float sumRadius = this.heroController.radius + monsterController.radius;
//사거리 안에 들어오면
if(distance <= sumRadius)
{
//공격
}
else
{
//이동
this.heroController.Move(monsterController);
}
}
else if(hit.collider.tag == "Ground")
{
this.heroController.Move(hit.point);
}
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonsterController : MonoBehaviour
{
public float radius = 1f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(this.transform.position, this.radius);
}
}
뭔가.. 오류가 난다 실질적 오류는 아니지만 땅을 계속 연속 클릭하면 속도가 계속 빨라진다 왜 그런걸까?
빨라지는 오류를 찾았다.
이 부분이 this.StopCoroutine이 계속 this.CoMove())로 받고있어서 다른 곳을 지정할 때마다 StopCoroutine이 실행되서 this.CoMove())가 실행되었던 것 같다. 다시 this.moveRoutine으로 받아주었다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HeroController : MonoBehaviour
{
private Animator anim;
private Vector3 targetPosition;
private MonsterController target;
private Coroutine moveRoutine;
public System.Action<MonsterController> onMoveComplete;
private float moveSpeed = 1f;
public float radius = 1f;
// Start is called before the first frame update
void Start()
{
this.anim = GetComponent<Animator>();
}
//코루틴 사용
private IEnumerator CoMove()
{
while(true)
{
//목표 바라보기
this.transform.LookAt(this.targetPosition);
//이동하기
this.anim.SetInteger("State", 1);
this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
//위치 distance로 바꿔주기
float distance = Vector3.Distance(this.transform.position, this.targetPosition);
//타겟이 있을 경우
if (this.target != null)
{
if (distance <= 2f)
{
break;
}
}
else
{
if(distance <= 0.1f)
{
break;
}
}
yield return null;
}
this.anim.SetInteger("State", 0);
this.onMoveComplete(this.target);
}
//Method Overload
public void Move(MonsterController target)
{
this.target = target;
this.targetPosition = this.target.gameObject.transform.position;
//코루틴이 실행중이라면
if (this.moveRoutine != null)
{
this.StopCoroutine(this.CoMove());
}
this.moveRoutine = this.StartCoroutine(this.CoMove());
}
//목표 : targetPosition까지 가기
public void Move(Vector3 targetPosition)
{
//타겟 지움
this.target = null;
//위치 저장
this.targetPosition = targetPosition;
//코루틴이 실행중이라면
if(this.moveRoutine != null)
{
this.StopCoroutine(this.CoMove());
}
this.moveRoutine = this.StartCoroutine(this.CoMove());
}
public void Attack(MonsterController target)
{
this.anim.SetInteger("State", 2);
this.StartCoroutine(this.CoAttack());
}
private IEnumerator CoAttack()
{
yield return new WaitForSeconds(0.1f);
yield return new WaitForSeconds(0.73f);
this.anim.SetInteger("State", 0);
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(this.transform.position, this.radius);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SimpleRpgSceneMain : MonoBehaviour
{
[SerializeField]
private HeroController heroController;
// Start is called before the first frame update
void Start()
{
this.heroController.onMoveComplete = ((target) => {
Debug.Log("이동완료");
if(target != null)
{
this.heroController.Attack(target);
}
});
}
// Update is called once per frame
void Update()
{
//마우스 왼쪽 클릭시
if (Input.GetMouseButtonDown(0))
{
//Ray로 마우스 위치 전달받기
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//마우스위치 찍어보기
Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 2f);
//찍은 위치 저장하기
RaycastHit hit;
//충돌햇다면 true ,, 아니면 false
if(Physics.Raycast(ray, out hit, 100f))
{
//충돌 tag 정보 확인
Debug.Log(hit.collider.tag);
if(hit.collider.tag == "Monster")
{
MonsterController monsterController = hit.collider.gameObject.GetComponent<MonsterController>();
//거리 합 구하기
float distance = Vector3.Distance(this.transform.position, hit.collider.gameObject.transform.position);
//반지름의 합 구하기
float sumRadius = this.heroController.radius + monsterController.radius;
//사거리 안에 들어오면
if(distance <= sumRadius)
{
//공격
}
else
{
//이동
this.heroController.Move(monsterController);
}
}
else if(hit.collider.tag == "Ground")
{
this.heroController.Move(hit.point);
}
}
}
}
}
공격하기
'유니티 기초 > 복습' 카테고리의 다른 글
[주말과제] SimpleRPG 합치기 (1) | 2023.08.14 |
---|---|
로비씬, 사과, 폭탄 [복습] (0) | 2023.08.08 |
챕터6 ClimbCloud [미완] - 복습 (0) | 2023.08.04 |
챕터 5 고양이 탈출 복습 - [완] (0) | 2023.08.04 |
챕터5 고양이탈출 - CatEscape - 복습 (0) | 2023.08.02 |