using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonsterMove : MonoBehaviour
{
Rigidbody2D rigid;
Animator anim;
SpriteRenderer spriteRenderer;
public int nextMove;//다음 행동지표를 결정할 변수
// Start is called before the first frame update
private void Awake()
{
rigid = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
// nextMove = Random.Range(-1, 2); //챗
spriteRenderer = GetComponent<SpriteRenderer>();
Invoke("Think", 5); // 초기화 함수 안에 넣어서 실행될 때 마다(최초 1회) nextMove변수가 초기화 되도록함
}
// Update is called once per frame
void FixedUpdate()
{
nextMove = Random.Range(2, 5);
//Move
rigid.velocity = new Vector2(nextMove, rigid.velocity.y); //nextMove 에 0:멈춤 -1:왼쪽 1:오른쪽 으로 이동
//자신의 한 칸 앞 지형을 탐색해야하므로 position.x + nextMove(-1,1,0이므로 적절함)
Vector2 frontVec = new Vector2(rigid.position.x + nextMove * 5f, rigid.position.y);
//한칸 앞 부분아래 쪽으로 ray를 쏨
Debug.DrawRay(frontVec, Vector3.down, new Color(0, 1, 0));
// 레이캐스트의 시작 위치 (몬스터의 현재 위치)
Vector2 startVec = new Vector2(transform.position.x, transform.position.y);
// 레이를 양옆 방향으로 쏩니다. 오른쪽 방향(1)과 왼쪽 방향(-1) 두 번 쏩니다.
RaycastHit2D hitRight = Physics2D.Raycast(startVec, Vector2.right, 1, LayerMask.GetMask("Wall"));
RaycastHit2D hitLeft = Physics2D.Raycast(startVec, Vector2.left, 1, LayerMask.GetMask("Wall"));
// 양옆에 벽이 있으면 Turn 함수 호출
if (hitRight.collider != null || hitLeft.collider != null)
{
Turn();
}
}
//재귀함수
void Think()
{
//Set Next Active
nextMove = Random.Range(0, 2) * 2 - 1; // -1 또는 1을 랜덤하게 설정
anim.SetInteger("WalkSpeed", nextMove);
//Flip Sprite
if (nextMove != 0)
{
spriteRenderer.flipX = nextMove == 1;
}
MoveMonster();
//Recursive
float nextThinkTime = Random.Range(2f, 5f);
Invoke("Think", nextThinkTime);
}
void Turn()
{
nextMove = -nextMove;
spriteRenderer.flipX = nextMove == 1;
float nextThinkTime = Random.Range(0.1f, 0.2f);
Invoke("Think", nextThinkTime);
}
void MoveMonster()
{
float moveSpeed = 3.0f; // 이동 속도를 조절해보세요
Vector2 newPosition = rigid.position + new Vector2(nextMove * moveSpeed * Time.fixedDeltaTime, 0);
rigid.MovePosition(newPosition);
}
void FlipSprite(bool flip)
{
// 스프라이트 렌더러 컴포넌트 가져오기
SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();
// 좌우 반전 적용
spriteRenderer.flipX = flip;
}
}
실질적인 오류는 안뜨는데 왜 오른쪽으로만 이동하는지 모르겠습니다..
- dc official App
fixedUpdate()에서 nextMove = Random.Range(2, 5); 이거 때문 인가 ㅇㅂㅇ)..
고칠 방법이 잇나 - dc App
nextMove = Random.Range(2, 5); 이거만 지워도 좌우로 왔다리 갔다리 함.
nextMove = Random.Range(2, 5); 이거랑 내가 애니메이션 갖고 있지 않으니까 애니메이션이랑 스프라이트 랜더러 관련한 코드 뺐더니 좌우로 움직임.
근데 나 궁금한게 있는데 fixedUpdate 안에다가 Think 안 넣고 재귀로 한 이유가 있으셈?
게이야 혹시 댓글 아직 보고 있으면 nextMove = Random.Range(2, 5); <<요거만 지워보고 좌우로 움직이는지 확인 점 해주라.
time 붙여서 랜덤실행하려고했지 - dc App
ㅇㅋ flex 놔둘게 - dc App
움직여짐 아 골때리네 근데 자기 스폰 위치에서 도네 생각을 안하고 - dc App
아니 내가 재귀로 한게 왜 궁금하냐면 왜 함수 실행하고서 그 함수 안에서 재귀호출하면 재귀호출된 함수가 닫힐때까지 이전 함수까지 전부 다 스택에 머물러 있쟈나.. 근데 내가 유니티 안 만진지 오래되서 햇갈리는데 invoke 쓰면 이전 함수 닫고 재귀함수 호출하게 되는거임?? 메모리 때문에 그럼;
아아 그래서 내가 그거 준거야 delay - dc App
근데 구지 재귀 안써도 됨..실험한거라 - dc App
그 이전에 거 닫고 재귀시키는거 아녔나 헷갈리네 - dc App
그리고 찾아보니까 인보크 자체가 오브젝트 활성화랑 별개로 cancelinvoke해줘야 한대서 뭔가 좀 뭔가인거 같음 ㅋㅋ;; 코루틴은 어때??
ㄴ...나 뉴비야..코루틴은 코틀린밖에 몰라.. - dc App
그럼 찾아보고 천천히 생각혀~~ 암튼 개발 열심히 하는거 같아서 너무 좋다 ㅎㅎ.. 힘내! 재밌게 만들고!
감사합니다 형님 한가지만 더 여쭈어봐도 될까요flixp 쓰면 왜 작동이 안될까요 - dc App
flixp가 fixedUpdate() 말하는 거면 어떤식으로 작동을 안하는 건지 모르겠는데 그게 물리연산 위해서 0.02초 주기로 실행되는 함수거든? 그래서 Think()에 Debug.Log("Think") 이거 넣고 콘솔창 보면서 Think가 진짜 빈번하게 실행되서 그런 건지 한번 확인해줘~
내 생각엔 이동 방향을 바꿔주는 Think()를 코드 따로 안 바꾸고 넣으면 너무 자주 이동방향을 바꾸려고 해서 결과적으로 가만히 있는 양태를 보일꺼 같아~
감사합니데이 - dc App
아.. 이 코드 찾아보니까
https://www.youtube.com/watch?v=7MYUOzgZTf8&list=PLO-mt5Iu5TeZGR_y6mHmTWyo0RyGgO0N_&index=6
<<이거 참고했나보구나.. 그럼 Invoke 써도 되겠다~~ 영상 후반부 보니까 Turn에서 cancelinvoke를 해주네..
spriteRenderer.flipX 으로 Flip 하면, 좌표도 좌우반전되는거아닐까?
그럼 어캐고치지 - dc App
Flip안했을땐 -> 로 이동했다면 지금은 Flip했을때 방향을 <- 이동하는거면, 한번 둘 다 ->로 바꿔보면 이문제인지 아닌지 알 수 있지 않을까?