유니티3D 프로그래밍

Unity 5주차 5일 수업 내용 : Dodge, Fov (21.04.09) 본문

Unity/수업내용

Unity 5주차 5일 수업 내용 : Dodge, Fov (21.04.09)

tjdgus9955 2021. 4. 9. 15:05

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);
            }
        }
    }
}