Chapter 12-1. 기타 : 트랩 만들기
카테고리: Unity Lesson 3
태그: Unity Game Engine
인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click
🚀 단순한 트랩 만들기
트랩 오브젝트
이 3 가지 오브젝트를 조합해서 트랩을 만든다. Rigidbody 를 붙여줄 때 중력과 물리를 꺼준다. 고기에 Trigger 충돌이 발동하면 나무와 나뭇가지의 중력과 물리를 활성화하여 쓰러지게 할 것이다.
- 네모 나무, 나뭇가지
- Box Collider
- Rigidbody (Use Gravity 해제, Is Kinematic 체크)
- 전체
SimpleTrap
부모 오브젝트에게 Box Collider 붙이고 Is Trigger체크. 고기 쪽에 붙인다.- 레이어는 “Building”
- AudioSource 를 붙인다.
- 📜SimpleTrap 이 붙을 것
📜SimpleTrap
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SimpleTrap : MonoBehaviour
{
private Rigidbody[] rigid; // Twig, Board 의 Rigidbody 가지고 올 것
[SerializeField] private GameObject go_Meat; // 트랩에 걸리면 고기가 사라지게
[SerializeField] private int damage; // 플레이어에게 입힐 데미지
private bool isActivated = false; // 트랩이 발동되면 true
private AudioSource theAudio;
[SerializeField] private AudioClip sound_Activate; // 트랩 발동 사운드
void Start()
{
rigid = GetComponentsInChildren<Rigidbody>();
theAudio = GetComponent<AudioSource>();
}
private void OnTriggerEnter(Collider other)
{
if (!isActivated)
{
if (other.transform.tag != "Untagged")
{
isActivated = true;
theAudio.clip = sound_Activate;
theAudio.Play();
Destroy(go_Meat);
for (int i = 0; i < rigid.Length; i++)
{
rigid[i].useGravity = true;
rigid[i].isKinematic = false;
}
if (other.transform.name == "Player")
other.transform.GetComponent<StatusController>().DecreaseHP(damage);
}
}
}
}
- Terrain 의 태그는 “Untagged”이다. 이 태그가 아닌 플레이어, 동물AI 등등 모든 것이 닿으면
- 트랩 사운드 재생
- 고기 없애기
- Twig와 Board의 중력, 물리 활성화하여 넘어지게 하기
- 플레이어의 데미지 입히기
플레이어가 고기에 닿으면 트랩의 중력과 물리가 발동하여 무너지게 되고 플레이어의 체력이 깎이게 된다.
🚀 좀 더 심화적인 트랩 만들기
✈ 트랩 오브젝트
가장 밑에있는 나뭇 가지에 플레이어가 닿으면 연필 같이 생긴 나무가 떨어지고 이 나무에 맞으면 데미지를 입게 할 것이다! 데미지는 지속 데미지는 아니고 딱 한번만 입는다.
- 부모
DeadTrap
- 태그 “Trap”, 레이어 “Building”
- 📜DeapTrap 불일 것
- Box Collider 2 개 (📜DeamTrap 에서 가져올 것)
- 하나는 가운데
- 메인 카메라의 Raycast 충돌을 받아 액션 텍스트 띄울 것
- 다른 하나는 얇은 나뭇 가지 있는 바닥
- 이 곳에 겹치면 트랩이 발동하게 할것
IsTrigger
체크
- 메인 카메라의 Raycast 충돌을 받아 액션 텍스트 띄울 것
- 이 곳에 겹치면 트랩이 발동하게 할것
- 하나는 가운데
- Animator
- Audio Source
- 플레이어가 부딪치면 관통 안되고 밀려날 수 있도록 모든 자식 오브젝트들에게 Box Collider 붙여주기
- 단, 플레이어가 맞아서 데미지를 입힐 저 연필 모양의 나무(
WoodWall
)는IsTrigger
가 체크된 Box Collider 를 한번 기존 Box Collider 바깥에 입혀지도록 하나 더 추가해준다. - 📜TrapDamage 붙일 것
- OnTriggerEnter 이벤트시 플레이어에게 데미지 입히는 처리
- Rigidbody
- 플레이어가 맞으면 튕겨나가도록 질량을 1000으로 무겁게
- 중력 끄고 물리 처리 끄고
- 단, 플레이어가 맞아서 데미지를 입힐 저 연필 모양의 나무(
✈ 트랩 애니메이션
트랩 애니메이션 클립
트랩이 활성화 될 때
- “DeadTrap_Activate” 애니메이션 클립
- 트랩이 활성화되면 다음과 같은 애니메이션이 재생될 수 있도록 녹화하여 키들을 만들었다.
트랩이 비활성화 상태일 떄
- “DeadTrap_Deactivate” 애니메이션 클립
- 그냥 정지해있을 때.
트랩 애니메이션 컨트롤러
DeadTrap
의 Animator 컴포넌트의 컨트롤러에 할당해준다.- Trigger 파라미터를 위와 같이 추가해준다.
- 각 Trigger가 발동할 때 해당 Transition이 일어나도록 한다.
- Has Exit Time 은 체크 해제. 그냥 애니메이션 재생이 끝나면 즉각 끝내도록!
✈ 트랩 작동시키기
📜DeadTrap
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DeadTrap : MonoBehaviour
{
private Animator anim;
private AudioSource theAudio;
private bool isActivated = false;
[SerializeField] private AudioClip sound_Activate;
[SerializeField] private TrapDamage theTrapDamage;
void Start()
{
anim = GetComponent<Animator>();
theAudio = GetComponent<AudioSource>();
}
private void OnTriggerEnter(Collider other)
{
if (!isActivated)
{
if (other.transform.tag != "Untagged" && other.transform.tag != "Trap")
{
StartCoroutine(theTrapDamage.ActivatedTrapCoroutine());
isActivated = true;
anim.SetTrigger("Activate");
theAudio.clip = sound_Activate;
theAudio.Play();
}
}
}
}
DeadTrap
에 붙는다. 아랫 나뭇 가지를 밟으면 트랩을 작동시킨다.
- OnTriggerEnter
DeadTrap
의 Box Collider 중 하나인 얇은 나뭇가지 부분! 그 부분은Is Trigger
가 체크되어 있으며, 그 부분을 밟으면 트랩이 작동되게 할 것이다.- 밟은 대상이 지형이 아니고(“Untagged”) 자기 자신이 아니라면(“Trap”)
- 밑에 후술할 📜TrapDamage 의 ActivatedTrapCoroutine 실행하여 데미지 입히는 처리
isActivated
true로 해야 데미지를 입을 수 있다.
- 트랩 애니메이션 재생
- 트랩 활성 효과음 재생
- 밑에 후술할 📜TrapDamage 의 ActivatedTrapCoroutine 실행하여 데미지 입히는 처리
- 밟은 대상이 지형이 아니고(“Untagged”) 자기 자신이 아니라면(“Trap”)
📜TrapDamage 가 붙어있는 WoodWall
활당.
📜TrapDamage
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TrapDamage : MonoBehaviour
{
[SerializeField] private int damage;
[SerializeField] private float finishTime;
private bool isHurt = false; // false 일 때만 데미지 입게
private bool isActivated = false;
public IEnumerator ActivatedTrapCoroutine()
{
isActivated = true;
yield return new WaitForSeconds(finishTime);
isActivated = false;
isHurt = false;
}
private void OnTriggerEnter(Collider other)
{
if (isActivated)
{
if (!isHurt)
{
isHurt = true;
if (other.transform.name == "Player")
other.transform.GetComponent<StatusController>().DecreaseHP(damage);
}
}
}
}
WoodWall
에 붙는다. 움직이는 이 오브젝트와 충돌이 일어나야만 데미지를 입게 할 것이다.
- 트랩이 활성화되면 📜DeadTrap에서 ActivatedTrapCoroutine을 실행하여
isActivated
가 True가 된다. 그리고finishTime
이 시간동안 대기를 한 후 다시isActivated
을 False로 만든다.- 따라서 이렇게 트랩이 활성화 된 후
finishTime
이 시간동안에만WoodWall
와 충돌 OnTriggerEnter 이 일어날 때 데미지를 입을 수 있게 된다. - 그리고
isHurt
를 통해finishTime
시간 당 1 회만 입을 수 있다. - 코루틴 함수는 병렬적으로 실행이 되기 떄문에 ActivatedTrapCoroutine 실행 중에, 즉 대기 시간을 기다리는 중에 OnTriggerEnter 가 실행 될 수 있다.
- 따라서 이렇게 트랩이 활성화 된 후
- 플레이어의 데미지 깎기
✈ 트랩의 작동이 끝나고나면 재설치
📜DeadTrap
public bool GetIsActivated()
{
return isActivated;
}
public void ReInstall()
{
isActivated = false;
anim.SetTrigger("Deactivate");
}
재설치 할 수 있도록 함수 만듬. “Deactivate” 애니메이션 재생. 단, 재설치는 isActivated
가 True 인 상태에서만 이루어져야 한다.
📜ActionController
private void TryAction()
{
if(Input.GetKeyDown(KeyCode.E))
{
CheckAction();
CanPickUp();
CanMeat();
CanDropFire();
CanComputerPowerOn();
CanArchemyTableOpen();
CanReInstallTrap();
}
}
private void CheckAction()
{
if (Physics.Raycast(transform.position, transform.forward, out hitInfo, range, layerMask))
{
if (hitInfo.transform.tag == "Item")
ItemInfoAppear();
else if (hitInfo.transform.tag == "Weak_Animal")
MeatInfoAppear();
else if (hitInfo.transform.tag == "Fire")
FireInfoAppear();
else if (hitInfo.transform.tag == "Computer")
ComputerInfoAppear();
else if (hitInfo.transform.tag == "ArchemyTable")
ArchemyInfoAppear();
else if (hitInfo.transform.tag == "Trap")
TrapInfoAppear();
else
InfoDisappear();
}
else
InfoDisappear();
}
private void TrapInfoAppear()
{
if (hitInfo.transform.GetComponent<DeadTrap>().GetIsActivated())
{
Reset();
lookActivatedTrap = true;
actionText.gameObject.SetActive(true);
actionText.text = "함정 재설치 " + "<color=yellow>" + "(E)" + "</color>";
}
}
private void InfoDisappear()
{
pickupActivated = false;
dissolveActivated = false;
firedLookActivated = false;
lookComputer = false;
lookArchemyTable = false;
lookActivatedTrap = false;
actionText.gameObject.SetActive(false);
}
private void CanReInstallTrap()
{
if (lookActivatedTrap)
{
if (hitInfo.transform != null)
{
hitInfo.transform.GetComponent<DeadTrap>().ReInstall();
InfoDisappear();
}
}
}
트랩 활성화 후 DeadTrap
(레이어 “Building”이며 layerMask
에는 이 레이어가 등록 되어 있음)의 Box Collider 를 쳐다보면 액션 텍스트 활성화, 그리고나서 E
누르면 재설치 하게끔.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기