몬스터가 플레이어와 일정 거리 이내로 좁혀지면 공격 애니메이션을 수행한다. 이때 플레이어의 생명력이 줄어드는 코드를 짜보자.

방법은 collider를 통해 처리하는 방법과 주기적으로 데미지를 주는 방법이 있다. 몬스터는 공격 상태가 되면 양손으로 타격하는 애니메이션을 실행하므로 전자의 방식으로 구현해보자.

하이라키뷰에서 L_wrist, R_wrist를 선택한후 다음 속성을 변경하면 동시에 적용된다.

물리적 충격을 주가위해 몬스터의 양속에 Collider와  Rigidbody컴포넌트를 추가한다. 

몬스터본체 Capsule Collider와의 간섭을 없애기 위해 Collider의 Is Trigger check, 움직임은 애니메이션에서 컨트롤 하므로 물리엔진인 Rigidbody의 Is Kinematic check한다.

Tag에서 PUNCH를 만들고 다시 L_wrist, R_wrist를 선택한후 TAG를 PUNCH로 바꿔준다.

주인공 Player에도 Capsule Collider를 추가해 다음과 같이 Center (0,1,0), Height:2을 설정한다. 

Rigidbody를 추가하고 FreezeRotation x,z를 check한다. 이러면 넘어지지 않는다

보통 FPS나 TPS게임을 개발할때 주인공은 character Controller컴포넌트를 사용한다. collider+rigidbody에 물리엔진을 disable해서 떨림현상이나 미림현상을 방지할 수 있다

 

OnTriggerEnter 콜백 함수

몬스터 양손에 Sphere Collider에서 IsTrigger를 체크했기때문에 OnTrigger계열의 콜백함수가 호출된다.

 

PlayerCtrl에 OnTriggerEnter()를 추가한다.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerCtrl : MonoBehaviour {
    // Start is called before the first frame update
    

    Transform tr;
    private Animation anim;

    private float moveSpeed = 10f; //이동속도
    private float turnSpeed = 0f;  //회전속도

    private readonly float initHP = 100.0f;  //초기 생명값
    public float curHP; //현재생명값

    IEnumerator  Start() {  //start()함수는 코루틴으로 실행할 수 있다.
        curHP = initHP;
        tr = GetComponent<Transform>();
        anim = GetComponent<Animation>();  //추가된 코드
        anim.Play("Idle");
        turnSpeed = 0.0f;  //프로그램 기동시 가비지 마우스값을 막기위해
        yield return new WaitForSeconds(0.3f);  //0.3초 기다린후
        turnSpeed = 100f;  //변수값을 설정
    }

    // Update is called once per frame
    void Update() {
        float h = Input.GetAxis("Horizontal");  //AD 입력 좌우
        float v = Input.GetAxis("Vertical");  //WS 입력 전후
        if (Mathf.Abs(h) > float.Epsilon || Mathf.Abs(v) > float.Epsilon) {  //움직임이 없다면 불필요한 동작을 안한다.
            Vector3 dir = Vector3.right * h + Vector3.forward * v;
            tr.Translate(dir.normalized * moveSpeed * Time.deltaTime);
            PlayerAnim(h, v);
        }
        float r = Input.GetAxis("Mouse X");  //마우스 x축 입력 
        tr.Rotate(Vector3.up * turnSpeed * Time.deltaTime * r);
    }
    void PlayerAnim(float h, float v) {
        GetComponent<NavCtrl>().SetNavStop();
        if (v >= 0.1f) {  //앞으로 달림
            anim.CrossFade("RunF",0.25f);
        } else if(v <= -0.1f) { //뒤로 움직임
            anim.CrossFade("RunB", 0.25f);
        } else if(h >= 0.1f) { //오른쪽으로 움직임
            anim.CrossFade("RunR", 0.25f);
        } else if (h <= -0.1f) { //왼쪽으로 움직임
            anim.CrossFade("RunL", 0.25f);
        } else { //제자리대기
            anim.CrossFade("Idle", 0.25f);
        }
    }
    void OnTriggerEnter(Collider coll) {
        if(curHP >= 0.0f && coll.CompareTag("PUNCH")) {
            curHP -= 10.0f;
            Debug.Log($"Player hp = { curHP / initHP }");
            if (curHP <= 0.0f) {
                PlayerDie();
            }
        }
    }
    void PlayerDie() {
        Debug.Log("Player Die !");
    }
}

+ Recent posts