녹화_2024_03_13_22_03_51_619.mp4
2.26MB

 

이제 목숨과 점수를 만들 것이다.

UI는 앵커를 잘 잡아야 한다.

이미지는 쉬프트 알트 왼쪽상단

텍스트는 쉬프트 알트 중앙 상단

캔버스 크기 고정

 

캔버스 안에 있는 것들 크기 및 위치 재조정

 

버튼 같이 늘어나는? 것들은 경계선을 설정 => apply

빈 오브젝트에 넣는다.

적을 처치하면 점수를 받는다. ( enemy가 파괴될때 player의 스코어를 더해준다.)

UI이미지들은 게임매니저에서 관리

게임매니저의 업데이트문에서 점수 처리

세자리마다 쉼표로 나눠주는 숫자 양식

체력을 잃는 부분은 플레이어 스크립트에 있으므로

체력 이미지를 배열로 받아서

색의 알파를 조절하여 보이지 않게 할 것이다.

목숨이 없으면 게임오버 창이 나오게 할것이고 아닐시 리스폰

게임매니저에서 활성화 여부 조절하는 메서드 작성

이제 퍼블릭으로 생성된 컴포넌트에 부착

프리팹 모드로 들어가서 각각 점수 할당 500, 200, 50

 

실행을 해서 죽으면 게임오버가 나오고 재시작 버튼로직을 이제 만들것이다.

화면 전환을 하는 방식으로 사용할 것이다.

https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadScene.html

 

Unity - Scripting API: SceneManagement.SceneManager.LoadScene

Note: In most cases, to avoid pauses or performance hiccups while loading, you should use the asynchronous version of this command which is: LoadSceneAsync. When using SceneManager.LoadScene, the scene loads in the next frame, that is it does not load imme

docs.unity3d.com

 

File - Bullid Settings => 기본값은 0

그런데 플레이를 하다가 한번에 두발을 맞으면 체력이 2가 줄어드는 곳을 볼 수 있는데 이것을 수정할 것이다.

bool 변수를 다시 초기화 하는 부분도 꼭 구현해야한다.

using System.Collections;
using System.Collections.Generic;
using System.Net.Http.Headers;
using UnityEngine;

public class Player : MonoBehaviour
{
    public bool isTouchTop;
    public bool isTouchBottom;
    public bool isTouchRight;
    public bool isTouchLeft;

    public int life;
    public int score;
    public float speed;
    public float power;
    public float maxShotDelay; //실제 딜레이
    public float curShorDelay; //한발 쏜 후 딜레이

    public GameObject bulletObjA;
    public GameObject bulletObjB;

    public GameManager manager;
    public bool isHit;
    private Animator anim;

    private void Awake()
    {
        anim = GetComponent<Animator>();
    }

    void Move()
    {
        float h = Input.GetAxisRaw("Horizontal");
        if ((isTouchRight && h == 1) || (isTouchLeft && h == -1))
            h = 0;
        float v = Input.GetAxisRaw("Vertical");
        if ((isTouchTop && v == 1) || (isTouchBottom && v == -1))
            v = 0;
        Vector3 curPos = this.transform.position;
        Vector3 nextPos = new Vector3(h, v, 0) * speed * Time.deltaTime;
        transform.position = curPos + nextPos;

        if (Input.GetButtonDown("Horizontal") ||
            Input.GetButtonDown("Vertical"))
        {
            anim.SetInteger("Input", (int)h);
        }
    }

    private void Update()
    {
        Move();
        Fire();
        Reload();
    }

    void Fire()
    {
        if (!Input.GetButton("Fire1"))
            return;
        if (curShorDelay < maxShotDelay)
            return;

        switch (power)
        {

            case 1://Power One
                GameObject bullet = Instantiate(bulletObjA, transform.position, transform.rotation);
                Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
                rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                break;
            case 2:
                GameObject bulletR = Instantiate(bulletObjA, transform.position + Vector3.right * 0.1f, transform.rotation);
                GameObject bulletL = Instantiate(bulletObjA, transform.position + Vector3.left * 0.1f, transform.rotation);
                Rigidbody2D rigidR = bulletR.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidL = bulletL.GetComponent<Rigidbody2D>();
                rigidR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);

                break;
            case 3:
                GameObject bulletRR = Instantiate(bulletObjA, transform.position + Vector3.right * 0.3f, transform.rotation);
                GameObject bulletCC = Instantiate(bulletObjB, transform.position, transform.rotation);
                GameObject bulletLL = Instantiate(bulletObjA, transform.position + Vector3.left * 0.3f, transform.rotation);
                Rigidbody2D rigidRR = bulletRR.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidCC = bulletCC.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidLL = bulletLL.GetComponent<Rigidbody2D>();
                rigidRR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidCC.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidLL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);

                break;
        }
                curShorDelay = 0;
    }

    void Reload()
    {
        curShorDelay += Time.deltaTime;

    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "Border")
        {
            switch(collision.gameObject.name)
            {
                case "Top":
                    isTouchTop = true;
                    break;
                case "Bottom":
                    isTouchBottom = true;
                    break;
                case "Right":
                    isTouchRight = true;
                    break;
                case "Left":
                    isTouchLeft = true;
                    break;
            }
        }
        else if(collision.gameObject.tag == "Enemy" || collision.gameObject.tag == "EnemyBullet")
        {
            if (isHit)
            {
                return;
            }
            isHit = true;
            life--;
            manager.UpdateLifeIcon(life);

            if(life == 0)
            {
                manager.GameOver();
            }
            else
            {
                manager.RespawnPlayer();
            }
            gameObject.SetActive(false);

        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        switch (collision.gameObject.name)
        {
            case "Top":
                isTouchTop = false;
                break;
            case "Bottom":
                isTouchBottom = false;
                break;
            case "Right":
                isTouchRight = false;
                break;
            case "Left":
                isTouchLeft = false;
                break;
        }
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour
{
    public int dmg;
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "BorderBullet")
        Destroy(gameObject); //모노비헤이어에 들어 있는 자체 함수 => 매개변수 오브젝트를 삭제하는 함수
    }
}

 

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    public string enemyName;
    public int enemyScore;
    public float speed;
    public int health;
    public Sprite[] sprites;
    public float maxShotDelay; //실제 딜레이
    public float curShorDelay; //한발 쏜 후 딜레이
    public GameObject bulletObjA;
    public GameObject bulletObjB;
    public GameObject player;
    SpriteRenderer spriteRenderer;
    Rigidbody2D rigid;

    private void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        rigid = GetComponent<Rigidbody2D>();
        rigid.velocity = Vector2.down * speed;
    }
    private void Update()
    {
        Fire();
        Reload();
    }
    void Fire()
    {
        if (curShorDelay < maxShotDelay)
            return;

        if (enemyName == "S")
        {
            GameObject bullet = Instantiate(bulletObjA, transform.position, transform.rotation);
            Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
            Vector3 dirVec = player.transform.position - transform.position;
            rigid.AddForce(dirVec.normalized * 3, ForceMode2D.Impulse);  // 방향 벡터를 정규화하여 힘을 가하는 부분 수정
        }
        else if (enemyName == "L")
        {
            GameObject bulletR = Instantiate(bulletObjB, transform.position + Vector3.right * 0.3f, transform.rotation);
            GameObject bulletL = Instantiate(bulletObjB, transform.position + Vector3.left * 0.3f, transform.rotation);
            Rigidbody2D rigidR = bulletR.GetComponent<Rigidbody2D>();
            Rigidbody2D rigidL = bulletL.GetComponent<Rigidbody2D>();
            Vector3 dirVecR = player.transform.position - (transform.position + Vector3.right * 0.3f);
            Vector3 dirVecL = player.transform.position - (transform.position + Vector3.left * 0.3f);
            rigidR.AddForce(dirVecR.normalized * 4, ForceMode2D.Impulse);  // 방향 벡터를 정규화하여 힘을 가하는 부분 수정
            rigidL.AddForce(dirVecL.normalized * 4, ForceMode2D.Impulse);  // 방향 벡터를 정규화하여 힘을 가하는 부분 수정
        }

        curShorDelay = 0;  // 발사 후 딜레이 초기화는 발사 이후에 처리되도록 이동
    }

    void Reload()
    {
        curShorDelay += Time.deltaTime;

    }
    private void OnHit(int dmg)
    {
        health -= dmg;
        spriteRenderer.sprite = sprites[1]; //피격시 1번
        Invoke("ReturnSprite", 0.1f);
        if(health <= 0)
        {
            Player playerLogic = player.GetComponent<Player>();
            playerLogic.score += enemyScore;
            Destroy(gameObject);
        }
    }

    void ReturnSprite()
    {
        spriteRenderer.sprite = sprites[0];
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "BorderBullet")
        {
            Destroy(gameObject );
        }
        else if(collision.gameObject.tag == "PlayerBullet")
        {
            Bullet bullet = collision.gameObject.GetComponent<Bullet>();
            OnHit(bullet.dmg);

            Destroy(collision.gameObject);
        }
    }

}

 

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public GameObject[] enemyObjs;
    public Transform[] spawnPoints;

    public float maxSpawnDelay;
    public float curSpawnDelay;

    public GameObject player;
    public Text scoreText;
    public Image[] lifeImage;
    public GameObject gameOverSet;
    private void Update()
    {
        curSpawnDelay += Time.deltaTime;

        if (curSpawnDelay > maxSpawnDelay)
        {
            SpawnEnemy();
            maxSpawnDelay = Random.Range(0.5f, 3f);
            curSpawnDelay = 0;
        }

        //UI Score

        Player playerLogic = player.GetComponent<Player>();
        scoreText.text = string.Format("{0:n0}", playerLogic.score);



    }
    void SpawnEnemy()
    {
        int ranEnemy = Random.Range(0, 3); //소환될 적
        int ranPoint = Random.Range(0, 9); //소환될 위치
        GameObject enemy = Instantiate(enemyObjs[ranEnemy],
                                        spawnPoints[ranPoint].position,
                                        spawnPoints[ranPoint].rotation);
        Rigidbody2D rigid = enemy.GetComponent<Rigidbody2D>();
        //스피드도 가지고 와야한다.
        Enemy enemyLogic = enemy.GetComponent<Enemy>();
        //적비행기 생성 직후 플레이에 변수를 넘겨준다.
        enemyLogic.player = player;
        if (ranPoint == 5 || ranPoint == 6)
        {
            enemy.transform.Rotate(Vector3.back * 90); //z축으로 90도
            rigid.velocity = new Vector2(enemyLogic.speed * (-1), -1);
        }else if(ranPoint == 7 || ranPoint == 8)
        {
            enemy.transform.Rotate(Vector3.forward * 90); //z축으로 90도
            rigid.velocity = new Vector2(enemyLogic.speed, -1);
        }
        else
        {
            rigid.velocity = new Vector2(0, enemyLogic.speed * (-1));
        }
    }

    public void UpdateLifeIcon(int life)
    {
        //UI Init Disable
        for (int index = 0; index < 3; index++)
        {
            lifeImage[index].color = new Color(1, 1, 1, 0);
        }
        //UI Life Active
        for (int index = 0; index < life; index++)
        {
            lifeImage[index].color = new Color(1, 1, 1, 1);
        }
    }


    public void RespawnPlayer()
    {
        Invoke("RespawnPlayerExe", 2f);
        
    }
    private void RespawnPlayerExe()
    {
        player.transform.position = Vector3.down * 3.5f;
        player.SetActive(true);

        Player playerLogic = player.GetComponent<Player>();
        playerLogic.isHit = false;
    }
    public void GameOver()
    {
        gameOverSet.SetActive(true);
    }

    public void GameRetry()
    {
        SceneManager.LoadScene(0);
    }
}

'산대특' 카테고리의 다른 글

팬텀로즈스칼렛 모작 최종  (0) 2024.04.08
2D Airplane - 원근감있는 무한 배경 만들  (0) 2024.03.17
2D Airplane - 4  (0) 2024.03.12
2D Airplane - 3  (0) 2024.03.12
2D Airplane - 2  (0) 2024.03.10
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Experimental.GraphView;
using UnityEngine;

public class PlayerCtrl : MonoBehaviour
{
    private Transform tr;
    public float moveSpeed = 10.0f;
    public float turnSpeed = 80.0f;
    private Animation anim;

    void Awake()
    {
        //제일먼저 호출되는 함수
        //스크리브가 비활성화되있어도 호출되는 함수

    }

    private void OnEnable()
    {
        //두번째로 호출되는 함수
        //스크립트가 활성화 될때마다 호출되는 함수
    }

    private void Start()
    {
        //세번째로 호출되는 함수
        //Update함수가 호출되기 전에 호출되는 함수
        //코루틴으로 호출될 수 있는 함수
        //예)
        //IEnumerator Start(){}
        tr = GetComponent<Transform>();
        anim = GetComponent<Animation>();

        this.anim.Play("Idle");

        //this.anim.clip = this.anim.GetClip("Idle");
        //anim.Play();

    }

    private void FixedUpdate()
    {
        //일정간격으로 호출되는 함수 (기본값은 0.02초)
        //물리엔진의 계산 주기와 일치

    }

    void Update()
    {
        //프레임마다 호출되는 함수
        //호출 간격이 불규칙하다
        //화면의 렌더링 주기와 일치 함
        float h = Input.GetAxis("Horizontal"); // -1.0 ~ 0 ~ 1
        float v = Input.GetAxis("Vertical"); // -1.0 ~ 0 ~ 1
        float r = Input.GetAxis("Mouse X");

        //Debug.Log("h=" + h);
        //Debug.Log("v=" + v);
        Debug.Log("r=" + r);

        //this.tr.Translate(Vector3.forward * 1 * 0.01f , Space.Self); //로컬좌표 기준으로 이동
        //this.tr.Translate(Vector3.forward * 1 * Time.deltaTime, Space.World); //월드좌표 기준으로 이동

        //매 프레임마다 1유닛씩 이동 => 0.02초
        //this.tr.Translate(Vector3.forward * 1 * Time.deltaTime);


        //매 초마다 1유닛씩 이동
        //프레임 레이트가 서로다른 기기에서도 개발자가 지정한 일정한 속도로 이동하기 위함
        //this.tr.Translate(Vector3.forward * v * Time.deltaTime * moveSpeed); //방향 * 속도 * 시간 => forward = (0,0,1) // v => -1~ 1 사이의 값 => v를 사용해서 앞뿐만이 아닌 뒤로도 이동가능

        //전후좌우 이동방향 벡터 계산
        Vector3 moveDir = (Vector3.forward * v) + (Vector3.right * h); // right = (1,0,0)

        //방향 * 속도 * 시간 
        this.tr.Translate(moveDir.normalized * moveSpeed * Time.deltaTime);

        //Vector3.up 축으로 turnSpeed만큼
        this.tr.Rotate(Vector3.up * r * this.turnSpeed);

        //캐릭터 애니메이션 실행
        PlayerAnim(h, v);


    }

    private void LateUpdate()
    {
        //Update함수가 종료된 후 호출 되는 함수
    }

    private void PlayerAnim(float h, float v)
    {
        //키보드 입력값을 기준으로 동작할 애니메이션 실행
        if (v >= 0.1f)
        {
            //0.25f초간 이전 애니메이션과 실행할 애니메이션을 보간 
            this.anim.CrossFade("RunF", 0.25f); //전진 애니메이션 실행 
        }
        else if (v <= -0.1f)
        {
            this.anim.CrossFade("RunB", 0.25f);//후진 
        }
        else if (h >= 0.1f)
        {
            this.anim.CrossFade("RunR", 0.25f);//오른쪽 
        }
        else if (h <= -0.1f)
        {
            this.anim.CrossFade("RunL", 0.25f);//왼쪽 
        }
        else
        {
            this.anim.CrossFade("Idle", 0.25f);//기본 
        }

    }

}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletCtrl : MonoBehaviour
{
    public float damage = 20.0f;
    public float force = 1500f;
    private Rigidbody rb;

    void Start()
    {
        this.rb = this.GetComponent<Rigidbody>();
        this.rb.AddForce(this.transform.forward * force);

        Destroy(gameObject, 3f);
    }

}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FollowCam : MonoBehaviour
{
    public Transform targetTr;
    private Transform camTr;

    //대상으로 부터 떨어질 거리 
    [Range(2.0f, 20.0f)]
    public float distance = 10.0f;

    //Y축으로 이동할 높이 
    [Range(0.0f, 10.0f)]
    public float height = 2.0f;

    //반응속도 
    public float damping = 10f;

    //SmoothDamp에 사용할 속도 변수
    private Vector3 velocity = Vector3.zero;

    //카메라 LookAt OffSet
    public float targetOffset = 2.0f;


    void Start()
    {
        this.camTr = GetComponent<Transform>();     //Transform 객체 캐싱 
    }

    private void LateUpdate()
    {
        //추적할 대상의 뒤쪽 distance만큼 이동 
        //높이를 height만큼 이동 
        Vector3 pos = this.targetTr.position +
            (-targetTr.forward * distance) +
            (Vector3.up * height);

        //구면 선형 보간 함수를 사용해 부드럽게 위치를 변경 
        //시작위치, 목표 위치, 시간 
        //this.camTr.position = Vector3.Slerp(this.camTr.position, pos, Time.deltaTime * damping);

        //시작위치, 목표위치, 현재속도, 목표 위치까지 도달할 시간
        this.camTr.position = Vector3.SmoothDamp(this.camTr.position, pos, ref velocity, damping);


        //Camera를 피벗 좌표를 향해 회전 
        this.camTr.LookAt(this.targetTr.position + (targetTr.up * targetOffset));

    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FireCtrl : MonoBehaviour
{
    public GameObject bulletPrefab;
    public Transform firePoint;
    public AudioClip fireSfx;
    private AudioSource audioSource;

    private MeshRenderer muzzleFlash;
    private Coroutine muzzleFlashCoroutine;

    private void Start()
    {
        audioSource = GetComponent<AudioSource>();
        muzzleFlash = this.firePoint.GetComponentInChildren<MeshRenderer>();
        muzzleFlash.enabled = false;
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            this.Fire();
        }
    }

    private void Fire()
    {
        Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);

        audioSource.PlayOneShot(fireSfx, 1f);

        if (muzzleFlashCoroutine != null) StopCoroutine(muzzleFlashCoroutine);

        this.muzzleFlashCoroutine = StartCoroutine(this.ShowMuzzleFlash());
    }

    IEnumerator ShowMuzzleFlash()
    {
        Vector2 offset = new Vector2(Random.Range(0, 2), Random.Range(0, 2)) * 0.5f;
        muzzleFlash.material.mainTextureOffset = offset;



        float angle = Random.Range(0, 360);
        muzzleFlash.transform.localRotation = Quaternion.Euler(0, 0, angle);


        float scale = Random.Range(1, 2);
        muzzleFlash.transform.localScale = Vector3.one * scale;


        muzzleFlash.enabled = true; //보여주기 

        yield return new WaitForSeconds(0.2f);  //0.2초후 

        muzzleFlash.enabled = false;    //안보여주기 
    }
}

 

using UnityEngine;
using System.Collections;
using UnityEditor;


public enum ArrowType
{
    Default,
    Thin,
    Double,
    Triple,
    Solid,
    Fat,
    ThreeD,
}

public static class DrawArrow
{
    public static void ForGizmo(Vector3 pos, Vector3 direction, Color? color = null, bool doubled = false, float arrowHeadLength = 0.2f, float arrowHeadAngle = 20.0f)
    {
        Gizmos.color = color ?? Color.white;

        //arrow shaft
        Gizmos.DrawRay(pos, direction);

        if (direction != Vector3.zero)
        {
            //arrow head
            Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * new Vector3(0, 0, 1);
            Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * new Vector3(0, 0, 1);
            Gizmos.DrawRay(pos + direction, right * arrowHeadLength);
            Gizmos.DrawRay(pos + direction, left * arrowHeadLength);
        }
    }

    public static void ForDebug(Vector3 pos, Vector3 direction, float duration = 0.5f, Color? color = null, ArrowType type = ArrowType.Default, float arrowHeadLength = 0.2f, float arrowHeadAngle = 30.0f, bool sceneCamFollows = false)
    {
        Color actualColor = color ?? Color.white;
        duration = duration / Time.timeScale;

        float width = 0.01f;

        Vector3 directlyRight = Vector3.zero;
        Vector3 directlyLeft = Vector3.zero;
        Vector3 directlyBack = Vector3.zero;
        Vector3 headRight = Vector3.zero;
        Vector3 headLeft = Vector3.zero;

        if (direction != Vector3.zero)
        {
            directlyRight = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + 90, 0) * new Vector3(0, 0, 1);
            directlyLeft = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - 90, 0) * new Vector3(0, 0, 1);
            directlyBack = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180, 0) * new Vector3(0, 0, 1);
            headRight = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * new Vector3(0, 0, 1);
            headLeft = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * new Vector3(0, 0, 1);
        }

        //draw arrow head
        Debug.DrawRay(pos + direction, headRight * arrowHeadLength, actualColor, duration);
        Debug.DrawRay(pos + direction, headLeft * arrowHeadLength, actualColor, duration);

        switch (type)
        {
            case ArrowType.Default:
                Debug.DrawRay(pos, direction, actualColor, duration); //draw center line
                break;
            case ArrowType.Double:
                Debug.DrawRay(pos + directlyRight * width, direction * (1 - width), actualColor, duration); //draw line slightly to right
                Debug.DrawRay(pos + directlyLeft * width, direction * (1 - width), actualColor, duration); //draw line slightly to left

                //draw second arrow head
                Debug.DrawRay(pos + directlyBack * width + direction, headRight * arrowHeadLength, actualColor, duration);
                Debug.DrawRay(pos + directlyBack * width + direction, headLeft * arrowHeadLength, actualColor, duration);

                break;
            case ArrowType.Triple:
                Debug.DrawRay(pos, direction, actualColor, duration); //draw center line
                Debug.DrawRay(pos + directlyRight * width, direction * (1 - width), actualColor, duration); //draw line slightly to right
                Debug.DrawRay(pos + directlyLeft * width, direction * (1 - width), actualColor, duration); //draw line slightly to left
                break;
            case ArrowType.Fat:
                break;
            case ArrowType.Solid:
                int increments = 20;
                for (int i = 0; i < increments; i++)
                {
                    float displacement = Mathf.Lerp(-width, +width, i / (float)increments);
                    //draw arrow body
                    Debug.DrawRay(pos + directlyRight * displacement, direction, actualColor, duration); //draw line slightly to right
                    Debug.DrawRay(pos + directlyLeft * displacement, direction, actualColor, duration); //draw line slightly to left
                                                                                                        //draw arrow head
                    Debug.DrawRay((pos + direction) + directlyRight * displacement, headRight * arrowHeadLength, actualColor, duration);
                    Debug.DrawRay((pos + direction) + directlyRight * displacement, headLeft * arrowHeadLength, actualColor, duration);
                }
                break;
            case ArrowType.Thin:
                Debug.DrawRay(pos, direction, actualColor, duration); //draw center line
                break;
            case ArrowType.ThreeD:
                break;
        }

        /*#if UNITY_EDITOR
            //snap the Scene view camera to a spot where it is looking directly at this arrow.
                if (sceneCamFollows)
                    SceneViewCameraFollower.activateAt(pos + direction, duration, "_arrow");
        #endif*/
    }

    public static void randomStar(Vector3 center, Color color)
    {
        //special: refuse to draw at 0,0.
        if (center == Vector3.zero) return;
        for (int i = 0; i < 2; i++)
            DrawArrow.ForGizmo(center, UnityEngine.Random.onUnitSphere * 1, color, false, 0.1f, 30.0f);
    }

    public static void comparePositions(Transform t1, Transform t2)
    {
        //direct from one to the other:
        ForDebug(t1.position, t2.position - t1.position);

        //direction
        //Vector3 moveDirection = (t2.position-t1.position).normalized;
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RemoveBullet : MonoBehaviour
{
    public GameObject sparkEffectPrefab;

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.collider.CompareTag("Bullet"))
        {
            //첫번째 충돌 지점의 정보 추출 
            ContactPoint contactPoint = collision.contacts[0];

            DrawArrow.ForDebug(contactPoint.point, -contactPoint.normal, 10, Color.red);

            //충돌한 총알의 법선 벡터를 쿼터니언으로 변환 
            Quaternion rot = Quaternion.LookRotation(-contactPoint.normal);

            Instantiate(this.sparkEffectPrefab, contactPoint.point, rot);

            Destroy(collision.gameObject);
        }
    }
}

 

using UnityEngine;

public class BarrelCtrl : MonoBehaviour
{
    private int hitCount = 0;
    private Transform trans;
    private Rigidbody rb;
    public GameObject explosionPrefab;
    public Texture[] textures;
    private new MeshRenderer renderer;

    //폭발 반경 
    public float radius = 10f;


    void Start()
    {
        this.trans = this.GetComponent<Transform>();
        this.rb = this.GetComponent<Rigidbody>();

        //자식에 있는 랜더러 컴포넌트를 찾아옴 
        this.renderer = this.GetComponentInChildren<MeshRenderer>();
        //난수 발생 
        int index = Random.Range(0, this.textures.Length);
        //텍스쳐 변경 
        this.renderer.material.mainTexture = textures[index];
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.collider.CompareTag("Bullet"))
        {
            if (++hitCount == 3)
            {
                ExplodeBarrel();
            }
        }
    }

    private void ExplodeBarrel()
    {
        //폭파 이펙트를 생성 
        GameObject exp = Instantiate(explosionPrefab, this.trans.position, Quaternion.identity);
        //이펙트 5초 있다가 제거 
        Destroy(exp, 5.0f);

        //힘을 위로 가함 
        //this.rb.mass = 1.0f;    //질량을 줄여주고 
        //this.rb.AddForce(Vector3.up * 1500);    //위로 힘을 가한다 

        //간접 폭발력 전달 
        IndirectDamage(this.trans.position);

        //3초후 드럼통 제거 
        Destroy(this.gameObject, 3);
    }

    private void IndirectDamage(Vector3 pos)
    {
        //주변에 있는 드럼통들을 모두 추출 
        Collider[] colls = Physics.OverlapSphere(pos, this.radius, 1 << 3);

        foreach (var coll in colls)
        {
            var rb = coll.GetComponent<Rigidbody>();
            rb.mass = 1.0f;
            rb.constraints = RigidbodyConstraints.None;
            rb.AddExplosionForce(1500, pos, radius, 1200);
        }
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(this.transform.position, this.radius);
    }


}

'산대특 > 게임 클라이언트 프로그래밍' 카테고리의 다른 글

Occlusion Culling  (0) 2024.03.18
Sprite Shooter - Player and Monster Animation  (0) 2024.03.14
Zombie - IK  (0) 2024.03.07
Zombie - Line Render  (0) 2024.03.07
Tank - Rigidbody.MovePosition  (0) 2024.03.06

 

 

리스폰 포인트 추가

추가후 어싸인

 

이제 적들이 옆에서도 등장하므로 위에서 아래로 떨어지는 부분 삭제

 

적 비행기 속도를 게임매니저가 관리할 것이다.

 

1, 2, 3, 4포인트는 x축은 변함이 없을 것이고 y축은 -1로 고정하여 아래로 내려오게

5, 6 포인트는 왼쪽(-1), y축은 -1

7, 8 포인트는 오른쪽(1), y축은 -1

생성시 보더불릿에 닿으면 사라져서 생성되지 않으니 위치 재조정

그림과 같이 옆모양으로 나오게 하기 위해 회전을 추가

 

이제 적의 총알을 만들 것이다.

기존의 불렛b를 복사한후 프리팹모드에 들어가서 이름을 바꾸고 저장

스프라이트 변경후 박스콜라이더 크기 재설정

 

하나더 만들어준 후 태그 달기

플레이어에 있는 코드를 가져와서 부착

네임은 오브젝트네임 자체에 들어가 있으므로 이름 변경

적이 생성될때 플레이어를 알아야한다.

적 비행기 생성 직후 플레이어 변수를 넘겨준다.

목표물 방향 = 목표물위치 - 자신의 위치

큰 적은 두발을 쏜다.

플레이어는 인스턴스화가 되어있지 않기에 할당X

 

 if문에 총알을 발사할 이름을 넣었기 때문에 이름을 할당

 

적들의 총알이 너무 빠르므로 속도를 조절

 

플레이어의 온트리거에 추가

게임매니저가 플레이러를 리스폰 시킬수 있다.

 

플레이어도 게임매니저를 알아야한다.

 public GameManager manager;

 

2초 후에 플레이어가 부활하게 할 것이다.

플레이어 스크립트에 리스폰 추가

 

using System.Collections;
using System.Collections.Generic;
using System.Net.Http.Headers;
using UnityEngine;

public class Player : MonoBehaviour
{
    public bool isTouchTop;
    public bool isTouchBottom;
    public bool isTouchRight;
    public bool isTouchLeft;
    private Animator anim;

    public float speed;
    public float power;
    public float maxShotDelay; //실제 딜레이
    public float curShorDelay; //한발 쏜 후 딜레이

    public GameObject bulletObjA;
    public GameObject bulletObjB;

    public GameManager manager;
    private void Awake()
    {
        anim = GetComponent<Animator>();
    }

    void Move()
    {
        float h = Input.GetAxisRaw("Horizontal");
        if ((isTouchRight && h == 1) || (isTouchLeft && h == -1))
            h = 0;
        float v = Input.GetAxisRaw("Vertical");
        if ((isTouchTop && v == 1) || (isTouchBottom && v == -1))
            v = 0;
        Vector3 curPos = this.transform.position;
        Vector3 nextPos = new Vector3(h, v, 0) * speed * Time.deltaTime;
        transform.position = curPos + nextPos;

        if (Input.GetButtonDown("Horizontal") ||
            Input.GetButtonDown("Vertical"))
        {
            anim.SetInteger("Input", (int)h);
        }
    }

    private void Update()
    {
        Move();
        Fire();
        Reload();
    }

    void Fire()
    {
        if (!Input.GetButton("Fire1"))
            return;
        if (curShorDelay < maxShotDelay)
            return;

        switch (power)
        {

            case 1://Power One
                GameObject bullet = Instantiate(bulletObjA, transform.position, transform.rotation);
                Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
                rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                break;
            case 2:
                GameObject bulletR = Instantiate(bulletObjA, transform.position + Vector3.right * 0.1f, transform.rotation);
                GameObject bulletL = Instantiate(bulletObjA, transform.position + Vector3.left * 0.1f, transform.rotation);
                Rigidbody2D rigidR = bulletR.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidL = bulletL.GetComponent<Rigidbody2D>();
                rigidR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);

                break;
            case 3:
                GameObject bulletRR = Instantiate(bulletObjA, transform.position + Vector3.right * 0.3f, transform.rotation);
                GameObject bulletCC = Instantiate(bulletObjB, transform.position, transform.rotation);
                GameObject bulletLL = Instantiate(bulletObjA, transform.position + Vector3.left * 0.3f, transform.rotation);
                Rigidbody2D rigidRR = bulletRR.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidCC = bulletCC.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidLL = bulletLL.GetComponent<Rigidbody2D>();
                rigidRR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidCC.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidLL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);

                break;
        }
                curShorDelay = 0;
    }

    void Reload()
    {
        curShorDelay += Time.deltaTime;

    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "Border")
        {
            switch(collision.gameObject.name)
            {
                case "Top":
                    isTouchTop = true;
                    break;
                case "Bottom":
                    isTouchBottom = true;
                    break;
                case "Right":
                    isTouchRight = true;
                    break;
                case "Left":
                    isTouchLeft = true;
                    break;
            }
        }
        else if(collision.gameObject.tag == "Enemy" || collision.gameObject.tag == "EnemyBullet")
        {
            manager.RespawnPlayer();
            gameObject.SetActive(false);

        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        switch (collision.gameObject.name)
        {
            case "Top":
                isTouchTop = false;
                break;
            case "Bottom":
                isTouchBottom = false;
                break;
            case "Right":
                isTouchRight = false;
                break;
            case "Left":
                isTouchLeft = false;
                break;
        }
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour
{
    public int dmg;
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "BorderBullet")
        Destroy(gameObject); //모노비헤이어에 들어 있는 자체 함수 => 매개변수 오브젝트를 삭제하는 함수
    }
}

 

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    public string enemyName;
    public float speed;
    public int health;
    public Sprite[] sprites;
    public float maxShotDelay; //실제 딜레이
    public float curShorDelay; //한발 쏜 후 딜레이
    public GameObject bulletObjA;
    public GameObject bulletObjB;
    public GameObject player;
    SpriteRenderer spriteRenderer;
    Rigidbody2D rigid;

    private void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        rigid = GetComponent<Rigidbody2D>();
        rigid.velocity = Vector2.down * speed;
    }
    private void Update()
    {
        Fire();
        Reload();
    }
    void Fire()
    {
        if (curShorDelay < maxShotDelay)
            return;

        if (enemyName == "S")
        {
            GameObject bullet = Instantiate(bulletObjA, transform.position, transform.rotation);
            Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
            Vector3 dirVec = player.transform.position - transform.position;
            rigid.AddForce(dirVec.normalized * 3, ForceMode2D.Impulse);  // 방향 벡터를 정규화하여 힘을 가하는 부분 수정
        }
        else if (enemyName == "L")
        {
            GameObject bulletR = Instantiate(bulletObjB, transform.position + Vector3.right * 0.3f, transform.rotation);
            GameObject bulletL = Instantiate(bulletObjB, transform.position + Vector3.left * 0.3f, transform.rotation);
            Rigidbody2D rigidR = bulletR.GetComponent<Rigidbody2D>();
            Rigidbody2D rigidL = bulletL.GetComponent<Rigidbody2D>();
            Vector3 dirVecR = player.transform.position - (transform.position + Vector3.right * 0.3f);
            Vector3 dirVecL = player.transform.position - (transform.position + Vector3.left * 0.3f);
            rigidR.AddForce(dirVecR.normalized * 4, ForceMode2D.Impulse);  // 방향 벡터를 정규화하여 힘을 가하는 부분 수정
            rigidL.AddForce(dirVecL.normalized * 4, ForceMode2D.Impulse);  // 방향 벡터를 정규화하여 힘을 가하는 부분 수정
        }

        curShorDelay = 0;  // 발사 후 딜레이 초기화는 발사 이후에 처리되도록 이동
    }

    void Reload()
    {
        curShorDelay += Time.deltaTime;

    }
    private void OnHit(int dmg)
    {
        health -= dmg;
        spriteRenderer.sprite = sprites[1]; //피격시 1번
        Invoke("ReturnSprite", 0.1f);
        if(health <= 0)
        {
            Destroy(gameObject);
        }
    }

    void ReturnSprite()
    {
        spriteRenderer.sprite = sprites[0];
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "BorderBullet")
        {
            Destroy(gameObject );
        }
        else if(collision.gameObject.tag == "PlayerBullet")
        {
            Bullet bullet = collision.gameObject.GetComponent<Bullet>();
            OnHit(bullet.dmg);

            Destroy(collision.gameObject);
        }
    }

}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    public GameObject[] enemyObjs;
    public Transform[] spawnPoints;

    public float maxSpawnDelay;
    public float curSpawnDelay;

    public GameObject player;

    private void Update()
    {
        curSpawnDelay += Time.deltaTime;

        if(curSpawnDelay > maxSpawnDelay)
        {
            SpawnEnemy();
            maxSpawnDelay = Random.Range(0.5f, 3f);
            curSpawnDelay = 0;
        }
    }
    void SpawnEnemy()
    {
        int ranEnemy = Random.Range(0, 3); //소환될 적
        int ranPoint = Random.Range(0, 9); //소환될 위치
        GameObject enemy = Instantiate(enemyObjs[ranEnemy],
                                        spawnPoints[ranPoint].position,
                                        spawnPoints[ranPoint].rotation);
        Rigidbody2D rigid = enemy.GetComponent<Rigidbody2D>();
        //스피드도 가지고 와야한다.
        Enemy enemyLogic = enemy.GetComponent<Enemy>();
        //적비행기 생성 직후 플레이에 변수를 넘겨준다.
        enemyLogic.player = player;
        if (ranPoint == 5 || ranPoint == 6)
        {
            enemy.transform.Rotate(Vector3.back * 90); //z축으로 90도
            rigid.velocity = new Vector2(enemyLogic.speed * (-1), -1);
        }else if(ranPoint == 7 || ranPoint == 8)
        {
            enemy.transform.Rotate(Vector3.forward * 90); //z축으로 90도
            rigid.velocity = new Vector2(enemyLogic.speed, -1);
        }
        else
        {
            rigid.velocity = new Vector2(0, enemyLogic.speed * (-1));
        }
    }
    public void RespawnPlayer()
    {
        Invoke("RespawnPlayerExe", 2f);
        
    }
    private void RespawnPlayerExe()
    {
        player.transform.position = Vector3.down * 3.5f;
        player.SetActive(true);
    }
}

'산대특' 카테고리의 다른 글

2D Airplane - 원근감있는 무한 배경 만들  (0) 2024.03.17
2D Airplane - 5  (1) 2024.03.14
2D Airplane - 3  (0) 2024.03.12
2D Airplane - 2  (0) 2024.03.10
2D Airplane - 1  (0) 2024.03.09

+ Recent posts