🎮 Game Dev (게임개발)/PC (데스크탑, 노트북, 터치패널)
[3D 액션게임] 04.무기 획득과 변경
- -
🔔 유튜브 크리에이터 골든메탈님의 유니티강의 3D 쿼터뷰 액션게임 [BE5] 를 보고 공부하여 작성한 게시글입니다! 🔔
플레이어 스크립트 코드 전체 보기
더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float speed;
public GameObject[] weapons;
public bool[] hasWeapons;
float hAxis;
float vAxis;
bool rDown;
bool jDown;
bool isJump;
bool isDodge;
bool isSwap;
bool iDown;
bool sDown1;
bool sDown2;
bool sDown3;
Vector3 moveVec;
Vector3 dodgeVec;
Rigidbody rigid;
Animator anim;
GameObject nearObject;
GameObject equipWeapon;
int equipWeaponIndex = -1;
// Start is called before the first frame update
void Start()
{
}
void Awake()
{
rigid = GetComponent<Rigidbody>();
anim = GetComponentInChildren<Animator>();
}
// Update is called once per frame
void Update()
{
GetInput();
Move();
Turn();
Jump();
Dodge();
Interation();
Swap();
}
void GetInput()
{
// 키보드입력에 따라 0 ~ 1로 변환 left right up down
hAxis = Input.GetAxisRaw("Horizontal");
vAxis = Input.GetAxisRaw("Vertical");
rDown = Input.GetButton("Run");
jDown = Input.GetButtonDown("Jump");
iDown = Input.GetButtonDown("Interation");
sDown1 = Input.GetButtonDown("Swap1");
sDown2 = Input.GetButtonDown("Swap2");
sDown3 = Input.GetButtonDown("Swap3");
}
void Move()
{
// x y z
moveVec = new Vector3(hAxis, 0, vAxis).normalized;
// 회피 시 업데이트 안되게
if (isDodge)
moveVec = dodgeVec;
// 스왑 시 못움직이게
if (isSwap)
moveVec = Vector3.zero;
// transform
transform.position += moveVec * (rDown ? 1.3f : 1f) * speed * Time.deltaTime;
// animator
anim.SetBool("isWalk", moveVec != Vector3.zero);
anim.SetBool("isRun", rDown);
}
void Turn()
{
// Rotation
transform.LookAt(transform.position + moveVec);
}
void Jump()
{
if(jDown && moveVec == Vector3.zero && !isJump && !isDodge) {
// 물리엔진에 힘을 준다. 여기선 즉발적인 Impulse
rigid.AddForce(Vector3.up * 15, ForceMode.Impulse);
anim.SetBool("isJump", true);
anim.SetTrigger("doJump");
isJump = true;
}
}
void Dodge()
{
// 이동하면서 점프할때,
if (jDown && moveVec != Vector3.zero && !isJump && !isDodge)
{
dodgeVec = moveVec;
speed *= 2;
anim.SetTrigger("doDodge");
isDodge = true;
Invoke("DodgeOut", 0.5f); // 시간지연 라이브러리 기능
}
}
void DodgeOut()
{
speed *= 0.5f;
isDodge = false;
}
void Swap()
{
if (sDown1 && (!hasWeapons[0] || equipWeaponIndex == 0))
return;
if (sDown2 && (!hasWeapons[1] || equipWeaponIndex == 1))
return;
if (sDown3 && (!hasWeapons[2] || equipWeaponIndex == 2))
return;
int weaponIndex = -1;
if (sDown1) weaponIndex = 0;
if (sDown2) weaponIndex = 1;
if (sDown3) weaponIndex = 2;
// 1, 2 ,3 버튼 누를때
if((sDown1 || sDown2 || sDown3) && !isJump && !isDodge) {
if(equipWeapon != null)
equipWeapon.SetActive(false);
equipWeaponIndex = weaponIndex;
equipWeapon = weapons[weaponIndex];
equipWeapon.SetActive(true);
anim.SetTrigger("doSwap");
// 스왑 중
isSwap = true;
Invoke("SwapOut", 0.4f);
}
}
void SwapOut()
{
isSwap = false;
}
void Interation()
{
if(iDown && nearObject != null && !isJump && !isDodge) {
if(nearObject.tag == "Weapon") {
Item item = nearObject.GetComponent<Item>();
int weaponIndex = item.value;
hasWeapons[weaponIndex] = true;
Destroy(nearObject);
}
}
}
// 충돌 시 이벤트 함수로 착지 구현
void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "Floor"){
isJump = false;
anim.SetBool("isJump", false);
}
}
private void OnTriggerStay(Collider other)
{
if (other.tag == "Weapon")
nearObject = other.gameObject;
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "Weapon")
nearObject = null;
}
}
🧷 1. 오브젝트 감지
- 무기 인식
/* Player Script , 기존 Script에서 해당하는 부분만을 표현했습니다. */
public class Player : MonoBehaviour
{
GameObject nearObject;
private void OnTriggerStay(Collider other)
{
if (other.tag == "Weapon")
nearObject = other.gameObject;
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "Weapon")
nearObject = null;
}
}
- 주위에 있는 Object를 인식하기 위한 GameObject 변수를 만듭니다.
- OnTriggerStay 로, 근처 item collision 에 닿고 있을때 무기면, nearObject에 gameObject를 넣어줍니다.
- OnTriggerExit 로 Item 근처에서 떨어질때는, null값으로 바꿔줍니다.
🧷 2. 무기 장착하기
- 무기 인벤토리에 넣기
- 아이템이 근처에 있을시 획득 할 단축키를 Interation이름의 "e" key로 지정해주었습니다.
그 다음 플레이어의 스크립트로 돌아와
/* Player Script , 기존 Script에서 해당하는 부분만을 표현했습니다. */
public class Player : MonoBehaviour
{
public bool[] hasWeapons;
GameObject nearObject;
bool iDown;
void Update()
{
Interation();
}
void GetInput()
{
iDown = Input.GetButtonDown("Interation");
}
void Interation()
{
if(iDown && nearObject != null && !isJump && !isDodge) {
if(nearObject.tag == "Weapon") {
Item item = nearObject.GetComponent<Item>();
int weaponIndex = item.value;
hasWeapons[weaponIndex] = true;
Destroy(nearObject);
}
}
}
}
- iDown 변수를 통해 "e" 키와 연결시켜주었습니다.
- 또한 Interation() 함수를 만들어 "e" 키를 누를시, nearObject가 Weapon일시, weaponIndex를 통해, bool 배열hasWeapons[]에 플레이어가 가지고 있는 무기로 넣어주었습니다.
- 무기 습득시 그 무기는 필드에서 없어집니다.
- 캐릭터의 손에 무기 쥐어주기
- 플레이어의 RightHand의 하위 오브젝트로 Cylinder을 만들어 Weapon Point로 지정하여 손의 위치에 쥐어줍니다.
- 그 후, 각 무기들을 에셋에서 Weapon Point 자식 오브젝트에 위치시켜 , 무기들을 보면서 손에 잘 쥐어 질 수 있도록 위치를 변경시켜 주면 됩니다.
- Weapons 오브젝트 넣어주기
/* Player Script , 기존 Script에서 해당하는 부분만을 표현했습니다. */
public class Player : MonoBehaviour
{
public GameObject[] weapons;
}
- GameObject들을 담을 weapons 변수를 만든 후, 무기들을 끌어당겨 넣어주었습니다.
- 무기 장착 스트립트 작성
Input Manager에 무기를 장착할 키를 sDown1,sDown2,sDown3 이름으로 작동키는 숫자 1, 2 ,3 으로 지정해주었습니다.
/* Player Script , 기존 Script에서 해당하는 부분만을 표현했습니다. */
public class Player : MonoBehaviour
{
GameObject equipWeapon;
int equipWeaponIndex = -1;
void GetInput()
{
sDown1 = Input.GetButtonDown("Swap1");
sDown2 = Input.GetButtonDown("Swap2");
sDown3 = Input.GetButtonDown("Swap3");
}
void Swap()
{
int weaponIndex = -1;
if (sDown1) weaponIndex = 0;
if (sDown2) weaponIndex = 1;
if (sDown3) weaponIndex = 2;
// 1, 2 ,3 버튼 누를때
if((sDown1 || sDown2 || sDown3) && !isJump && !isDodge) {
if(equipWeapon != null)
equipWeapon.SetActive(false);
equipWeaponIndex = weaponIndex;
equipWeapon = weapons[weaponIndex];
equipWeapon.SetActive(true);
}
}
}
- 다음 조건을 지정하여, 1, 2, 3을 누를시 가지고 있는 장착하고있는 무기가 Active 되도록 해주었습니다.
- 여기서 해머 = 1, 권총 = 1, 머신건 = 2 로 지정했습니다.
🧷 3. 무기 교체하기
- 무기 교체 애니메이션
- 플레이어 에셋에서 Swap 애니메이션을 doSwap 트리거를 통해 연결해주었습니다.
- 무기 교체 스크립트 연결 및 제한사항
/* Player Script , 기존 Script에서 해당하는 부분만을 표현했습니다. */
public class Player : MonoBehaviour
{
public GameObject[] weapons;
bool isSwap;
void Move()
{
// 스왑 시 못움직이게
if (isSwap)
moveVec = Vector3.zero;
}
void Swap()
{
// 인벤토리에 무기가 없다면 실행 안되고, 똑같은 무기는 꺼낼 수 없습니다.
if (sDown1 && (!hasWeapons[0] || equipWeaponIndex == 0))
return;
if (sDown2 && (!hasWeapons[1] || equipWeaponIndex == 1))
return;
if (sDown3 && (!hasWeapons[2] || equipWeaponIndex == 2))
return;
int weaponIndex = -1;
if (sDown1) weaponIndex = 0;
if (sDown2) weaponIndex = 1;
if (sDown3) weaponIndex = 2;
// 1, 2 ,3 버튼 누를때
if((sDown1 || sDown2 || sDown3) && !isJump && !isDodge) {
if(equipWeapon != null)
equipWeapon.SetActive(false);
equipWeaponIndex = weaponIndex;
equipWeapon = weapons[weaponIndex];
equipWeapon.SetActive(true);
anim.SetTrigger("doSwap");
// 스왑 중
isSwap = true;
Invoke("SwapOut", 0.4f);
}
}
void SwapOut()
{
isSwap = false;
}
}
anim.SetTrigger("doSwap")
- 또한 스왑 중일때, 다른 움직이지 못하고 계속 스왑동작을 실행시키지 않게 Invoke를 이용해 쿨타임을 주었습니다.
if (sDown1 && (!hasWeapons[0] || equipWeaponIndex == 0)) return; if (sDown2 && (!hasWeapons[1] || equipWeaponIndex == 1)) return; if (sDown3 && (!hasWeapons[2] || equipWeaponIndex == 2)) return;
- 그리고, 똑같은 무기를 스왑하거나, 가지고있지도 않는 무기를 꺼낼 수 없게 조건을 달아 완성시켜 주었습니다.
출처: 골든메탈님 유튜브
https://www.youtube.com/watch?v=APS9OY_p6wo&list=PLO-mt5Iu5TeYkrBzWKuTCl6IUm_bA6BKy&index=4
'🎮 Game Dev (게임개발) > PC (데스크탑, 노트북, 터치패널)' 카테고리의 다른 글
[3D 액션게임] 06. 근접무기 공격구현 (0) | 2022.04.01 |
---|---|
[3D 액션게임] 05.아이템 획득과 공전효과 (0) | 2022.03.31 |
[3D 액션게임] 03.아이템 만들기 (0) | 2022.03.29 |
[3D 액션게임] 02.점프와 회피 (0) | 2022.03.28 |
[3D 액션게임] 01.플레이어 이동 (0) | 2022.03.27 |
Contents
소중한 공감 감사합니다