드랍무기 입수를 위해
OnTriggerStay 와 OnTriggerExit 를 이용해서 오브젝트 인식부터 진행합니다.
플레이어 주변의 오브젝트 tag가 Weapon 일때, 지정한 변수에 오브젝트의 정보를 변수에 담아주고
오브젝트 범위를 벗어나면 지정한 변수에 담겨져있던 오브젝트의 정보를 null 로 비워줍니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float speed;
float hAxis;
float vAxis;
bool wDown;
bool jDown;
public bool isJump;
bool isDodge;
Vector3 moveVec;
Vector3 dodgeVec;
Rigidbody rigid;
Animator anim;
GameObject nearObject;
void Awake() {
rigid = GetComponent<Rigidbody>();
anim = GetComponentInChildren<Animator>();
}
// Update is called once per frame
void Update()
{
GetInput();
Move();
Turn();
Jump();
Dodge();
}
void GetInput() {
//키 입력 인식
hAxis = Input.GetAxisRaw("Horizontal"); //edit-project settings-input manager-Axes 의 Horizontal
vAxis = Input.GetAxisRaw("Vertical");
wDown = Input.GetButton("Walk");
jDown = Input.GetButtonDown("Jump");
}
void Move() {
//대각선 이동 노멀라이즈
moveVec = new Vector3(hAxis, 0, vAxis).normalized;
if (isDodge) {
moveVec = dodgeVec;
}
//벡터이동
//삼항연산자 사용해서 걷기wDown true면 걷기 속도-false면 Run속도
transform.position += moveVec * speed * (wDown ? 0.3f : 1f) * Time.deltaTime;
anim.SetBool("isRun", moveVec != Vector3.zero);
anim.SetBool("isWalk", wDown);
}
void Turn() {
//키 입력에 따라 해당 방향으로 바라보기(회전)
transform.LookAt(transform.position + moveVec);
}
void Jump() {
if (jDown && moveVec == Vector3.zero && !isJump && !isDodge) { //무한점프가 안되도록 !isJump 제약조건 걸기
rigid.AddForce(Vector3.up * 16, ForceMode.Impulse); //up 방향으로 Addforce
anim.SetBool("isJump", true);
anim.SetTrigger("doJump");
//isJump = true;
}
}
void Dodge() {
if (jDown && moveVec != Vector3.zero && !isJump && !isDodge) { //무한점프가 안되도록 !isJump 제약조건 걸기
dodgeVec = moveVec;
speed *= 2;
anim.SetTrigger("doDodge");
isDodge = true;
Invoke("DodgeOut", 0.4f); //0.4초 후 DodgeOut 함수를 호출. invoke 시간차 호출
}
}
void DodgeOut() {
speed *= 0.5f;
isDodge = false;
}
void OnCollisionEnter(Collision collision) {
if (collision.gameObject.tag == "Floor") {
anim.SetBool("isJump", false);
isJump = false;
}
}
private void OnCollisionStay(Collision collision) { // 캐릭터의 collision 값을 계속 디텍팅.
if(collision.gameObject.tag == "Floor") { //collision 이 닿은 오브젝트의 tag가 Floor 이면
anim.SetBool("isJump",false);
isJump = false; //점프가 가능하도록 isJump 를 false 로 반환.
}
}
private void OnCollisionExit(Collision collision) { //캐릭터와 닿은 collision과 떨어졌을때
if (collision.gameObject.tag == "Floor") { //collision 이 닿았던 오브젝트의 tag가 Floor 이면
//anim.SetBool("isJump", false);
isJump = true; //점프가 불가능하도록 isJump 를 true 로 반환.
}
}
void OnTriggerStay(Collider other) {
if (other.tag == "Weapon") //만약 지금 다 있는 오브젝트 tag가 Weapon이면
nearObject = other.gameObject; //nearObject 변수에 저장한다.
Debug.Log(nearObject.name);
}
void OnTriggerExit(Collider other) {
if (other.tag == "Weapon") //만약 지금 다 있는 오브젝트 tag가 Weapon이면
nearObject = null; //nearObject 변수를 비워준다.
}
}
유니티 오류가 발생했습니다.
NullReferenceException: Object reference not set to an instance of an object Player.OnTriggerStay
null 참조예외 : 오브젝트 레퍼런스가 OnTriggerStay 오브젝트 인스턴스에 세팅되지 않았다.
OnCollisionEnter 함수 전체를 주석처리 하니까 오류를 고쳤습니다.
OnCollisionEnter 함수를 사용하지 않기 위해서 OnCollisionStay 와 OnCollisionExit 함수를 사용했던건데 둘 사이에서 참조에 대한 충돌이 있었던 것같습니다.
블록 선택한 라인 주석달기 Ctrl+K+C!!!
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 wDown;
bool jDown;
bool iDown;//인터랙션(무기 입수)
bool isJump;
bool isDodge;
Vector3 moveVec;
Vector3 dodgeVec;
Rigidbody rigid;
Animator anim;
GameObject nearObject;
void Awake() {
rigid = GetComponent<Rigidbody>();
anim = GetComponentInChildren<Animator>();
}
// Update is called once per frame
void Update()
{
GetInput();
Move();
Turn();
Jump();
Dodge();
Interaction();
}
void GetInput() {
//키 입력 인식
hAxis = Input.GetAxisRaw("Horizontal"); //edit-project settings-input manager-Axes 의 Horizontal
vAxis = Input.GetAxisRaw("Vertical");
wDown = Input.GetButton("Walk");
jDown = Input.GetButtonDown("Jump");
iDown = Input.GetButtonDown("Interaction");
}
void Move() {
//대각선 이동 노멀라이즈
moveVec = new Vector3(hAxis, 0, vAxis).normalized;
if (isDodge) {
moveVec = dodgeVec;
}
//벡터이동
//삼항연산자 사용해서 걷기wDown true면 걷기 속도-false면 Run속도
transform.position += moveVec * speed * (wDown ? 0.3f : 1f) * Time.deltaTime;
anim.SetBool("isRun", moveVec != Vector3.zero);
anim.SetBool("isWalk", wDown);
}
void Turn() {
//키 입력에 따라 해당 방향으로 바라보기(회전)
transform.LookAt(transform.position + moveVec);
}
void Jump() {
if (jDown && moveVec == Vector3.zero && !isJump && !isDodge) { //무한점프가 안되도록 !isJump 제약조건 걸기
rigid.AddForce(Vector3.up * 16, ForceMode.Impulse); //up 방향으로 Addforce
anim.SetBool("isJump", true);
anim.SetTrigger("doJump");
//isJump = true;
}
}
void Dodge() {
if (jDown && moveVec != Vector3.zero && !isJump && !isDodge) { //무한점프가 안되도록 !isJump 제약조건 걸기
dodgeVec = moveVec;
speed *= 2;
anim.SetTrigger("doDodge");
isDodge = true;
Invoke("DodgeOut", 0.4f); //0.4초 후 DodgeOut 함수를 호출. invoke 시간차 호출
}
}
void DodgeOut() {
speed *= 0.5f;
isDodge = false;
}
void Interaction() {
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") {
// anim.SetBool("isJump", false);
// isJump = false;
// }
//}
void OnCollisionStay(Collision collision) { // 캐릭터의 collision 값을 계속 디텍팅.
if(collision.gameObject.tag == "Floor") { //collision 이 닿은 오브젝트의 tag가 Floor 이면
anim.SetBool("isJump",false);
isJump = false; //점프가 가능하도록 isJump 를 false 로 반환.
}
}
void OnCollisionExit(Collision collision) { //캐릭터와 닿은 collision과 떨어졌을때
if (collision.gameObject.tag == "Floor") { //collision 이 닿았던 오브젝트의 tag가 Floor 이면
//anim.SetBool("isJump", false);
isJump = true; //점프가 불가능하도록 isJump 를 true 로 반환.
}
}
void OnTriggerStay(Collider other) {
if (other.tag == "Weapon") //만약 지금 다 있는 오브젝트 tag가 Weapon이면
nearObject = other.gameObject; //nearObject 변수에 저장한다.
//Debug.Log(nearObject.name);
}
void OnTriggerExit(Collider other) {
if (other.tag == "Weapon") //만약 지금 다 있는 오브젝트 tag가 Weapon이면
nearObject = null; //nearObject 변수를 비워준다.
}
}
무기 입수까지 스크립트를 짰는데 Weapon tag 가 아닌 item 태그를 플레이어가 인식하게 되면 Debug.Log(nearObject.name) 라인에 에러가 발생하면서 유니티가 멈추게 됩니다.
그래서 해당 라인을 주석처리함으로써 에러를 해결했습니다.
무기 입수 Interaction 키는 E 키로 진행했습니다.
출처 - https://youtu.be/APS9OY_p6wo?list=PLO-mt5Iu5TeYI4dbYwWP8JqZMC9iuUIW2
'C' 카테고리의 다른 글
3D 쿼터뷰 액션게임 - 플레이어 회피기 (0) | 2023.06.02 |
---|---|
3D 쿼터뷰 액션게임 - 플레이어 점프 (0) | 2023.06.02 |
3D 쿼터뷰 액션게임 - 코드 정리 (0) | 2023.05.18 |
3D 쿼터뷰 액션게임 - 플레이어 이동 애니메이션, 카메라 이동 (0) | 2023.05.18 |
3D 쿼터뷰 액션게임 - 플레이어 이동 (0) | 2023.05.18 |