유니티3D 프로그래밍
Unity 5주차 5일 수업 내용 : Dodge, Fov (21.04.09) 본문
Dodge
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
public int damage = 30;
public float speed = 8f;
private PlayerController player;
private Rigidbody bulletRigidbody;
// Start is called before the first frame update
void Start()
{
//게임오브젝트에서 Rigidbody 컴포넌트를 찾아 bulletRigidbody변수에 할당
this.bulletRigidbody = this.GetComponent<Rigidbody>();
//리지드바디의 속도 = 앞쪽 방향 * 이동 속력
this.bulletRigidbody.velocity = this.transform.forward * speed;
Destroy(this.gameObject, 3f);
}
public void Damage()
{
player.currnetHp -= this.damage;
}
private void OnTriggerEnter(Collider other)
{
//충돌 감지
if (other.tag == "Player")
{
this.player = other.GetComponent<PlayerController>();
//상대방으로부터 PlayerController컴포넌트 가져오는데 성공했다면
if (player != null)
{
this.Damage();
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletSpawner : MonoBehaviour
{
public GameObject bulletPrefab; //생성할 탄알의 원본 프리팹
public float spawnRateMin = 0.5f; //최소 생성 주기
public float spawnRateMax = 3; //최대 생성 주기
private Transform target; //발사할 대상
private float spawnRate; //생성주기
private float timeAfterSpawn; //최근 생성 시점에서 지난 시간
// Start is called before the first frame update
void Start()
{
//최근 생성이후의 누적 시간을 0으로 초기화
this.timeAfterSpawn = 0;
// 탄알 생성간격을 spawnRateMin과 spawnRateMax 사이에 랜덤값으로 지정
this.spawnRate = Random.Range(this.spawnRateMin, this.spawnRateMax);
//PlayerController 컴포넌트를 가진 게임 오브젝트를 찾아 조준 대상으로 설정
this.target = FindObjectOfType<PlayerController>().transform;
}
// Update is called once per frame
void Update()
{
if(!target.GetComponent<PlayerController>().isDie)
{
//timeAfterSpawn 갱신
this.timeAfterSpawn += Time.deltaTime;
//최근 생성 시점부터 누적된 시간이 생성주기보다 크거나 같으면
if (this.timeAfterSpawn >= this.spawnRate)
{
//누적 시간 리셋
this.timeAfterSpawn = 0;
//bulletPrefab의 복제본을 transform.position의 위치와 transform.rotation의 회전으로 생성
GameObject bullet = Instantiate(this.bulletPrefab, this.transform.position, this.transform.rotation);
//생성된 bullet 게임 오브젝트의 정면방향이 target을 향하도록 회전
bullet.transform.LookAt(target);
//다음번 생성 간격을 spawnRateMin, spawnRateMax 사이에 랜덤으로 설정
this.spawnRate = Random.Range(this.spawnRateMin, this.spawnRate);
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public GameObject gameoverText;
public Text recordText;
private float time = 0f;
private float score;
private bool isGameOver;
// Start is called before the first frame update
void Start()
{
score = 0;
isGameOver = false;
}
// Update is called once per frame
void Update()
{
if(!isGameOver)
{
this.time += Time.deltaTime;
if(this.time > 0.5f)
{
score += 100;
recordText.text = "Score: " + (int)score;
time = 0;
}
}
else
{
if(Input.GetKeyDown(KeyCode.R))
{
SceneManager.LoadScene("GameScene");
}
}
}
public void EndGame()
{
isGameOver = true;
gameoverText.SetActive(true);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HPSlider : MonoBehaviour
{
public Slider slider;
public GameObject player;
public PlayerController playerHp;
// Start is called before the first frame update
void Start()
{
this.slider = GetComponent<Slider>();
}
// Update is called once per frame
void Update()
{
this.playerHp = player.GetComponent<PlayerController>();
this.slider.value = this.playerHp.currnetHp / this.playerHp.maxHp;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private Rigidbody playerRigidbody;
public bool isDie = false;
public float speed = 8f;
public float maxHp;
public float currnetHp;
private Animation anim;
// Start is called before the first frame update
private void Awake()
{
this.maxHp = 100;
this.currnetHp = maxHp;
}
void Start()
{
this.anim = this.GetComponent<Animation>();
playerRigidbody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
// 수평축과 수직축의 입력값을 감지해서 저장
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
var dir = new Vector3(horizontal, 0, vertical);
if (dir != Vector3.zero)
{
this.anim.Play("run@loop");
float angle = Mathf.Atan2(this.playerRigidbody.velocity.x, this.playerRigidbody.velocity.z) * Mathf.Rad2Deg;
this.playerRigidbody.rotation = Quaternion.Euler(0, angle, 0);
}
else
{
this.anim.Play("idle@loop");
}
//실제 이동속도를 입력값과 이동 속력을 사용해 결정
float xSpeed = horizontal * speed; //방향과 속도
float zSpeed = vertical * speed;
//Vector3 속도를 (xSpeed, 0, zSpeed)로 생성
Vector3 newVelocity = new Vector3(xSpeed, 0, zSpeed);
//AddForce : 관성이 적용
//힘을 누적 속도를 점진적으로 증가
//이전속도를 지우고 새로운 속도를 사용
//관성이 무시됨
playerRigidbody.velocity = newVelocity;
if (currnetHp <= 0)
{
this.Die();
}
}
public void Die()
{
this.gameObject.SetActive(false);
this.anim.Play("die");
this.isDie = true;
GameManager gameManager = FindObjectOfType<GameManager>();
gameManager.EndGame();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotator : MonoBehaviour
{
public float rotationSpeed = 60f;
public GameObject play;
public PlayerController player;
private void Start()
{
}
// Update is called once per frame
void Update()
{
this.player = this.play.GetComponent<PlayerController>();
if (!this.player.isDie)
{
transform.Rotate(0f, rotationSpeed * Time.deltaTime, 0f);
}
}
}
벡터는 위치, 방향, 회전, 속도, 크기등에서 사용
벡터의 종료 ( 요소, 요소)
1. 수 벡터
2. 기하 벡터
벡터 : 방향, 크기
상대 좌표 : 현재 좌표에서 나의 좌표
절대 좌표 : 게임 세상속에서 나의 좌표
벡터의 곱 : 스칼라 곱
벡터의 길이가 늘어난다 (요소의 곱)
ex : (-3, 4) x 2 = (-3 x 2, 4 x 2) = (-6, 8)
크기가 1인 벡터 : 단위 벡터 (방향 벡터)
Vector3.forward(0, 0, 1);
transform.forward
벡터의 합 : 요소의 합
A (3, 2) + B (1, 6) = (4, 8)
B (-2, 8) - A (1, 3) = (-3, 5)
Fov
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fov : MonoBehaviour
{
public float area = 1f;
public float angle = 60f;
public Vector3 anglePos;
public Vector3 CirclePoint(float angle)
{
return new Vector3(
Mathf.Sin((angle + this.transform.eulerAngles.y) * Mathf.Deg2Rad),
0,
Mathf.Cos((angle + this.transform.eulerAngles.y) * Mathf.Deg2Rad));
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(Fov))]
public class FovEditor : Editor
{
private void OnSceneGUI()
{
Fov fov = (Fov)this.target;
//주어진 각도의 1/2
Vector3 fromAnglePos = fov.CirclePoint(-fov.angle * 0.5f);
fov.anglePos = fromAnglePos;
//색상
Handles.color = new Color(1, 1, 1, 0.3f);
Handles.DrawWireDisc(
fov.gameObject.transform.position, //원점
Vector3.up, //방향 벡터
fov.area //원의 반지름
);
Handles.DrawSolidArc(
fov.transform.position, //원점좌표
Vector3.up, //노멀백터
fromAnglePos, //시작위치
fov.angle, //각도
fov.area //반지름
);
GUIStyle guiStyle = new GUIStyle();
guiStyle.fontSize = 40;
Handles.Label(fov.transform.position + fov.transform.forward,
fov.angle.ToString(), guiStyle);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hero : MonoBehaviour
{
private Fov fov;
private GameObject[] monsters;
// Start is called before the first frame update
void Start()
{
this.fov = this.GetComponent<Fov>();
this.monsters = GameObject.FindGameObjectsWithTag("Monster");
}
// Update is called once per frame
void Update()
{
foreach (var monster in this.monsters)
{
var toOther = monster.transform.position - this.transform.position; //몬스터의 방향
var angle = Vector3.Angle(this.transform.forward, toOther); //몬스터와의 각도
var distance = toOther.magnitude; //길이
if (distance <= this.fov.area && angle < this.fov.angle / 2)
{
Debug.DrawLine(this.transform.position, monster.transform.position, Color.red);
}
}
}
}
'Unity > 수업내용' 카테고리의 다른 글
Unity UGUI Test (21.04.20) (0) | 2021.04.20 |
---|---|
Unity 6주차 5일 수업 내용 : 다단계 Scene 구성 (21.04.06) (0) | 2021.04.16 |
Unity 6주차 3,4,5일 수업 내용 : Zombie (21.04.14) (0) | 2021.04.16 |
Unity 6주차 2일 수업 내용 : 쿠키런 구현해보기 (21.04.13) (0) | 2021.04.13 |
Unity 5주차 4일 수업 내용 : Ray, 캐릭터 이동 (21.04.08) (0) | 2021.04.08 |