using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class BombGuyController : MonoBehaviour
{
private Rigidbody2D rBody2D;
[SerializeField] private float jumpForce = 10f; // 점프하는 힘
[SerializeField] private float moveForce = 30f; // 이동하는 힘
[SerializeField] private GameObject BombPrefab;
[SerializeField] private Transform ShootPoint;
private Animator anim;
private State currentState = State.Idle;
private bool isJumping = false;
private enum State
{
Idle,
Walk,
Jump
}
void Start()
{
rBody2D = GetComponent<Rigidbody2D>();
anim = GetComponentInChildren<Animator>();
StartCoroutine(HandleMovement());
StartCoroutine(ShootBomb());
}
void Update()
{
AdjustAnimationSpeed();
}
void AdjustAnimationSpeed()
{
float speed = Mathf.Abs(rBody2D.velocity.x);
float animationSpeed = speed / 2.0f;
anim.speed = Mathf.Max(1, animationSpeed);
}
IEnumerator ShootBomb()
{
while (true)
{
if (Input.GetKeyDown(KeyCode.A))
{
// BombPrefab을 ShootPoint의 위치에 생성하고, 회전은 기본값(Quaternion.identity)으로 설정
Instantiate(BombPrefab, ShootPoint.transform.position, Quaternion.identity);
}
yield return null;
}
}
IEnumerator HandleMovement()
{
while (true) // 무한 루프를 사용하여 지속적으로 입력을 체크
{
if (Input.GetKey(KeyCode.Space) && !isJumping && Mathf.Abs(rBody2D.velocity.y) <= 0f)
{
rBody2D.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
isJumping = true;
SetAnimationState(State.Jump);
}
int dirX = 0;
if (Input.GetKey(KeyCode.LeftArrow))
dirX = -1;
if (Input.GetKey(KeyCode.RightArrow))
dirX = 1;
if (dirX != 0 && !isJumping)
{
SetAnimationState(State.Walk);
}
else if (!isJumping)
{
SetAnimationState(State.Idle);
}
transform.localScale = dirX != 0 ? new Vector3(2 * dirX, 2, 1) : transform.localScale;
if (dirX == 0)
{
rBody2D.velocity = new Vector2(0, rBody2D.velocity.y);
}
float speedX = Mathf.Abs(rBody2D.velocity.x);
if (speedX < 2f)
{
rBody2D.AddForce(transform.right * dirX * moveForce);
}
transform.position = new Vector3(Mathf.Clamp(transform.position.x, -8.2f, 8.4f), transform.position.y, transform.position.z);
yield return null; // 다음 프레임까지 대기
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.CompareTag("ground"))
{
isJumping = false;
if (currentState == State.Jump)
{
SetAnimationState(State.Idle);
}
}
}
private void SetAnimationState(State newState)
{
if (currentState != newState)
{
currentState = newState;
anim.SetInteger("State", AnimationStateToInt(currentState));
}
}
private int AnimationStateToInt(State state)
{
switch (state)
{
case State.Idle:
return 0;
case State.Walk:
return 1;
case State.Jump:
return 2;
default:
return 0;
}
}
}
2. BombGuyController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BombController : MonoBehaviour
{
private Rigidbody2D rBody2D;
private Animator anim;
void Start()
{
rBody2D = GetComponent<Rigidbody2D>();
anim = GetComponentInChildren<Animator>();
StartCoroutine(BombAnimation());
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("ground"))
{
this.rBody2D.gravityScale = 0f;
this.rBody2D.velocity = Vector3.zero;
}
}
IEnumerator BombAnimation()
{
yield return new WaitForSeconds(2f);
anim.SetInteger("State", 1);
BoxCollider2D boxCollider = GetComponent<BoxCollider2D>();
if (boxCollider != null)
{
Destroy(boxCollider);
}
}
}
3. BombController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyCaptainController : MonoBehaviour
{
private Rigidbody2D rBody2D;
private Animator anim;
[SerializeField] private int HP = 3; // 예시로 HP를 3으로 설정합니다.
private enum State
{
Idle,
Hit,
DeadHit
}
private State currentState = State.Idle;
void Start()
{
rBody2D = GetComponent<Rigidbody2D>();
anim = GetComponentInChildren<Animator>();
}
void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Bomb"))
{
TakeDamage();
}
}
void TakeDamage()
{
HP -= 1; // HP를 1 감소
if (HP <= 0) // DeadHit 상태가 아니면 DeadHit 애니메이션 재생
{
SetAnimationState(State.DeadHit);
}
else if (HP > 0)
{
SetAnimationState(State.Hit); // 아니면 Hit 애니메이션 재생
}
}
private void SetAnimationState(State newState)
{
currentState = newState;
anim.SetInteger("State", (int)newState);
}
}
4. EnemyCaptainController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AutoBombDestroy : MonoBehaviour
{
public void DestroyObject() //이벤트 핸들러 메서드
{
GameObject parentObject = gameObject.transform.parent.gameObject;
Destroy(parentObject);
}
}
5. AutoBombDestroy.cs
using UnityEngine;
public class ReturnIdle : MonoBehaviour
{
private Animator anim;
void Start()
{
anim = GetComponent<Animator>();
}
public void ResetToIdle()
{
anim.SetInteger("State", 0); // Idle 상태로 설정
}
}
6. ReturnIdle.cs
코루틴 까지는 금방 했는데,
애니메이션 이벤트에서 한번 꼬여가지고 고생한 것 같다.
그래도 막혔던 부분을 해결하니
또 하나 배운 것 같다.
적(Captain)이 죽을 떄 넉백되면서 죽게 만들고 싶었는데
자꾸 parameter에서 ignore가 뜨면서 애니메이션 실행에 문제가 발생해서
그 부분이 좀 아쉽긴 하다.
반응형
'산대특 > 게임 클라이언트 프로그래밍' 카테고리의 다른 글
[AppleCatch] AppleCatch 만들기 (0) | 2024.02.05 |
---|---|
[ShootingGame] 이동, 발사, 충돌, 애니메이션(연출) 만들기 (0) | 2024.02.05 |
[SpaceShooter2D] 비행기[Player] GetAxis로 이동하기 + 정규화(Normalize) (0) | 2024.02.02 |
[Bamsongi] 화면 클릭해서 밤송이 던지기 + 파티클 (0) | 2024.02.02 |
Update와 Coroutine (0) | 2024.02.02 |