728x90
1. 엣셋다운
2. 라이팅 세팅
3. 애니메이션
애니스테이트 -> Die 연결
4. 무기장착
5.
Rigidbody 추가 -> Capsule Collider 추가
6. 바닥레이어
7. 캐릭터 이동
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private Vector3 movement;
private float h;
private float v;
public float speed;
public Rigidbody rigidbody3d;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
}
private void FixedUpdate()
{
//이동 방향 벡터 생성
movement = new Vector3(h, 0f, v).normalized;
movement = movement * speed * Time.fixedDeltaTime;
//Rigidbody.MovePosition을 이용해 이동 처리를 수행
rigidbody3d.MovePosition(transform.position + movement);
}
}
캐릭터 회전하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private Vector3 movement;
private float h;
private float v;
public float speed;
public Rigidbody rigidbody3d;
private int floorMask;
// Start is called before the first frame update
void Start()
{
LayerMask.GetMask("Floor");
}
// Update is called once per frame
void Update()
{
h = Input.GetAxisRaw("Horizontal");
v = Input.GetAxisRaw("Vertical");
}
private void FixedUpdate()
{
Move(); //이동처리
Turn(); //회전처리
}
void Move()
{
//이동 방향 벡터 생성
movement = new Vector3(h, 0f, v).normalized;
movement = movement * speed * Time.fixedDeltaTime;
//Rigidbody.MovePosition을 이용해 이동 처리를 수행
rigidbody3d.MovePosition(transform.position + movement);
}
void Turn()
{
Ray cameraRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit FloorHit;
//레이와 바닥과의 충돌 여부를 확인하고, 충돌될 경우 정보를 가져옴 -> floorHit
if (Physics.Raycast(cameraRay, out FloorHit, 100f, floorMask))
{
//캐릭터의 회전 방향 벡터
Vector3 direction = FloorHit.point - transform.position;
direction.y = 0f;
//회전 방향을 향한 쿼터니언을 구함
Quaternion dirRotation = Quaternion.LookRotation(direction.normalized);
//캐릭터를 회전함
rigidbody3d.MoveRotation(dirRotation);
}
}
}
애니메이션 적용
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private Vector3 movement;
private float h;
private float v;
public float speed;
public Rigidbody rigidbody3d;
private int floorMask;
public Animator animator;
// Start is called before the first frame update
void Start()
{
floorMask = LayerMask.GetMask("Floor");
}
// Update is called once per frame
void Update()
{
h = Input.GetAxisRaw("Horizontal");
v = Input.GetAxisRaw("Vertical");
//이동 여부에 따른 애니메이션을 적용
bool walking = (h != 0f || v != 0f);
animator.SetBool("IsWalking", walking);
}
private void FixedUpdate()
{
Move(); //이동처리
Turn(); //회전처리
}
void Move()
{
//이동 방향 벡터 생성
movement = new Vector3(h, 0f, v).normalized;
movement = movement * speed * Time.fixedDeltaTime;
//Rigidbody.MovePosition을 이용해 이동 처리를 수행
rigidbody3d.MovePosition(transform.position + movement);
}
void Turn()
{
Ray cameraRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit FloorHit;
//레이와 바닥과의 충돌 여부를 확인하고, 충돌될 경우 정보를 가져옴 -> floorHit
if (Physics.Raycast(cameraRay, out FloorHit, 100f, floorMask))
{
//캐릭터의 회전 방향 벡터
Vector3 direction = FloorHit.point - transform.position;
direction.y = 0f;
//회전 방향을 향한 쿼터니언을 구함
Quaternion dirRotation = Quaternion.LookRotation(direction.normalized);
//캐릭터를 회전함
rigidbody3d.MoveRotation(dirRotation);
}
}
}
추적카메라
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
// 추적 타겟
public Transform target;
// 부드러움 수치 (보간수치)
public float smoothing = 5f;
// 추적 간격(거리) 오프셋
Vector3 offset;
// Start is called before the first frame update
void Start()
{
offset = transform.position - target.position;
}
// LateUpdate(): 모든 Update가 호출된 다음에 실행되는 이벤트 메소드
// * 캐릭터의 이동처리가 완료된(Update의 처리 후가 보장된) 후 실행되는 이벤트 Update메소드
void LateUpdate()
{
//갱신된 추적 대상(캐릭터)의 위치에 오프셋값을 더함
Vector3 targetCamPos = target.position + offset;
//카메라의 위치를 변경함
transform.position = Vector3.Lerp(transform.position, targetCamPos, smoothing + Time.deltaTime);
}
}
무기 발포하기
무기에 라이팅 추가
Line Renderer 추가 ->Edit Key
발포 라이트
돌에 충돌 추가
발포 라이트 효과
C# Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerShot : MonoBehaviour
{
//발포 시간 관련 속성들
public float fireDelayTime; // 발포 주기
public float fireRange; //발포 길이
private float time; //발포 주기 계산 시간
// 발포 피격 관련 속성들
private Ray shootRay = new Ray(); // 레이생성
private RaycastHit shootHit; //레이 충돌 정보
private int ShootableMask; // 발포 충돌 레이어 마스크(충돌 레이어 정수값)
public int damagePerShot; //피격 데미지
// 발포 효과 관련 속성들
public ParticleSystem gunParticleSys; //발포 이펙트 파티클 컴포넌트 참조
public LineRenderer fireLine; //발포 라인 효과 (라인랜더러)
public Light faceLight; // 발포 스팟 라이트 효과
public Light gunLight; // 발포 포인트 라이트 효과
public float effectDisplayTime; //발포 효과 재생 시간
// Start is called before the first frame update
void Start()
{
// 충돌 레이어 이름으로 충돌 마스크 값을 구함
ShootableMask = LayerMask.GetMask("Shootable");
}
// Update is called once per frame
void Update()
{
//시간을 계산함
time += Time.deltaTime;
//마우스 왼쪽 버튼을 누르고
if (Input.GetButton("Fire1") && time >= fireDelayTime)
{
Shot(); //발포 처리
}
if (time >= fireDelayTime * effectDisplayTime)
{
gunLight.enabled = false;
faceLight.enabled = false;
}
}
void Shot()
{
time = 0f;
gunLight.enabled = true;
faceLight.enabled = true;
Debug.Log("발포!!!");
}
}
발포 레이저
firePos 만들기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerShot : MonoBehaviour
{
//발포 시간 관련 속성들
public float fireDelayTime; // 발포 주기
public float fireRange; //발포 길이
private float time; //발포 주기 계산 시간
// 발포 피격 관련 속성들
private Ray shootRay = new Ray(); // 레이생성
private RaycastHit shootHit; //레이 충돌 정보
private int shootableMask; // 발포 충돌 레이어 마스크(충돌 레이어 정수값)
public int damagePerShot; //피격 데미지
// 발포 효과 관련 속성들
public ParticleSystem gunParticleSys; //발포 이펙트 파티클 컴포넌트 참조
public LineRenderer fireLine; //발포 라인 효과 (라인랜더러)
public Light faceLight; // 발포 스팟 라이트 효과
public Light gunLight; // 발포 포인트 라이트 효과
public float effectDisplayTime; //발포 효과 재생 시간
public Transform firePos; //발포위치
// Start is called before the first frame update
void Start()
{
// 충돌 레이어 이름으로 충돌 마스크 값을 구함
shootableMask = LayerMask.GetMask("Shootable");
}
// Update is called once per frame
void Update()
{
//시간을 계산함
time += Time.deltaTime;
//마우스 왼쪽 버튼을 누르고
if (Input.GetButton("Fire1") && time >= fireDelayTime)
{
Shot(); //발포 처리
}
if (time >= fireDelayTime * effectDisplayTime)
{
gunLight.enabled = false;
faceLight.enabled = false;
//라인 비활성화
fireLine.enabled = false;
}
}
void Shot()
{
time = 0f;
//이펙트 라이트 on
gunLight.enabled = true;
faceLight.enabled = true;
//발포 파티클 재생
gunParticleSys.Stop();
gunParticleSys.Play();
//라인렌더러 활성화
fireLine.enabled = true;
//라인시작점 인덱스 : 0, 두번쨰 연결점 인덱스 : 1, ......2,3,4
//라인랜더러의 시작점을 총구 위치로 설정
fireLine.SetPosition(0, firePos.position);
//발포 레이 시작 위치 설정
shootRay.origin = firePos.position;
//발포 레이의 방향 설정
shootRay.direction = firePos.forward;
if (Physics.Raycast(shootRay, out shootHit, fireRange, shootableMask))
{
//레이가 충돌한 지점까지 라인의 끝점을 설정함
fireLine.SetPosition(1, shootHit.point);
}
else
{
//레이의 충돌이 없으면 레이 방향으로 지정된 발포 길이만큼으로 라인의 끝점을 설정함
fireLine.SetPosition(1, shootRay.origin + shootRay.direction * fireRange);
}
Debug.Log("발포!!!");
}
}
몬스터 만들기
Plane, Environment -> Navigation Static -> Bake
유니티 짱 쉐이더로 몬스터 바꾸기
유니티짱 쉐이터 복사 -> 붙여넣기
몬스터 애니메이터
몬스터에 애니메이터 연결
파라미터 추가
플레이어 추적하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//AI(Navigation) 사용
using UnityEngine.AI;
//적군 이동 처리
public class EnemyMovement : MonoBehaviour
{
//공격 대상 (추적대상)
public Transform attackTarget;
//네브메쉬 에이전트 참조
public NavMeshAgent navMeshAgent;
//몬스터 애니메이터
public Animator animator;
// Start is called before the first frame update
void Start()
{
//플레이어 게임오브젝트를 찾음 (태그로)
GameObject player = GameObject.FindGameObjectWithTag("Player");
//플레이어를 추적대상으로 설정
attackTarget = player.transform;
}
// Update is called once per frame
void Update()
{
//플레이어를 추적함
navMeshAgent.SetDestination(attackTarget.position);
}
}
몬스터에 충돌 콜라이더 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyHealth : MonoBehaviour
{
//시작 체력
public int startHealth;
//현재체력
public int currentHealth;
//사망 상태
public bool isDie;
//애니메이터 컴포넌트 참조
public Animator animator;
// Start is called before the first frame update
void Start()
{
currentHealth = startHealth;
}
//피격 처리 (피격 데미지)
public void TakeDamage(int damage)
{
currentHealth -= damage;
if (currentHealth <= 0 && ! isDie)
{
}
}
//몬스터 사망 처리
public void Death()
{
isDie = true;
animator.SetTrigger("Die");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerShot : MonoBehaviour
{
//발포 시간 관련 속성들
public float fireDelayTime; // 발포 주기
public float fireRange; //발포 길이
private float time; //발포 주기 계산 시간
// 발포 피격 관련 속성들
private Ray shootRay = new Ray(); // 레이생성
private RaycastHit shootHit; //레이 충돌 정보
private int shootableMask; // 발포 충돌 레이어 마스크(충돌 레이어 정수값)
public int damagePerShot; //피격 데미지
// 발포 효과 관련 속성들
public ParticleSystem gunParticleSys; //발포 이펙트 파티클 컴포넌트 참조
public LineRenderer fireLine; //발포 라인 효과 (라인랜더러)
public Light faceLight; // 발포 스팟 라이트 효과
public Light gunLight; // 발포 포인트 라이트 효과
public float effectDisplayTime; //발포 효과 재생 시간
public Transform firePos; //발포위치
// Start is called before the first frame update
void Start()
{
// 충돌 레이어 이름으로 충돌 마스크 값을 구함
shootableMask = LayerMask.GetMask("Shootable");
}
// Update is called once per frame
void Update()
{
//시간을 계산함
time += Time.deltaTime;
//마우스 왼쪽 버튼을 누르고
if (Input.GetButton("Fire1") && time >= fireDelayTime)
{
Shot(); //발포 처리
}
if (time >= fireDelayTime * effectDisplayTime)
{
gunLight.enabled = false;
faceLight.enabled = false;
//라인 비활성화
fireLine.enabled = false;
}
}
void Shot()
{
time = 0f;
//이펙트 라이트 on
gunLight.enabled = true;
faceLight.enabled = true;
//발포 파티클 재생
gunParticleSys.Stop();
gunParticleSys.Play();
//라인렌더러 활성화
fireLine.enabled = true;
//라인시작점 인덱스 : 0, 두번쨰 연결점 인덱스 : 1, ......2,3,4
//라인랜더러의 시작점을 총구 위치로 설정
fireLine.SetPosition(0, firePos.position);
//발포 레이 시작 위치 설정
shootRay.origin = firePos.position;
//발포 레이의 방향 설정
shootRay.direction = firePos.forward;
//
if (Physics.Raycast(shootRay, out shootHit, fireRange, shootableMask))
{
//레이가 충돌한 지점까지 라인의 끝점을 설정함
fireLine.SetPosition(1, shootHit.point);
//관통된 게임 오브젝트에 EnemyHealth 컴포넌트 존재하는지 확인함
EnemyHealth health = shootHit.collider.GetComponent<EnemyHealth>();
if (health != null)
{
health.TakeDamage(damagePerShot);
}
}
else
{
//레이의 충돌이 없으면 레이 방향으로 지정된 발포 길이만큼으로 라인의 끝점을 설정함
fireLine.SetPosition(1, shootRay.origin + shootRay.direction * fireRange);
}
Debug.Log("발포!!!");
}
}
몬스터 사망
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class EnemyHealth : MonoBehaviour
{
//시작 체력
public int startHealth;
//현재체력
public int currentHealth;
//사망 상태
public bool isDie;
//애니메이터 컴포넌트 참조
public Animator animator;
public ParticleSystem hitParticle;
// Start is called before the first frame update
void Start()
{
currentHealth = startHealth;
}
//피격 처리 (피격 데미지)
public void TakeDamage(int damage, Vector3 hitPos)
{
currentHealth -= damage;
if (currentHealth <= 0 && !isDie)
{
Death(); //사망 처리
}
if (isDie) return;
hitParticle.transform.position = hitPos;
hitParticle.Play();
}
//몬스터 사망 처리
public void Death()
{
isDie = true;
animator.SetTrigger("Die");
GetComponent<NavMeshAgent>().isStopped = true;
Destroy(gameObject, 2f);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerShot : MonoBehaviour
{
//발포 시간 관련 속성들
public float fireDelayTime; // 발포 주기
public float fireRange; //발포 길이
private float time; //발포 주기 계산 시간
// 발포 피격 관련 속성들
private Ray shootRay = new Ray(); // 레이생성
private RaycastHit shootHit; //레이 충돌 정보
private int shootableMask; // 발포 충돌 레이어 마스크(충돌 레이어 정수값)
public int damagePerShot; //피격 데미지
// 발포 효과 관련 속성들
public ParticleSystem gunParticleSys; //발포 이펙트 파티클 컴포넌트 참조
public LineRenderer fireLine; //발포 라인 효과 (라인랜더러)
public Light faceLight; // 발포 스팟 라이트 효과
public Light gunLight; // 발포 포인트 라이트 효과
public float effectDisplayTime; //발포 효과 재생 시간
public Transform firePos; //발포위치
// Start is called before the first frame update
void Start()
{
// 충돌 레이어 이름으로 충돌 마스크 값을 구함
shootableMask = LayerMask.GetMask("Shootable");
}
// Update is called once per frame
void Update()
{
//시간을 계산함
time += Time.deltaTime;
//마우스 왼쪽 버튼을 누르고
if (Input.GetButton("Fire1") && time >= fireDelayTime)
{
Shot(); //발포 처리
}
if (time >= fireDelayTime * effectDisplayTime)
{
gunLight.enabled = false;
faceLight.enabled = false;
//라인 비활성화
fireLine.enabled = false;
}
}
void Shot()
{
time = 0f;
//이펙트 라이트 on
gunLight.enabled = true;
faceLight.enabled = true;
//발포 파티클 재생
gunParticleSys.Stop();
gunParticleSys.Play();
//라인렌더러 활성화
fireLine.enabled = true;
//라인시작점 인덱스 : 0, 두번쨰 연결점 인덱스 : 1, ......2,3,4
//라인랜더러의 시작점을 총구 위치로 설정
fireLine.SetPosition(0, firePos.position);
//발포 레이 시작 위치 설정
shootRay.origin = firePos.position;
//발포 레이의 방향 설정
shootRay.direction = firePos.forward;
//
if (Physics.Raycast(shootRay, out shootHit, fireRange, shootableMask))
{
//레이가 충돌한 지점까지 라인의 끝점을 설정함
fireLine.SetPosition(1, shootHit.point);
//관통된 게임 오브젝트에 EnemyHealth 컴포넌트 존재하는지 확인함
EnemyHealth health = shootHit.collider.GetComponent<EnemyHealth>();
if (health != null)
{
health.TakeDamage(damagePerShot, shootHit.point);
}
}
else
{
//레이의 충돌이 없으면 레이 방향으로 지정된 발포 길이만큼으로 라인의 끝점을 설정함
fireLine.SetPosition(1, shootRay.origin + shootRay.direction * fireRange);
}
Debug.Log("발포!!!");
}
}
사망 이벤트 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class EnemyHealth : MonoBehaviour
{
//시작 체력
public int startHealth;
//현재체력
public int currentHealth;
//사망 상태
public bool isDie;
//애니메이터 컴포넌트 참조
public Animator animator;
public ParticleSystem hitParticle;
public ParticleSystem deathParticle;
public Renderer bodyRenderer;
// Start is called before the first frame update
void Start()
{
currentHealth = startHealth;
}
//피격 처리 (피격 데미지)
public void TakeDamage(int damage, Vector3 hitPos)
{
currentHealth -= damage;
if (currentHealth <= 0 && !isDie)
{
Death(); //사망 처리
}
if (isDie) return;
hitParticle.transform.position = hitPos;
hitParticle.Play();
}
//몬스터 사망 처리
public void Death()
{
isDie = true;
animator.SetTrigger("Die");
GetComponent<NavMeshAgent>().isStopped = true;
}
public void OnDieAnimationEvent()
{
bodyRenderer.enabled = false;
deathParticle.Play();
Destroy(gameObject, deathParticle.main.duration);
}
}
적군 생성하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyGenerator : MonoBehaviour
{
public Transform[] genPositions; //생성 위치들
public GameObject enemyPrefab; // 생성 몬스터 참조
public float genDelayTime; // 생성 주기
// Start is called before the first frame update
void Start()
{
//몬스터 생성 타이머
InvokeRepeating("EnemyGenTimer", 2f, genDelayTime);
}
void EnemyGenTimer()
{
int genIndex = Random.Range(0, genPositions.Length);
Instantiate(enemyPrefab, genPositions[genIndex].position, genPositions[genIndex].rotation);
}
}
랜덤생성할때 넓게 생성하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyGenerator : MonoBehaviour
{
public Transform[] genPositions; //생성 위치들
public GameObject enemyPrefab; // 생성 몬스터 참조
public float genDelayTime; // 생성 주기
// Start is called before the first frame update
void Start()
{
//몬스터 생성 타이머
InvokeRepeating("EnemyGenTimer", 2f, genDelayTime);
}
void EnemyGenTimer()
{
int genIndex = Random.Range(0, genPositions.Length);
Vector3 genPosition = genPositions[genIndex].position;
float x = Random.Range(genPosition.x = 1f, genPosition.x + 1f);
float z = Random.Range(genPosition.x = 1f, genPosition.z + 1f);
genPosition = new Vector3(x, 0f, z);
Instantiate(enemyPrefab, genPositions[genIndex].position, genPositions[genIndex].rotation);
}
}
'Unity' 카테고리의 다른 글
[유니티] 3D 슈팅게임 3 (0) | 2021.05.28 |
---|---|
[유니티] 3D 슈팅게임 2 (0) | 2021.05.27 |
[유니티] 네이게이션 (0) | 2021.05.20 |
[유니티]UI (드롭박스) (0) | 2021.05.20 |
[유니티] UI/UX Samples (0) | 2021.05.18 |
댓글