애니메이션
기본 상태인 Idle 애니메이션, 걷는 상태인 Walk 애니메이션, 공격 모션인 Attack 애니메이션을 추가했다.
Bool 형 Walk, Attack 파라미터를 설정해서 Idle 상태에서
Attack 이 True 이면 Attack 애니메이션으로 Walk 가 True 이면 Walk 애니메이션으로 진행되고
반대의 경우 다시 Idle 로 돌아오게 설정하였다.
걷기 모션
스크립트에서 Animator 컴포넌트를 불러온 후 SetBool 함수를 통해서 파라미터를 컨트롤 해준다.
프레임이 Update 될 때 마다 Walk 함수는 항상 false 상태를 유지해서 화살표 키보드 입력을 받기 전에는
항상 Idle 상태를 유지한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class PlayerMove : MonoBehaviour
{
Animator MyAnimator;
// Start is called before the first frame update
void Start()
{
MyAnimator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
MyAnimator.SetBool("Walk", false);
if (Input.GetKey(KeyCode.RightArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(0.001f * speed, 0, 0);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(-0.001f * speed, 0, 0);
}
if (Input.GetKeyDown(KeyCode.LeftAlt) && GroundTag)
{
GroundTag = false;
MyRigidbody2D.AddForce(new Vector2(0, 100*jumpforce));
}
}
}
공격 모션
걷기 모션과 같은 방법으로 코드를 추가해준다.
공격 모션 중 점프하거나 방향 전환 하는 것을 막기위해서 CurAttackTime 을 설정하고
공격을 시작하면 시간을 부여한 후 Time.deltaTime 으로 CurAttackTime 의 값을 줄인다.
공격이 끝나 CurAttackTime 이 0 이하가 되면 점프나 방향 전환이 가능하다.
공격 중 움직이는 것은 가능하게 하기 위해 transform.localScale 을 변경하는 코드만 적용하였다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class PlayerMove : MonoBehaviour
{
Animator MyAnimator;
private float AttackTime = 0.56f;
public float CurAttackTime = 0;
// Start is called before the first frame update
void Start()
{
MyAnimator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
MyAnimator.SetBool("Walk", false);
MyAnimator.SetBool("Attack", false);
if (Input.GetKey(KeyCode.RightArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(0.001f * speed, 0, 0);
if (CurAttackTime <= 0)
transform.localScale = Vector2.one;
}
if (Input.GetKey(KeyCode.LeftArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(-0.001f * speed, 0, 0);
if (CurAttackTime <= 0)
transform.localScale = new Vector2(-1, 1);
}
if (Input.GetKeyDown(KeyCode.LeftAlt) && (GroundTag && CurAttackTime <= 0))
{
GroundTag = false;
MyRigidbody2D.AddForce(new Vector2(0, 100*jumpforce));
}
if (CurAttackTime <= 0) // 공격시작
{
MyAnimator.SetBool("Attack", true);
CurAttackTime = AttackTime;
if (Input.GetKeyDown(KeyCode.LeftControl))
CurAttackTime = AttackTime;
}
if (CurAttackTime >= 0)
CurAttackTime -= Time.deltaTime;
}
}
공격 범위 설정
오버랩 박스를 사용하여 공격 범위를 설정하였고 방향 전환 시 공격 범위도 변경하기 위해서 현재 보고있는 방향을 나타내는 Bool 형 RightState 변수를 선언했다.
오버랩 박스의 위치는 플레이어 위치에 (1.255f, -0.3f) 를 더한 값이다.
공격 범위에 Enemy 가 충돌하면 "Hi" 라는 메시지를 출력한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class PlayerMove : MonoBehaviour
{
Rigidbody2D MyRigidbody2D;
Animator MyAnimator;
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.name == "Ground")
GroundTag = true;
}
private float AttackTime = 0.56f;
public float CurAttackTime = 0;
public Transform AttackPos;
private Vector2 AttackBoxSize = new Vector2(0.94f, 1.19f);
bool RightState;
bool GroundTag = false;
// Start is called before the first frame update
void Start()
{
MyRigidbody2D = GetComponent<Rigidbody2D>();
MyAnimator = GetComponent<Animator>();
RightState = true;
}
// Update is called once per frame
void Update()
{
MyAnimator.SetBool("Walk", false);
MyAnimator.SetBool("Attack", false);
if (Input.GetKey(KeyCode.RightArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(0.001f * speed, 0, 0);
if (CurAttackTime <= 0)
{
transform.localScale = Vector2.one;
RightState = true;
}
}
if (Input.GetKey(KeyCode.LeftArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(-0.001f * speed, 0, 0);
if (CurAttackTime <= 0)
{
transform.localScale = new Vector2(-1, 1);
RightState = false;
}
}
if (RightState == true)
AttackPos.position = new Vector2(transform.position.x + 1.255f, transform.position.y - 0.3f);
else
AttackPos.position = new Vector2(transform.position.x - 1.255f, transform.position.y - 0.3f);
if (Input.GetKeyDown(KeyCode.LeftAlt) && (GroundTag && CurAttackTime <= 0))
{
GroundTag = false;
MyRigidbody2D.AddForce(new Vector2(0, 100*jumpforce));
}
if (CurAttackTime <= 0) // 공격시작
{
if (Input.GetKeyDown(KeyCode.LeftControl))
{
MyAnimator.SetBool("Attack", true);
CurAttackTime = AttackTime;
Collider2D[] collider2Ds = Physics2D.OverlapBoxAll(AttackPos.position, AttackBoxSize, 0);
foreach (Collider2D collider in collider2Ds)
{
if (collider.name == "Enemy")
{
Debug.Log("hi");
}
}
}
}
if (CurAttackTime >= 0)
CurAttackTime -= Time.deltaTime;
}
}
최종 코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class PlayerMove : MonoBehaviour
{
Rigidbody2D MyRigidbody2D;
Animator MyAnimator;
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.name == "Ground")
GroundTag = true;
}
public int speed = 6;
public int jumpforce = 8;
private float AttackTime = 0.56f;
public float CurAttackTime = 0;
public Transform AttackPos;
private Vector2 AttackBoxSize = new Vector2(0.94f, 1.19f);
bool RightState;
bool GroundTag = false;
// Start is called before the first frame update
void Start()
{
MyRigidbody2D = GetComponent<Rigidbody2D>();
MyAnimator = GetComponent<Animator>();
RightState = true;
}
// Update is called once per frame
void Update()
{
MyAnimator.SetBool("Walk", false);
MyAnimator.SetBool("Attack", false);
if (Input.GetKey(KeyCode.RightArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(0.001f * speed, 0, 0);
if (CurAttackTime <= 0)
{
transform.localScale = Vector2.one;
RightState = true;
}
}
if (Input.GetKey(KeyCode.LeftArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(-0.001f * speed, 0, 0);
if (CurAttackTime <= 0)
{
transform.localScale = new Vector2(-1, 1);
RightState = false;
}
}
if (RightState == true)
AttackPos.position = new Vector2(transform.position.x + 1.255f, transform.position.y - 0.3f);
else
AttackPos.position = new Vector2(transform.position.x - 1.255f, transform.position.y - 0.3f);
if (Input.GetKeyDown(KeyCode.LeftAlt) && (GroundTag && CurAttackTime <= 0))
{
GroundTag = false;
MyRigidbody2D.AddForce(new Vector2(0, 100*jumpforce));
}
if (CurAttackTime <= 0) // 공격시작
{
if (Input.GetKeyDown(KeyCode.LeftControl))
{
CurAttackTime = AttackTime;
Collider2D[] collider2Ds = Physics2D.OverlapBoxAll(AttackPos.position, AttackBoxSize, 0);
foreach (Collider2D collider in collider2Ds)
{
if (collider.name == "Enemy")
{
Debug.Log("hi");
}
}
}
}
if (CurAttackTime >= 0)
CurAttackTime -= Time.deltaTime;
}
}
결과물
앞으로 해야할 것
플레이어와 몬스터 체력 구현
피격 시 넉백, 이펙트 구현
플레이어와 몬스터 사망 구현
몬스터 스폰 구현
'유니티 > 유니티 연습프로젝트' 카테고리의 다른 글
[유니티/연습 프로젝트] 몬스터 스폰, 피격, 처치 구현 (0) | 2023.11.09 |
---|---|
[유니티/연습 프로젝트] 캐릭터 이동 (0) | 2023.10.06 |