using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyMoving : MonoBehaviour
{
Rigidbody2D rigid;
public int nextMove;//다음 행동지표를 결정할 변수
Animator animator;
SpriteRenderer spriteRenderer;
public float speed;
public int hp;
public GameObject player;
// Start is called before the first frame update
private void Awake() {
animator = GetComponent<Animator>();
spriteRenderer = GetComponent<SpriteRenderer>();
rigid = GetComponent<Rigidbody2D>();
Invoke("Think", 0f); // 초기화 함수 안에 넣어서 실행될 때 마다(최초 1회) nextMove변수가 초기화 되도록함
}
// Update is called once per frame
void FixedUpdate()
{
//Move
rigid.velocity = new Vector2(nextMove*speed,rigid.velocity.y); //nextMove 에 0:멈춤 -1:왼쪽 1:오른쪽 으로 이동
Vector2 detectPlayer = new Vector2(transform.position.x, transform.position.y);
Debug.DrawRay(detectPlayer, Vector2.left*1f, new Color(0,1,0));
//Platform check(맵 앞이 낭떨어지면 뒤돌기 위해서 지형을 탐색)
//자신의 한 칸 앞 지형을 탐색해야하므로 position.x + nextMove(-1,1,0이므로 적절함)
Vector2 frontVec = new Vector2(rigid.position.x + nextMove*0.4f, rigid.position.y);
//한칸 앞 부분아래 쪽으로 ray를 쏨
//레이를 쏴서 맞은 오브젝트를 탐지
RaycastHit2D raycast = Physics2D.Raycast(frontVec, Vector3.down,1,LayerMask.GetMask("Ground"));
//탐지된 오브젝트가 null : 그 앞에 지형이 없음
if(!raycast.collider){
Turn();
}
/*if(Detect_player())
{
StartCoroutine("Attack");
}
*/
}
void Think(){//몬스터가 스스로 생각해서 판단 (-1:왼쪽이동 ,1:오른쪽 이동 ,0:멈춤 으로 3가지 행동을 판단)
//Set Next Active
//Random.Range : 최소<= 난수 <최대 /범위의 랜덤 수를 생성(최대는 제외이므로 주의해야함)
nextMove = Random.Range(-1,2);
//Sprite Animation
//WalkSpeed변수를 nextMove로 초기화
animator.SetInteger("isRun",nextMove);
//Flip Sprite
if(nextMove != 0) //서있을 때 굳이 방향을 바꿀 필요가 없음
spriteRenderer.flipX = nextMove == 1; //nextmove 가 1이면 방향을 반대로 변경
//Recursive (재귀함수는 가장 아래에 쓰는게 기본적)
float time = Random.Range(2f, 5f); //생각하는 시간을 랜덤으로 부여
//Think(); : 재귀함수 : 딜레이를 쓰지 않으면 CPU과부화 되므로 재귀함수쓸 때는 항상 주의 ->Think()를 직접 호출하는 대신 Invoke()사용
Invoke("Think", time); //매개변수로 받은 함수를 time초의 딜레이를 부여하여 재실행
}
void Turn(){
nextMove= nextMove*(-1); //우리가 직접 방향을 바꾸어 주었으니 Think는 잠시 멈추어야함
spriteRenderer.flipX = nextMove == 1;
CancelInvoke(); //think를 잠시 멈춘 후 재실행
Invoke("Think",2);
}
//공격모션 재현 // ray를 쐈을때 플레이어이면 공격모션 발동
bool Detect_player()
{
Vector2 detect_player = new Vector2(rigid.position.x+nextMove,rigid.position.y);
RaycastHit2D ray_player = Physics2D.Raycast(detect_player,new Vector3(nextMove,0,0),1,LayerMask.GetMask("Player"));
if(ray_player)
{
return true;
}
else
{
return false;
}
}
IEnumerator Attack()
{
CancelInvoke();
animator.SetBool(“isAttack”, true);
yield return new WaitForSeconds(1.1f); // 애니메이션 끝날 때까지 대기
Vector2 enemyPosition = new Vector2(transform.position.x, transform.position.y);
int direction = (nextMove >= 0) ? -1 : 1;
RaycastHit2D rayPlayer = Physics2D.Raycast(enemyPosition, Vector2.left * direction, 2f, LayerMask.GetMask("Player"));
bool detect=(rayPlayer) ? true : false;
if (detect)
{
GameObject player = rayPlayer.collider.gameObject;
int directionX = transform.position.x - player.transform.position.x > 0 ? -1 : 1;
player.GetComponent<Rigidbody2D>().AddForce(new Vector2(directionX*1f, 1f), ForceMode2D.Impulse);
player.GetComponent<PlayerMovement>().onCrouch(true);
yield return new WaitForSeconds(0.6f);
player.GetComponent<PlayerMovement>().onCrouch(false);
detect=false;
}
animator.SetBool("isAttack", false);
// 여기에 플레이어 hp 삭제
StopCoroutine("Attack");
player.GetComponent<PlayerMovement>().onCrouch(false);
Invoke("Think", 1f); // 대신에 Invoke 대신에 1초 후에 호출
}
IEnumerator Die()
{
CancelInvoke();
StopCoroutine("Attack");
yield return new WaitForSeconds(0.7f);
Destroy(gameObject);
}
void Update()
{
if(Detect_player())
{
StartCoroutine("Attack");
}
if(Input.GetKeyDown(KeyCode.C))
{
hp--;
animator.SetInteger("Death",hp);
}
if(hp<0)
{
StartCoroutine("Die");
}
}
}
it is my code but i try to some test ex) nextMove==0 then go attack
but don’t play attack animation
and i set when isRun ==0 and isAttack true// then go attack from idle but doesn’t not play