본문 바로가기

C

3D 쿼터뷰 액션게임 - 드랍무기 입수

 

 

드랍무기 입수를 위해

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