Assets
1.Map_ Simple Low Poly Nature pack
2.Sky_ Customizable skybox
3.Player_ Battle Royale Duo Playart PBR
4.Enemy_ RPG Monster Duo PBR Polyart
5.Effect_ War FX
pdf file
슈팅게임1-1.pdf
2.27MB
슈팅게임1-2.pdf
0.98MB
슈팅게임2-1.pdf
1.80MB
C# Code
Player
Player의 이동
더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
// 플레이어 키보드 상하좌우 이동
public float moveSpeed = 5; // 이동속도
public float jumpPower = 4; // 점프력
public float rotSpeed = 600; // 회전속도
int jumpCount = 0; // 점프횟수
Rigidbody rb;
Animator anim;
void Start()
{
rb = GetComponent<Rigidbody>();
anim = GetComponent<Animator>();
}
void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(h, 0, v);
dir.Normalize(); // 모든 방향의 속도가 동일하도록 정규화
// 플레이어를 기준으로 방향 조절
dir = transform.TransformDirection(dir);
// 방향*속도*시간(모든 기기에서 동일한 속도)
// transform.position += dir * moveSpeed * Time.deltaTime;
// tr.position, tr.Translate() / rb.position, rb.MovePosition,
// rb.velocity, rb.Addforce(), rb.AddRelativeForce()
// 이동시 물리 작용 적용
rb.MovePosition(rb.position + (dir * moveSpeed * Time.deltaTime));
// 이동하는 속도를 velocity 변수에 할당하여 애니메이션 전환
anim.SetFloat("velocity", dir.magnitude);
// 점프(2단점프)-스페이스키 누른 순간, 점프횟수가 2회 미만이라면
if (Input.GetKeyDown(KeyCode.Space) && jumpCount < 2)
{
// 위로 순간적인 힘 발생
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
// jump 애니메이션 실행
anim.SetTrigger("jump");
anim.SetBool("isJump",true);
// 점프할 때마다 점프횟수 증가
jumpCount++;
}
// 마우스의 좌우움직임 입력 받아서 마우스가 움직인만큼 Y축 회전
float mouseMoveX = Input.GetAxis("Mouse X");
transform.Rotate(0, mouseMoveX * rotSpeed * Time.deltaTime, 0);
}
// 플레이어가 바닥에 닿으면 다시 점프할 수 있도록 준비
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "Ground")
{
jumpCount = 0;
// 점프 애니메이션 종료
anim.SetBool("isJump", false);
}
}
}
PlayerFire
더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerFire : MonoBehaviour
{
public GameObject bulletPrefab; // 총알프리팹 담아둘 변수
public float firePower = 8; // 총알 발사하는 힘
void Start()
{
// 마우스 커서 안보이게하고,
// 마우스 커서가 게임화면을 벗어나지 못하도록 잠금
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Confined;
}
void Update()
{
// 마우스 왼쪽 클릭 시 총알 공장에서 총알을 생성
// -> 플레이어의 위치보다 조금 앞에서 순간적적인 힘 발생
if (Input.GetMouseButtonDown(0))
{
GameObject bullet = Instantiate(bulletPrefab, transform.position + transform.forward, Quaternion.identity);
bullet.GetComponent<Rigidbody>().AddForce(transform.forward * firePower, ForceMode.Impulse);
}
}
}
PlayerFire2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerFire2 : MonoBehaviour
{
// 총효과 프리팹을 담아둘 변수
public GameObject shootEffectPrefab;
Animator anim;
void Start()
{
anim = GetComponent<Animator>();
// 마우스 커서 안보이게하고,
// 마우스 커서가 게임화면을 벗어나지 못하도록 잠금
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Confined;
}
void Update()
{
// 화면 가운데에 조준점을 만들고, 마우스 왼쪽 클릭 시
// Ray를 발사해서 Ray에 맞은 물체는 hit 변수에 저장하고 그 이름을 출력한다.
if (Input.GetMouseButtonDown(0))
{
anim.SetTrigger("shoot");
// 화면 가운데에서 시작하는 Ray 생성
Ray ray = Camera.main.ViewportPointToRay(new Vector2(0.5f, 0.5f));
// Ray에 맞은 물체를 담아둘 변수 선언
RaycastHit hit;
// Ray를 발사하고, Ray에 맞은 물체는 hit에 저장, 맞은 물체가 있을 때만
if(Physics.Raycast(ray, out hit))
{
// Instantiate(shootEffectPrefab, hit.point, Quaternion.LookRotation(hit.normal));
// 맞은 위치에, 맞은 표면의 수직이 되는 각도로 총 효과 프리팹의 복사본 생성
GameObject shootEffect = Instantiate(shootEffectPrefab, hit.point + hit.normal * 0.01f, Quaternion.LookRotation(hit.normal));
// 총알 자국을 맞은 오브젝트의 자식으로 설정
shootEffect.transform.SetParent(hit.transform);
// Ray에 맞은 물체가 Enemy(적)이라면 적에게 10만큼 데미지를 받으라고 전달
if (hit.transform.tag == "Enemy")
{
hit.transform.SendMessage("Damaged", 10);
}
}
}
}
}
에디터에서 Shoot Effect Prefab라는 항목에 Shoot Effect Prefab을 찾아서 넣어두어야 한다.
CameraTotate
카메라의 움직임과 관련된 코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraRotate : MonoBehaviour
{
public float rotSpeed = 600; // 회전속도
// eulerAngles.x의 값을 저장할 변수
float tempX;
void Update()
{
// 마우스의 위아래움직임 입력 받아서 마우스가 움직인만큼 X축 회전
float mouseMoveY = Input.GetAxis("Mouse Y");
transform.Rotate(-mouseMoveY * rotSpeed * Time.deltaTime, 0, 0);
// print(transform.eulerAngles.x);// -10도=350도(오일러각),-10=270도
// 위아래 회전 범위를 -30~+30도로 제한
// 각도가 180도가 넘으면 360을 빼서 각도변환, 아니면 그 값 그대로 저장
if (transform.eulerAngles.x > 180)
{
tempX = transform.eulerAngles.x - 360;
}
else
{
tempX = transform.eulerAngles.x;
}
// 변환한 각도에서 -30~+30도 제한(Mathf.Clamp()) -> 오일러값으로 저장
tempX = Mathf.Clamp(tempX, -30, 30);
transform.eulerAngles = new Vector3(tempX, transform.eulerAngles.y, transform.eulerAngles.z);
}
}
Billboard
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Billboard : MonoBehaviour
{
void Update()
{
//카메라가 바라보는 방향대로 내가 바라보는 방향 설정
transform.forward = Camera.main.transform.forward;
}
}
Enemy
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // UI 관련 클래스를 사용하기 위해 추가
using UnityEngine.AI; // AI 관련된 클래스를 사용하기 위해 네임스페이스 영역 추가
public class Enemy : MonoBehaviour
{
NavMeshAgent agent; // NavMeshAgent 컴포넌트를 변수로 사용
// 적이 가질 수 있는 상태 목록
public enum EnemyState
{
Idle, // 기본(대기)
Walk, // 이동
Attack, // 공격
Damaged, // 피격
Dead, // 죽음
}
// 상태를 저장할 변수 생성(기본값은 Idle로 지정)
public EnemyState eState = EnemyState.Idle;
public float hp = 100; // 적의 체력
public Slider hpBar; // 적의 체력바
Transform player; // 플레이어
float distance; // 플레이어와의 거리
// 공격받는 기능
void Damaged(float damage)
{
// 공격받은 데미지만큼 체력 감소
hp -= damage;
hpBar.value = hp;
agent.isStopped = true; // 이동 중단
agent.ResetPath(); // 경로 초기화
if (hp > 0) // 체력이 남아있다면 피격 상태로 전환
{
eState = EnemyState.Damaged;
}
else // 체력이 남아있지않으면 죽음 상태로 전환
{
eState = EnemyState.Dead;
}
}
void Start()
{
// Player 컴포넌트로 찾은 플레이어의 Transform 컴포넌트 가져오기
player = FindObjectOfType<Player>().transform;
// 나의(Enemy의) NavMeshAgent 컴포넌트 가져오기
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
// 적과 플레이어 사이의 거리 계산
distance = Vector3.Distance(transform.position, player.position);
print(distance);
// 기본, 이동, 공격 상태일 때 할 일 나누기
switch (eState)
{
case EnemyState.Idle: Idle(); break;
case EnemyState.Walk: Walk(); break;
case EnemyState.Attack: Attack(); break;
}
}
// 플레이어와의 거리가 8
void Idle() // 기본 상태일 때 계속 할 일
{
// 플레이어와의 거리가 8이하면 이동 상태로 전환
if (distance <= 8)
{
eState = EnemyState.Walk;
agent.isStopped = false; // 이동 시작한다.
}
}
void Walk() // 이동 상태일 때 계속 할 일
{
// 플레이어와의 거리가 8보다 크면 기본 상태로 전환
// 플레이어와의 거리가 2이하면 공격 상태로 전환
if (distance > 8)
{
eState = EnemyState.Idle;
agent.isStopped = true; // 이동 중단
agent.ResetPath(); // 경로 초기화
}
else if (distance <= 2)
{
eState = EnemyState.Attack;
agent.isStopped = true; // 이동 중단
agent.ResetPath(); // 경로 초기화
}
else
{
agent.SetDestination(player.position);
}
}
void Attack() // 공격 상태일 때 계속 할 일
{
// 플레이어와의 거리가 2보다 크면 이동 상태로 전환
if (distance > 2)
{
eState = EnemyState.Walk;
agent.isStopped = false; // 이동 시작
}
}
}
에디터에 있는 E State은 열거형 변수이고
Hp Bar는 안에 HpBarSlider를 넣어야 한다.