EasyCastleUNITY

바구니로 떨어지는 사과 받기 본문

유니티 기초

바구니로 떨어지는 사과 받기

EasyCastleT 2023. 8. 7. 12:03

0.조명 조정

빛에 대한 정보를 저장하는 파일 생성

1. 바구니 이동(Ray를 활용)

기본화면

BasketController

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

public class BasketController : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        //마우스 왼쪽 클릭 하면 (화면을 클릭하면) Ray를 만들자
        if (Input.GetMouseButtonDown(0))
        {
            //화면상의 좌표-> Ray객체 생성
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            float maxDistance = 100f;
            //ray를 눈으로 확인 
            Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 1f);

            //ray와 collider의 충돌을 검사하는 메서드
            //out 매개변수를 사용하려면 변수정의를 먼저 해야 한다.
            RaycastHit hit;
            //out 키워드를 사용해서 인자로 넣어라
            //Raycast 메서드에서 연산된 결과를 hit 매개변수에 넣어줌 
            //Ray가 collider와 충돌하면 true, 아니면 false 
            if (Physics.Raycast(ray, out hit, maxDistance))
            {
                Debug.LogFormat("hit.point:{0}", hit.point);
                //클릭한 지점으로 바구니 위치 변경
                // this.transform.position = hit.point;
                //x좌표와 z좌표를 반올림 
                float x = Mathf.RoundToInt(hit.point.x);
                float z = Mathf.RoundToInt(hit.point.z);
                //새로운 좌표 생성
                this.transform.position = new Vector3(x, 0, z);
            }
        }
    }
}

바구니 이동

2. 아이템 생성(사과, 폭탄)

ItemGenerator 스크립트를 ItemGenerator에 할당, Prefab 2개도 할당

2-1. 아이템 이동

ItemController

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

public class ItemController : MonoBehaviour
{
    [SerializeField]
    private float moveSpeed = 1.0f;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //리지드바디가 없는 오브젝트의 이동
        //this.transform.Translate(방향 * 속도 * 시간)
        this.transform.Translate(Vector3.down*this.moveSpeed*Time.deltaTime);
        //바닥에 도달하면 제거 
        if (this.transform.position.y <= 0)
        {
            Destroy(this.gameObject);
        }
    }
}

2-2. 아이템 생성

ItemGenerator

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

public class ItemGenerator : MonoBehaviour
{
    private float elasedTime; //경과시간
    private float spawnTime = 1f; //1초에 한번씩
    public GameObject applePrefab;
    public GameObject bombPrefab;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //시간 측정하기
        //변수에 Time.deltaTime을 더해라 
        this.elasedTime += Time.deltaTime;
        //1초가 지났다면
        if(this.elasedTime >= this.spawnTime)
        {
            //아이템을 생성
            this.CreateItem();
            //시간 초기화 
            this.elasedTime = 0;
        }
    }
    private void CreateItem()
    {
        //사과 또는 폭탄
        int rand = Random.Range(1, 11); //1~10
        GameObject itemGo = null;
        if(rand > 2) // 3,4,5,6,7,8,9,10
        {
            //사과
            itemGo= Instantiate(this.applePrefab);
        }
        else // 1,2  20%로 폭탄 생성
        {
            //폭탄
            itemGo = Instantiate(this.bombPrefab);
        }
        //위치 설정
        //x: -1, 1
        //z: -1, 1
        int x =Random.Range(-1, 2); 
        int z =Random.Range(-1, 2);
        //위치를 설정
        itemGo.transform.position = new Vector3(x, 5.0f, z);
    }

}

아이템 생성 및 떨어짐

3. 아이템과 바구니 충돌 및 소리 재생

바구니 설정

아이템 설정

3-2. 충돌 연산

3-3. 전체적인 코드

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

public class BasketController : MonoBehaviour
{
    private AudioSource audioSource;
    public AudioClip appleSfx;
    public AudioClip bombSfx;
    // Start is called before the first frame update
    void Start()
    {
        this.audioSource = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        //마우스 왼쪽 클릭 하면 (화면을 클릭하면) Ray를 만들자
        if (Input.GetMouseButtonDown(0))
        {
            //화면상의 좌표-> Ray객체 생성
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            float maxDistance = 100f;
            //ray를 눈으로 확인 
            Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 1f);

            //ray와 collider의 충돌을 검사하는 메서드
            //out 매개변수를 사용하려면 변수정의를 먼저 해야 한다.
            RaycastHit hit;
            //out 키워드를 사용해서 인자로 넣어라
            //Raycast 메서드에서 연산된 결과를 hit 매개변수에 넣어줌 
            //Ray가 collider와 충돌하면 true, 아니면 false 
            if (Physics.Raycast(ray, out hit, maxDistance))
            {
                Debug.LogFormat("hit.point:{0}", hit.point);
                //클릭한 지점으로 바구니 위치 변경
                // this.transform.position = hit.point;
                //x좌표와 z좌표를 반올림 
                float x = Mathf.RoundToInt(hit.point.x);
                float z = Mathf.RoundToInt(hit.point.z);
                //새로운 좌표 생성
                this.transform.position = new Vector3(x, 0, z);
            }
        }
    }
    //충돌 연산
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log(other.tag);

        if(other.tag == "Apple")
        {
            Debug.Log("득점");
            this.audioSource.PlayOneShot(this.appleSfx);
        }
        else if(other.tag == "Bomb")
        {
            Debug.Log("감점");
            this.audioSource.PlayOneShot(this.bombSfx);

        }
        Destroy(other.gameObject); //사과 또는 폭탄을 제거 
    }
}

4. 최종완성

BasketController

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

public class BasketController : MonoBehaviour
{
    private AudioSource audioSource;
    [SerializeField]
    private AudioClip appleSfx;
    [SerializeField]
    private AudioClip bombSfx;
    [SerializeField]
    private GameDirector gameDirector;
    // Start is called before the first frame update
    void Start()
    {
        this.audioSource = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        //마우스 왼쪽 클릭 하면 (화면을 클릭하면) Ray를 만들자
        if (Input.GetMouseButtonDown(0))
        {
            //화면상의 좌표-> Ray객체 생성
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            float maxDistance = 100f;
            //ray를 눈으로 확인 
            Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 1f);

            //ray와 collider의 충돌을 검사하는 메서드
            //out 매개변수를 사용하려면 변수정의를 먼저 해야 한다.
            RaycastHit hit;
            //out 키워드를 사용해서 인자로 넣어라
            //Raycast 메서드에서 연산된 결과를 hit 매개변수에 넣어줌 
            //Ray가 collider와 충돌하면 true, 아니면 false 
            if (Physics.Raycast(ray, out hit, maxDistance))
            {
                Debug.LogFormat("hit.point:{0}", hit.point);
                //클릭한 지점으로 바구니 위치 변경
                // this.transform.position = hit.point;
                //x좌표와 z좌표를 반올림 
                float x = Mathf.RoundToInt(hit.point.x);
                float z = Mathf.RoundToInt(hit.point.z);
                //새로운 좌표 생성
                this.transform.position = new Vector3(x, 0, z);
            }
        }
    }
    //충돌 연산
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log(other.tag);

        if(other.tag == "Apple")
        {
            Debug.Log("득점");
            this.audioSource.PlayOneShot(this.appleSfx);
            this.gameDirector.IncreaseScore(100);
        }
        else if(other.tag == "Bomb")
        {
            Debug.Log("감점");
            this.audioSource.PlayOneShot(this.bombSfx);
            this.gameDirector.DecreaseScore(50);
        }
        this.gameDirector.UpdateScoreUI();
        Destroy(other.gameObject); //사과 또는 폭탄을 제거 
    }
}

ItemController

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

public class ItemController : MonoBehaviour
{
    [SerializeField]
    private float moveSpeed = 1.0f;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //리지드바디가 없는 오브젝트의 이동
        //this.transform.Translate(방향 * 속도 * 시간)
        this.transform.Translate(Vector3.down*this.moveSpeed*Time.deltaTime);
        //바닥에 도달하면 제거 
        if (this.transform.position.y <= 0)
        {
            Destroy(this.gameObject);
        }
    }
}

ItemGenerator

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

public class ItemGenerator : MonoBehaviour
{
    private float elasedTime; //경과시간
    private float spawnTime = 1f; //1초에 한번씩
    public GameObject applePrefab;
    public GameObject bombPrefab;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //시간 측정하기
        //변수에 Time.deltaTime을 더해라 
        this.elasedTime += Time.deltaTime;
        //1초가 지났다면
        if(this.elasedTime >= this.spawnTime)
        {
            //아이템을 생성
            this.CreateItem();
            //시간 초기화 
            this.elasedTime = 0;
        }
    }
    private void CreateItem()
    {
        //사과 또는 폭탄
        int rand = Random.Range(1, 11); //1~10
        GameObject itemGo = null;
        if(rand > 2) // 3,4,5,6,7,8,9,10
        {
            //사과
            itemGo= Instantiate(this.applePrefab);
        }
        else // 1,2  20%로 폭탄 생성
        {
            //폭탄
            itemGo = Instantiate(this.bombPrefab);
        }
        //위치 설정
        //x: -1, 1
        //z: -1, 1
        int x =Random.Range(-1, 2); 
        int z =Random.Range(-1, 2);
        //위치를 설정
        itemGo.transform.position = new Vector3(x, 5.0f, z);
    }

}

GameDirector

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SocialPlatforms.Impl;
using UnityEngine.UI;

public class GameDirector : MonoBehaviour
{
    [SerializeField]
    private Text txtTime;
    [SerializeField]
    private Text txtScore;

    private float time = 60.0f;
    private int score = 0;

    // Start is called before the first frame update
    void Start()
    {
        this.UpdateScoreUI();
    }

    public void UpdateScoreUI()
    {
        this.txtScore.text = string.Format("{0} Point", score);
    }


    public void IncreaseScore(int score)
    {
        this.score += score;
    }
    public void DecreaseScore(int score)
    {
        this.score -= score;
    }

    // Update is called once per frame
    void Update()
    {
        this.time -= Time.deltaTime;    //매프레임마다 감소된 시간을 표시
        //https://sosobaba.tistory.com/244 
        //https://chragu.com/entry/C-double-to-string
        this.txtTime.text = this.time.ToString("F1");   //소수점 1자리까지 표시
    }
}

완성