목차
Rigidbody
- Drag : Position 공기 저항
- Angular Drag : Rotation 공기 저항 --> 회전하지 않게 고정시키기 위해 'Infinity'라는 값을 넣을 수 있음
특정 축 제약
ex) 캐릭터가 Object에 부딪혔을 때, 안 넘어지게 하기
Transform vs Rigidbody
- Transform : 위치값을 순간이동 --> 값을 바꿔버리는 기능
- Rigidbody : 물리적으로 이동
충돌 레이어 설정
Physic Material
: 탄성과 마찰력
※ 만드는 법
- Dynamic Friction : 움직이는 대상에 대해서 마찰력
- Static Friction : 멈춰있는 대상에 대해서 마찰력
- Bounciness : 튕기는 탄성 (값의 범위 : 0 ~ 1) --> 충돌하는 Object에만 작용, 감지하는 Object는 어차피 뚫고 지나가기 때문
※ 적용법
※ 탱탱볼처럼 튀어오르게 만드려면, 땅에도 Physic Material을 넣어야 함 --> 작용 반작용의 개념이 있기 때문
Animation
: 애니메이션을 실행하는 Component --> 하지만 Animation Component는 사용하지 않으며, Animator에서 통합 관리하여 사용
>> Animation Window 생성 --> 단축키 : Ctrl + 6
※ Trigger가 작동하려면 Rigidbody가 필요하다.
Animation 생성
1. 최상위 Object를 선택하여 Animation을 만듦
2. 자식 Object를 선택하여 Add Property
첫 번째 방법,
두 번째 방법,
3. 녹화버튼 누르고 원하는 위치로 옮긴 뒤, Object 변화주기
4. 녹화 종료하기
>> 녹화를 종료하지 않고 다른 것을 건드렸다가는 Animation이 망가짐
※ Animation을 만들면 Animator가 Inspector에 자동으로 생성된다.
Animation 중 특정 프레임에서 Event 생성
1. 코드 작성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoorEvent : MonoBehaviour
{
void AnimationEvent()
{
Debug.Log("문이 열리는 중");
}
}
2. 적용할 Object에 Script 추가
3. Animation에서 Event 추가
4. Event를 선택하여 함수 추가
※ 원본 데이터의 Prefab을 끊고 나만의 Prefab을 만들기
이후 Hierarchy에 있는 Object를 Project에 드래그
Animator
: Animation 동작을 관리하는 Component
>> 켜는 법
- 주황색 State : 프로그램이 시작할 때 먼저 실행되는 기본 State
- Empty State : 애니메이션이 들어가는 빈 공간
- Entry : 상시 적용 (시작 지점)
- Any State : 원할 때 실행 가능 --> 필요할 때 실행할 Key 값 필요
- Exit : 종료 지점
>> 현재, 기본으로 Door Animation이 들어가 있기 때문에 Play하면 바로 문이 열려버림
--> Empty State를 기본 State로 변경
[예제] 문 애니메이션 만들기
: 문 리소스
https://assetstore.unity.com/packages/3d/props/interior/free-wood-door-pack-280509
Free Wood Door Pack | 3D 인테리어 | Unity Asset Store
Elevate your workflow with the Free Wood Door Pack asset from Biostart. Find this & other 인테리어 options on the Unity Asset Store.
assetstore.unity.com
1. 위의 'Animation 생성'를 참고, 애니메이션 녹화까지 마치기
2. 문은 한번만 열리므로 Loop 끄기
3. 문이 저절로 열리는 것을 막기 위해, Animator에서 Empty State를 만들어 기본 State로 지정
4. Any State에서 'Door Open' State로 화살표 잇기
: 화살표 만들기
5. Key값 만들어서 넣기
: Key값 만들기
>> Key 이름은 대소문자, 띄어쓰기 전부 구별하기 때문에 오타 주의
* Key 이름 : Open
: Key 넣기
6. Script 작성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoorEvent : MonoBehaviour
{
public Animator anim; // Animator 타입의 변수
public void OnTriggerEnter(Collider other)
{
anim.SetTrigger("Open"); // Animator에서 Trigger 파라미터 "Open" 실행
Debug.Log(other.name + "라는 대상의 감지가 시작됐다.");
}
public void OnTriggerExit(Collider other)
{
Debug.Log("감지되던 것이 종료됐다.");
}
}
7. Object에 Script 적용
8. 문과 캐릭터에 Collider 추가 및 위치 조정
:
※ 캐릭터만 감지하여 문 자동으로 열리게 하기
>> 이름으로 구별하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoorEvent : MonoBehaviour
{
public Animator anim; // Animator 타입의 변수
public void OnTriggerEnter(Collider other)
{
if (other.name == "AmongUs")
{
anim.SetTrigger("Open"); // Animator에서 Trigger 파라미터 "Open" 실행
Debug.Log(other.name + "라는 대상의 감지가 시작됐다.");
}
}
public void OnTriggerExit(Collider other)
{
Debug.Log("감지되던 것이 종료됐다.");
}
}
※ 이름으로 구분하기엔 변별력이 부족함 --> Tag 사용 (별명)
>> Tag로 구별하기
: Object에 Tag 넣기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoorEvent : MonoBehaviour
{
public Animator anim; // Animator 타입의 변수
public void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player")) // other.tag == "Player"
{
anim.SetTrigger("Open"); // Animator에서 Trigger 파라미터 "Open" 실행
Debug.Log(other.name + "라는 대상의 감지가 시작됐다.");
}
}
public void OnTriggerExit(Collider other)
{
Debug.Log("감지되던 것이 종료됐다.");
}
}
※ Door Close
: Open을 복붙한 뒤, Speed를 음수로 만들면 된다. --> 이후 Key값을 만들고 파라미터를 생성 후 연결, 화살표를 누르고 Conditions에서 Key값 적용
최종
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoorEvent : MonoBehaviour
{
public Animator anim; // Animator 타입의 변수
public void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player")) // other.tag == "Player"
{
anim.SetTrigger("Open"); // Animator에서 Trigger 파라미터 "Open" 실행
}
}
public void OnTriggerExit(Collider other)
{
if (other.CompareTag("Player"))
{
anim.SetTrigger("Close");
}
}
}
[예제] 캐릭터 점프
점프 기능
1. 조건 : Space를 눌렀을 때
2. 점프하기 위한 힘이 필요 --> 변수
3. Rigidbody에 있는 AddForce 함수 사용
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterMovement : MonoBehaviour
{
private float h = 0f;
private float v = 0f;
public float moveSpeed = 5f;
public float jumpPower = 5f;
void Update()
{
Move();
Jump();
}
private void Jump()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// Rigidbody Component에 접근해서 AddForce 기능을 사용
// addForce로 힘을 가함 (위쪽으로 jumpPower만큼)
// ForceMode : 지속적인 힘 vs 순간적인 힘 / 질량 적용 유무
GetComponent<Rigidbody>().AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
private void Move()
{
h = Input.GetAxis("Horizontal"); // 오른쪽, 왼쪽 이동
v = Input.GetAxis("Vertical"); // 앞, 뒤 이동
Vector3 dir = new Vector3(h, 0f, v); // 입력한 값으로 Vector3 선언 및 할당
//Vector3 dir = new Vector3(h, 0f, v).normalized;
transform.position += moveSpeed * Time.deltaTime * dir;
if (h != 0 || v != 0) // h나 v나 아무 키나 하나는 누른 상태
{
// 캐릭터가 이동하려는 방향을 바라보게 하는 코드
Vector3 targetPos = transform.position + dir; // 목표 위치
transform.LookAt(targetPos); // 목표 위치를 바라보는 코드
}
}
}
※ ForceMode
- Force : 지속적인 힘 + 질량 적용
- Impulse : 순간적인 힘 + 질량 적용 --> 주로 사용
- Acceleration : 지속적인 힘 + 질량 무시
- VelocityChange : 순간적인 힘 + 질량 무시
2단 점프 방지
1. 'CharacterMovement'에 'isGround' 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterMovement : MonoBehaviour
{
private float h = 0f;
private float v = 0f;
public float moveSpeed = 5f;
public float jumpPower = 5f;
public bool isGround = false;
void Update()
{
Move();
Jump();
}
private void Jump()
{
if (Input.GetKeyDown(KeyCode.Space) && isGround == true)
{
// Rigidbody Component에 접근해서 AddForce 기능을 사용
// addForce로 힘을 가함 (위쪽으로 jumpPower만큼)
// ForceMode : 지속적인 힘 vs 순간적인 힘 / 질량 적용 유무
GetComponent<Rigidbody>().AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
private void Move()
{
h = Input.GetAxis("Horizontal"); // 오른쪽, 왼쪽 이동
v = Input.GetAxis("Vertical"); // 앞, 뒤 이동
Vector3 dir = new Vector3(h, 0f, v); // 입력한 값으로 Vector3 선언 및 할당
//Vector3 dir = new Vector3(h, 0f, v).normalized;
transform.position += moveSpeed * Time.deltaTime * dir;
if (h != 0 || v != 0) // h나 v나 아무 키나 하나는 누른 상태
{
// 캐릭터가 이동하려는 방향을 바라보게 하는 코드
Vector3 targetPos = transform.position + dir; // 목표 위치
transform.LookAt(targetPos); // 목표 위치를 바라보는 코드
}
}
}
2. 지면에 Script 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GroundEvent : MonoBehaviour
{
public void OnCollisionEnter(Collision collision)
{
if (collision.collider.CompareTag("Player"))
{
GameObject characterObj = collision.gameObject;
// 캐릭터 오브젝트의 CharacterMovement 스크립트(컴포넌트)에 접근해서 변경
characterObj.GetComponent<CharacterMovement>().isGround = true;
}
}
public void OnCollisionExit(Collision collision)
{
if (collision.collider.CompareTag("Player"))
{
GameObject characterObj = collision.gameObject;
characterObj.GetComponent<CharacterMovement>().isGround = false;
}
}
}
'Development > C#' 카테고리의 다른 글
[멋쟁이사자처럼 부트캠프 TIL 회고] Unity 게임 개발 3기 9일차 (1) | 2024.11.30 |
---|---|
[멋쟁이사자처럼 부트캠프 TIL 회고] Unity 게임 개발 3기 8일차 (0) | 2024.11.28 |
[멋쟁이사자처럼 부트캠프 TIL 회고] Unity 게임 개발 3기 6일차 (0) | 2024.11.26 |
[멋쟁이사자처럼 부트캠프 TIL 회고] Unity 게임 개발 3기 5일차 (0) | 2024.11.25 |
[멋쟁이사자처럼 부트캠프 TIL 회고] Unity 게임 개발 3기 4일차 (0) | 2024.11.22 |