현재 테스트 광고 단위를 사용하는데

 

배너의 크기를 조절하던 중 오류가 났다.

 

분명 커스터마이징이 가능한 줄 알았는데 애드몹에서 지정된 사이즈로만

 

변경 할 수 있던 것이다.

 

본 프로젝트에는 크기에 맞춤을 적용하였다.

 

https://developers.google.com/admob/unity/banner?hl=ko

 

배너 광고  |  Unity  |  Google for Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 배너 광고 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 배너 보기는 화면 안의 한 지점을 차지하는

developers.google.com

using UnityEngine;
using GoogleMobileAds.Api;
using System;
using System.Drawing;

public class BannerManager : MonoBehaviour
{
    public static BannerManager instance;
    public static BannerManager Instance
    {
        get
        {
            // Singleton 패턴을 이용하여 단일 인스턴스 반환
            if (instance == null)
            {
                instance = FindObjectOfType<BannerManager>();
                if (instance == null)
                {
                    GameObject adMobManagerGO = new GameObject();
                    instance = adMobManagerGO.AddComponent<BannerManager>();
                    adMobManagerGO.name = "AdMobManager";
                    DontDestroyOnLoad(adMobManagerGO);
                }
            }
            return instance;
        }
    }

    public string _adUnitId;

    // 광고 뷰 객체
    BannerView _bannerView;

    public void Awake()
    {
        // 싱글톤 인스턴스 설정
        if (instance == null)
        {
            instance = this as BannerManager;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public void Start()
    {
        //// Google Mobile Ads SDK 초기화
        MobileAds.Initialize((InitializationStatus initStatus) =>
        {
            // SDK 초기화 콜백
            Debug.Log("Google Mobile Ads SDK initialized.");
            // 광고 뷰 생성
            //_bannerView = new BannerView(_adUnitId, AdSize.Banner, AdPosition.Bottom);


            //AdSize adSize = new AdSize(350, 50);

            //_bannerView = new BannerView(_adUnitId, adSize, AdPosition.Bottom);

            CreateBannerView();

            ListenToAdEvents();
        });


        //CreateBannerView();

#if UNITY_ANDROID
        _adUnitId = "ca-app-pub-3940256099942544/6300978111"; // 안드로이드 테스트 광고 단위 ID
#elif UNITY_IPHONE
        _adUnitId = "ca-app-pub-3940256099942544/2934735716"; // iOS 테스트 광고 단위 ID
#else
        _adUnitId = "unused"; // 기타 플랫폼 또는 테스트에 사용되지 않는 경우
#endif
    }

    public void CreateBannerView()
    {
        Debug.Log("Creating banner view");

        // 기존 배너 뷰가 있으면 제거
        //if (_bannerView != null)
        //{
        //    _bannerView.Destroy();
        //}

        // Use the AdSize argument to set a custom size for the ad.
        AdSize adSize = AdSize.GetCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(AdSize.FullWidth);


        //_bannerView = new BannerView(_adUnitId, adSize, AdPosition.Bottom);
        _bannerView = new BannerView(_adUnitId, adSize, AdPosition.Bottom);
       
        ListenToAdEvents();
    }/// <summary>
     /// Creates the banner view and loads a banner ad.
     /// </summary>
    public void LoadAd()
    {
        // create an instance of a banner view first.
        if (_bannerView == null)
        {
            CreateBannerView();
        }

        // create our request used to load the ad.
        var adRequest = new AdRequest();

        // send the request to load the ad.
        Debug.Log("Loading banner ad.");
        _bannerView.LoadAd(adRequest);
    }
    /// <summary>
    /// listen to events the banner view may raise.
    /// </summary>
    public void ListenToAdEvents()
    {
        // Raised when an ad is loaded into the banner view.
        _bannerView.OnBannerAdLoaded += () =>
        {
            Debug.Log("Banner view loaded an ad with response : "
                + _bannerView.GetResponseInfo());
        };
        // Raised when an ad fails to load into the banner view.
        _bannerView.OnBannerAdLoadFailed += (LoadAdError error) =>
        {
            Debug.LogError("Banner view failed to load an ad with error : "
                + error);
        };
        // Raised when the ad is estimated to have earned money.
        _bannerView.OnAdPaid += (AdValue adValue) =>
        {
            Debug.Log(String.Format("Banner view paid {0} {1}.",
                adValue.Value,
                adValue.CurrencyCode));
        };
        // Raised when an impression is recorded for an ad.
        _bannerView.OnAdImpressionRecorded += () =>
        {
            Debug.Log("Banner view recorded an impression.");
        };
        // Raised when a click is recorded for an ad.
        _bannerView.OnAdClicked += () =>
        {
            Debug.Log("Banner view was clicked.");
        };
        // Raised when an ad opened full screen content.
        _bannerView.OnAdFullScreenContentOpened += () =>
        {
            Debug.Log("Banner view full screen content opened.");
        };
        // Raised when the ad closed full screen content.
        _bannerView.OnAdFullScreenContentClosed += () =>
        {
            Debug.Log("Banner view full screen content closed.");
        };
    }/// <summary>
     /// Destroys the banner view.
     /// </summary>
    public void DestroyAd()
    {
        if (_bannerView != null)
        {
            Debug.Log("Destroying banner view.");
            _bannerView.Destroy();
            _bannerView = null;
        }
    }
}

 

using UnityEngine;
using Firebase.Analytics;

public class AdManager : MonoBehaviour
{
    private static AdManager instance;

    public static AdManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<AdManager>();
                if (instance == null)
                {
                    GameObject adManagerGO = new GameObject();
                    instance = adManagerGO.AddComponent<AdManager>();
                    adManagerGO.name = "AdManager";
                    DontDestroyOnLoad(adManagerGO);
                }
            }
            return instance;
        }
    }

    private void Awake()
    {
        if (instance == null)
        {
            instance = this as AdManager;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public void Start()
    {
        // Initialize Firebase Analytics
        FirebaseAnalytics.SetAnalyticsCollectionEnabled(true);
        FirebaseAnalytics.LogEvent(FirebaseAnalytics.EventAppOpen);
        BannerManager.Instance.LoadAd();
    }

    public void ShowInterstitialAd()
    {
        // Show interstitial ad logic here
        // For example, assuming _interstitialAd is an instance of your interstitial ad
        // and it's shown successfully, log the event
        LogInterstitialAdShownEvent();
    }

    private void LogInterstitialAdShownEvent()
    {
        // Log an event indicating the interstitial ad was shown
        FirebaseAnalytics.LogEvent("interstitial_ad_shown");
    }
}

해야 할 것

스크립트를 하나로 합쳤는데

2개 클릭 시 다시 다른 버튼 클릭을 막으려다

현재 클릭된 버튼도 클릭이 막힌 상태

클릭이 된 2개를 기준으로 클릭을 해제하면 다른 것을 클릭할 수 있도록 수정하기

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
using UnityEngine.U2D;
using UnityEditor;

public class SelectSkillPopUp : MonoBehaviour
{
    public GameObject[] selectSkills;
    public Image[] skillImgs;
    public TMP_Text[] skillIds;
    public TMP_Text[] skillNames;
    public TMP_Text[] skillDescs;

    public Button shuffleSkills;
    public Button selectBtn;
    public SpriteAtlas skillsAtlas;
    List<SkillData> skillList = new List<SkillData>();

    private int selectedCount = 0;
    private List<int> selectedIndexes = new List<int>();

    void Start()
    {
        selectBtn.gameObject.SetActive(false);
        ShowLevelUp();

        foreach (var data in SkillManager.instance.skillDatas)
        {
            skillList.Add(data);
        }
        shuffleSkills.onClick.AddListener(ShuffleSkills);

        // 각 스킬 오브젝트에 대해 클릭 이벤트 추가
        for (int i = 0; i < selectSkills.Length; i++)
        {
            int index = i;
            selectSkills[i].GetComponent<Button>().onClick.AddListener(() =>
            {
                ToggleSkill(index);
            });
        }
    }

    void ShowLevelUp()
    {
        selectedIndexes.Clear();

        for (int i = 0; i < skillImgs.Length; i++)
        {
            int randomIndex = SkillManager.instance.GetSkillsRandomNum();
            selectedIndexes.Add(randomIndex);

            skillImgs[i].sprite = SkillManager.instance.GetRandomAtlasImg(randomIndex);
            skillIds[i].text = SkillManager.instance.GetRandomAtlasImgId(randomIndex).ToString();
            skillNames[i].text = SkillManager.instance.GetRandomAtlasName(randomIndex);
            skillDescs[i].text = SkillManager.instance.GetRandomAtlasDesc(randomIndex);
        }
    }

    void ShuffleSkills()
    {
        selectedCount = 0;

        for (int i = 0; i < skillImgs.Length; i++)
        {
            int randomIndex = GetUniqueRandomIndex();
            selectedIndexes[i] = randomIndex;

            skillIds[i].text = SkillManager.instance.GetRandomAtlasImgId(randomIndex).ToString();
            skillNames[i].text = SkillManager.instance.GetRandomAtlasName(randomIndex);
            skillDescs[i].text = SkillManager.instance.GetRandomAtlasDesc(randomIndex);
            skillImgs[i].sprite = SkillManager.instance.GetRandomAtlasImg(randomIndex);
            SetImageAlpha(skillImgs[i], 1f); // 알파 값을 원래대로 초기화
        }

        UpdateSelectBtn();
    }

    int GetUniqueRandomIndex()
    {
        int randomIndex;
        do
        {
            randomIndex = Random.Range(0, skillList.Count);
        } while (selectedIndexes.Contains(randomIndex));

        return randomIndex;
    }

    void SetImageAlpha(Image image, float alpha)
    {
        Color color = image.color;
        color.a = alpha;
        image.color = color;
    }

    void UpdateSelectBtn()
    {
        selectBtn.gameObject.SetActive(selectedCount == 2);
    }

    public void ToggleSkill(int index)
    {
        if (selectedCount >= 2)
        {
            // 이미 2개의 스킬이 선택되었으므로 다른 스킬 선택을 막음
            return;
        }

        Image skillImage = skillImgs[index].GetComponent<Image>();
        if (GetImageAlpha(skillImage) != 65f / 255f)
        {
            SetImageAlpha(skillImage, 65f / 255f);
            selectedCount++;
        }
        else
        {
            SetImageAlpha(skillImage, 1f);
            selectedCount--;
        }

        UpdateSelectBtn();
    }

    float GetImageAlpha(Image image)
    {
        return image.color.a;
    }
}

 

using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;
using UnityEngine.UI;

public class SkillManager : MonoBehaviour
{
    public static SkillManager instance; // 싱글톤

    public SpriteAtlas skillsAtlas;
    public Button levelUpBtn;
    public Button closeBtn;
    public GameObject selectSkillPopUp;
    public SkillData[] skillDatas;
    private List<int> rememberRandomIndex = new List<int>();

    private void Awake() // 싱글톤
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else if (instance != this)
        {
            Destroy(gameObject);
        }
    }

    public void Start()
    {
        levelUpBtn.onClick.RemoveAllListeners();
        OnClickLevelUpBtn();
        OnClickCloseBtn();
        TextAsset asset = Resources.Load<TextAsset>("data/skills_data");
        string json = asset.text;

        skillDatas = JsonConvert.DeserializeObject<SkillData[]>(json);
    }

    public SkillData GetDataById(int id)
    {
        SkillData foundSkillData = null;
        foreach (SkillData skillData in skillDatas)
        {
            if (skillData.id == id)
            {
                foundSkillData = skillData;
                break;
            }
        }
        return foundSkillData;
    }

    public int GetRandomAtlasImgId(int randomIndex)
    {
        return skillDatas[randomIndex].id;
    }

    public string GetRandomAtlasName(int randomIndex)
    {
        return skillDatas[randomIndex].name;
    }

    public string GetRandomAtlasDesc(int randomIndex)
    {
        return skillDatas[randomIndex].desc;
    }

    public Sprite GetRandomAtlasImg(int randomIndex)
    {
        return skillsAtlas.GetSprite(skillDatas[randomIndex].name);
    }

    public int GetSkillsRandomNum()
    {
        int randomIndex;
        do
        {
            randomIndex = Random.Range(0, skillDatas.Length);
        } while (rememberRandomIndex.Contains(randomIndex));

        rememberRandomIndex.Add(randomIndex);

        Debug.Log("랜덤으로 선택된 스킬 인덱스: " + randomIndex);
        return randomIndex;
    }

    public void OnClickLevelUpBtn()
    {
        levelUpBtn.onClick.AddListener(() =>
        {
            selectSkillPopUp.SetActive(true);

            int randomIndex = GetSkillsRandomNum();

            GetRandomAtlasImg(randomIndex);
            GetRandomAtlasName(randomIndex);
            GetRandomAtlasDesc(randomIndex);
        });
    }

    public void OnClickCloseBtn()
    {
        closeBtn.onClick.AddListener(() =>
        {
            selectSkillPopUp.SetActive(false);
        });
    }
}

추가적으로 해야 할 것

유니티를 실행하다 꺼서 다시 시작할 필요 없이

버튼을 클릭 시 스킬이 다시 랜덤으로 생성되게

(이 부분을 계속 시도해보는데 초기화가 안됨)

(RemoveAllListener을 사용해봄)

+ 스킬 2개는 중복이 되면 안된다.

 

 

 

using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.U2D;
using UnityEngine.UI;

public class SkillManager : MonoBehaviour
{
    public static SkillManager instance; //싱글톤

    public SpriteAtlas skillsAtlas;
    public Button levelUpBtn;
    public Button closeBtn;
    public GameObject selectSkillPopUp;
    public SkillData[] skillDatas;
    private int randomSkillIndex;

    private void Awake() //싱글톤
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else if (instance != null)
        {
            Destroy(this.gameObject);
        }
    }

    // 비모노 일때
    //public static SkillManager Instance 
    //{
    //    get
    //    {
    //        if (null == instance)
    //        {
    //            return null;
    //        }
    //        return instance;
    //    }
    //}


    public void Start()
    {
        levelUpBtn.onClick.RemoveAllListeners();
        OnClickLevelUpBtn();
        OnClickCloseBtn();
        TextAsset asset = Resources.Load<TextAsset>("data/skills_data");
        string json = asset.text;

        Debug.Log(json);

        skillDatas = JsonConvert.DeserializeObject<SkillData[]>(json);
        foreach (SkillData data in skillDatas)
        {
            Debug.Log(data.id);
            //문자열 => 객체 (역직렬화) 각 객체를 돌며 id를 잘 찾는지 확인
        }
    }


    public SkillData GetDataById(int id)
    {
        SkillData foundSkillData = null;
        for (int i = 0; i < skillDatas.Length; i++)
        {
            SkillData skillData = this.skillDatas[i];
            if (skillData.id == id)
            {
                foundSkillData = skillData;
                break;
            }
        }
        return foundSkillData;
    }

    public int GetRandomAtlasImgId()
    {
        int id = skillDatas[randomSkillIndex].id;
        return id;
    }

    public string GetRandomAtlasName()
    {
        string name = skillDatas[randomSkillIndex].name;
        return name;
    }

    public string GetRandomAtlasDesc()
    {
        string desc = skillDatas[randomSkillIndex].desc;
        return desc;
    }


    public Sprite GetRandomAtlasImg()
    {
        //랜덤으로 얻은 배열인 인덱스의 이미지 이름
        Sprite skillSprite = skillsAtlas.GetSprite(skillDatas[randomSkillIndex].name);
        return skillSprite;
    }

    public void GetSkillsRandomNum()
    {
        randomSkillIndex = Random.Range(0, skillDatas.Length);
        //스킬데이터의 인덱스번호로 랜덤하게 출력
        //Debug.Log(randomSkillIndex); 


    }

    public void OnClickLevelUpBtn()
    {
        levelUpBtn.onClick.AddListener(() =>
            {
                selectSkillPopUp.SetActive(true);

                GetSkillsRandomNum();

                GetRandomAtlasImg();
                GetRandomAtlasName();
                GetRandomAtlasDesc();
            });
    }



    public void OnClickCloseBtn()
    {
        closeBtn.onClick.AddListener(() =>
        {
            selectSkillPopUp.SetActive(false);
        });
    }





}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
public class SelectSkillPopUp : MonoBehaviour
{
    public Image skillImg1;
    public TMP_Text skillId1;
    public TMP_Text skillName1;
    public TMP_Text skillDesc1;


    public Image skillImg2;
    public TMP_Text skillId2;
    public TMP_Text skillName2;
    public TMP_Text skillDesc2;


    public Button shuffleSkills;


   
    void Start()
    {

        shuffleSkills.onClick.AddListener(() =>
        {
            Debug.Log("클릭");

            SkillManager.instance.OnClickLevelUpBtn();
        });
        ////skillId1.text = SkillManager.instance.GetDataById(105).id.ToString();
        ////skillId2.text = SkillManager.instance.GetDataById(104).id.ToString();

        //skillImg1.sprite = SkillManager.instance.GetRandomAtlasImg();
        //skillImg2.sprite = SkillManager.instance.GetRandomAtlasImg();
        ////skillId1.text = SkillManager.instance.GetDataById().id.ToString();
        //skillId1.text = SkillManager.instance.GetRandomAtlasImgId().ToString();
        //skillId2.text = SkillManager.instance.GetRandomAtlasImgId().ToString();



        skillImg1.sprite = SkillManager.instance.GetRandomAtlasImg();
        skillId1.text = SkillManager.instance.GetRandomAtlasImgId().ToString();
        skillName1.text = SkillManager.instance.GetRandomAtlasName().ToString();
        skillDesc1.text = SkillManager.instance.GetRandomAtlasDesc().ToString();


        SkillManager.instance.GetSkillsRandomNum();

        
        skillImg2.sprite = SkillManager.instance.GetRandomAtlasImg();
        skillId2.text = SkillManager.instance.GetRandomAtlasImgId().ToString();
        skillName2.text = SkillManager.instance.GetRandomAtlasName().ToString();
        skillDesc2.text = SkillManager.instance.GetRandomAtlasDesc().ToString();
    }

}

Panel을 UI로 만든후 시점이 맞았을때

패널을 보이게 하고 그렇지 않을 경우 보이지 않게 한다.

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem.LowLevel;

public class Car : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IGvrPointerHoverHandler
{
    private Coroutine coroutine;
    public GameObject menuUI;
    public void OnGvrPointerHover(PointerEventData eventData)
    {
        //Debug.Log("Hover");
    }


    public void OnPointerEnter(PointerEventData eventData)
    {
        coroutine = StartCoroutine(CoClick());
        Debug.Log("Enter");
        menuUI.SetActive(true);

    }


    private IEnumerator CoClick()
    {
        float delta = 0f;
        while (true)
        {
            delta += Time.deltaTime;
            if(delta >= 3)
            {
                Debug.LogFormat("Clicked , {0}", delta);
                delta = 0f;
            }
            yield return null;
        }
    }
    public void OnPointerExit(PointerEventData eventData)
    {
        Debug.Log("Exit");
        menuUI.SetActive(false);
        StopCoroutine(coroutine);
    }
}

 

 

플레이어의 위치에 따라서 패널의 방향이 변경되는데

이는 캔버스안에 넣어주어야 한다.

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

public class Billboard : MonoBehaviour
{
    

    // Update is called once per frame
    void Update()
    {
        this.transform.LookAt(Camera.main.transform.position);
    }
}

 

 

 

 

IPointerEnterHandler, IPointerExitHandler는 유니티엔진에 있는 메소드이지만,

IGvrPointerHoverHandler는 직접 만들어준 메소드이다.

 


 

커스텀 래티클 만들기

 

이번엔 기존에 사용했던 빨간색 래티클을 없애고 새로운 래티클을 만들어 주려 한다.

 

Main Camera의 GvrRecticlePointer와 GvrPointerPhysicsRaycast를 비활성화  한다.

 

Main Camera자식으로 Canvas를 생성하고  다음과  같이  속성을  변경  한다

 

 

그리고 적절한 이미지를 붙여준 후 Fill효과를 넣어줄 것이므로

복사해서 앞과 뒤를 만든다.

Back은 알파 값을 조금 줄여주고

Front는 filled, Radial 360, Top으로 변경하였다.

 

우선 래티클이 변경되었으니 인지를 하게 만드는 것이 우선인데

차의 레이어는 7 메뉴의 레이어는 6으로 만들어서

인지할수 있도록 하였다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem.LowLevel;

public class Car : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IGvrPointerHoverHandler
{
    private static Car instance;
    private Coroutine coroutine;
    public GameObject menuUI;

    private void Start()
    {
        //menuUI.SetActive(false);
    }

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else
        {
            Debug.LogWarning("Duplicate instance of Car found!");
            Destroy(gameObject); // 중복된 인스턴스 제거
        }
    }

    public static Car GetInstance()
    {
        return instance;
    }



    public void OnGvrPointerHover(PointerEventData eventData)
    {
        //Debug.Log("Hover");
    }


    public void OnPointerEnter(PointerEventData eventData)
    {
        coroutine = StartCoroutine(CoClick());
        Debug.Log("Enter");
        menuUI.SetActive(true);
        Debug.Log("이벤트 대상: " + eventData.pointerEnter.name);
    }


    private IEnumerator CoClick()
    {
        float delta = 0f;
        while (true)
        {
            delta += Time.deltaTime;
            if(delta >= 3)
            {
                Debug.LogFormat("Clicked , {0}", delta);
                delta = 0f;
            }
            yield return null;
        }
    }
    public void OnPointerExit(PointerEventData eventData)
    {
        Debug.Log("Exit");
        menuUI.SetActive(false);
        StopCoroutine(coroutine);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class EyeCast : MonoBehaviour
{
    private Transform trans;
    private Ray ray;
    private RaycastHit hit;
    public float dist = 10f;
    public Image gauge;
    bool isOpenedUIMenu = false;
    private Car carInstance; // 전역 변수로 선언

    void Start()
    {
        this.trans = this.GetComponent<Transform>();
        carInstance = Car.GetInstance(); // 전역 변수에 할당
        carInstance.menuUI.SetActive(false);
    }

    void Update()
    {
        ray = new Ray(this.trans.position, this.trans.forward);
        Debug.DrawRay(ray.origin, ray.direction * this.dist, Color.green);

        var mask = 1 << 6 | 1 << 7; // 레이어 마스크 설정
        if (Physics.Raycast(ray, out hit, dist, mask))
        {
            this.GazeButton();
        }
        else
        {
            ReleaseButton();
            // 여기에서 메뉴 닫는 동작을 추가할 수 있습니다.
            // 예: carInstance.menuUI.SetActive(false);
        }
    }

    private void GazeButton()
    {
        if (this.hit.collider.gameObject.layer == 7 && carInstance != null)
        {
            carInstance.menuUI.SetActive(true);
        }
    }

    private void ReleaseButton()
    {
        if (this.hit.collider == null || this.hit.collider.gameObject == null)
        {
            carInstance.menuUI.SetActive(false);
        }
    }
}

 

보기와 같이 코드에서 차뿐만이 아닌 버튼에도 레이어를 설정해두었기 때문에

버튼쪽에 래티클을 갖다 두어도 창이 사라지지 않는다.

 

레이어를 인식해서 게이지를 채우고

나갔을 때 초기화

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class EyeCast : MonoBehaviour
{
    private Transform trans;
    private Ray ray;
    private RaycastHit hit;
    public float dist = 10f;
    public Image gauge;
    bool isOpenedUIMenu = false;
    private Car carInstance; // 전역 변수로 선언
    private float delta;

    void Start()
    {
        this.trans = this.GetComponent<Transform>();
        carInstance = Car.GetInstance(); // 전역 변수에 할당
        carInstance.menuUI.SetActive(false);
    }

    void Update()
    {
        ray = new Ray(this.trans.position, this.trans.forward);
        Debug.DrawRay(ray.origin, ray.direction * this.dist, Color.green);

        var mask = 1 << 6 | 1 << 7; // 레이어 마스크 설정
        if (Physics.Raycast(ray, out hit, dist, mask))
        { 
            //gauge.fillAmount = 0;
            StartCoroutine(GazeButton());
        }
        else
        {
            delta = 0;
            gauge.fillAmount = 0;

            StartCoroutine(ReleaseButton());
           

            // 여기에서 메뉴 닫는 동작을 추가할 수 있습니다.
            // 예: carInstance.menuUI.SetActive(false);
        }
    }
    IEnumerator GazeButton()
    {
        
        if (this.hit.collider.gameObject.layer == 7 && carInstance != null)
        {
            carInstance.menuUI.SetActive(true);

            this.delta += Time.deltaTime;
            gauge.fillAmount = delta / 3;
        }
        else
        {

        }
        yield return null;
    }

    IEnumerator ReleaseButton()
    {
        if (this.hit.collider == null || this.hit.collider.gameObject == null)
        {

            carInstance.menuUI.SetActive(false);


        }
        yield return null;
    }
}

 

 

게이지를 채워서 예를 누르면 예가 찍히고

아니요를 누르면 창을 종료 시켰다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class EyeCast : MonoBehaviour
{
    private Transform trans;
    private Ray ray;
    private RaycastHit hit;
    public float dist = 10f;
    public Image gauge;
    private Car carInstance; // 전역 변수로 선언
    private float delta;
    public Button clickYes;
    public Button clickNo;
    private bool isYesClicked = false;
    private Coroutine coroutine;

    void Start()
    {
        this.trans = this.GetComponent<Transform>();
        carInstance = Car.GetInstance(); // 전역 변수에 할당
        carInstance.menuUI.SetActive(false);
    }

    void Update()
    {
        

        ray = new Ray(this.trans.position, this.trans.forward);
        Debug.DrawRay(ray.origin, ray.direction * this.dist, Color.green);

        var mask = 1 << 7; // 레이어 마스크 설정
        if (Physics.Raycast(ray, out hit, dist, mask))
        {
            //gauge.fillAmount = 0;
            
              if(coroutine != null)
            {
                StopCoroutine(coroutine);

            }

            StartCoroutine(GazeButton());

        }
       

        else if (Physics.Raycast(ray, out hit, dist, 1 << 6))
        {
            //gauge.fillAmount = 0;
            //StartCoroutine(GazeButton());
       
         
              
                StartCoroutine(GazeButton());
                StartCoroutine(ClickButton());

          
           
        }

        else
        {
            if (isYesClicked == true)
            {
                isYesClicked = false;
            }
            delta = 0;
            gauge.fillAmount = 0;

            StartCoroutine(ReleaseButton());


            // 여기에서 메뉴 닫는 동작을 추가할 수 있습니다.
            // 예: carInstance.menuUI.SetActive(false);
        }
    }
    IEnumerator GazeButton()
    {

        if (this.hit.collider.gameObject.layer == 7 || this.hit.collider.gameObject.layer == 6 && carInstance != null)
        {
            carInstance.menuUI.SetActive(true);

            this.delta += Time.deltaTime;
            gauge.fillAmount = delta / 2;
        }
        else
        {
            delta = 0;
            gauge.fillAmount = 0;
        }
        yield return null;
    }

    IEnumerator ClickButton()
    {
        if (this.hit.collider.gameObject.layer == 6)
        {
            this.delta += Time.deltaTime;
            if (gauge.fillAmount >= 1)
            {
                if (hit.collider.gameObject.name == "ButtonYes" && isYesClicked == false)
                {
                    isYesClicked = true;
                    Debug.Log("예를 입력하였습니다");
                }
                if (hit.collider.gameObject.name == "ButtonNo")
                {
                    carInstance.menuUI.SetActive(false);
                }
            }
        }
        yield return null;
    }


    IEnumerator ReleaseButton()
    {
        if (this.hit.collider == null || this.hit.collider.gameObject == null)
        {
            carInstance.menuUI.SetActive(false);
        }
        yield return null;
    }
}

 

 

 

마지막으로 레이어 이동시 게이지를 초기화 시키도록 구현하기 위해 수정을 하였다.

using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class EyeCast : MonoBehaviour
{
    private Transform trans;
    private RaycastHit hit;
    public float dist = 10f;
    public Image gauge;
    public Car car;
    public Button clickYes;
    public Button clickNo;

    private int lastLayer = 0;
    private string lastButton = "";

    float carCount = 0;
    float yesButtonCount = 0;
    float noButtonCount = 0;


    void Start()
    {
        this.trans = this.GetComponent<Transform>();
        car.menuUI.SetActive(false); // 처음엔 menu가 닫힌채로 시작

        StartCoroutine(ReleaseButton());
        StartCoroutine(GazeButton());
        StartCoroutine(ClickButton());
    }


    IEnumerator GazeButton()
    {
        while (true)
        {
            Ray ray = new Ray(this.trans.position, this.trans.forward);
            if (Physics.Raycast(ray, out hit, dist, 1 << 7)) // Layer 7 = Car
            {
                if (lastLayer != 7 && carCount < 2)
                {
                    carCount = 0;
                    gauge.fillAmount = 0;
                }
                else if (lastLayer != 7 && carCount >= 2)
                {
                    carCount = 2;
                    gauge.fillAmount = 1;
                }
                else if (lastLayer !=7 && carCount >= 2 && !car.menuUI.gameObject.activeSelf) // No 버튼으로 menu가 닫혔을때, 다시 초기화
                {
                    carCount = 0;
                    gauge.fillAmount = 0;
                }
                lastLayer = 7;
                lastButton = "";

                //car.menuUI.SetActive(true);  -> Car를 응시 했을 때, 바로 메뉴 오픈

                if (carCount < 2)
                {
                    carCount += Time.deltaTime;
                    gauge.fillAmount = carCount / 2;

                    if (gauge.fillAmount >= 1)
                    {
                        car.menuUI.SetActive(true); // -> Car를 응시 했을 때, 2초 후 메뉴 오픈
                    }
                }
            }
            yield return null;
        }
    }



    IEnumerator ClickButton()  // ButtonYes와 ButtonNo 콜라이더 사이에 공백이 있으면 ResetCountAndGauge 메서드(메뉴 닫힘 및 초기화)가 실행 될 수 있으니 유의
    {
        while (true)
        {
            Ray ray = new Ray(this.trans.position, this.trans.forward);
            if (Physics.Raycast(ray, out hit, dist, 1 << 6)) //Layer 6 = Button
            {
                if (hit.collider.gameObject.name == "ButtonYes")
                {
                    lastLayer = 6;

                    if (lastButton != "ButtonYes" && yesButtonCount < 2)
                    {
                        lastButton = "ButtonYes";
                        yesButtonCount = 0;
                        gauge.fillAmount = 0;
                    }
                    else if (lastButton != "ButtonYes" && yesButtonCount >= 2)
                    {
                        lastButton = "ButtonYes";
                        yesButtonCount = 2;
                        gauge.fillAmount = 1;
                    }
                    if (yesButtonCount < 2)
                    {
                        yesButtonCount += Time.deltaTime;
                        gauge.fillAmount = yesButtonCount / 2;

                        if (gauge.fillAmount >= 1)
                        {
                            Debug.Log("예를 입력하였습니다");
                            car.uiText.text = "차량 정보 확인"; // UI Text 변경
                        }
                    }
                }
                else if (hit.collider.gameObject.name == "ButtonNo")
                {
                    lastLayer = 6;

                    if (lastButton != "ButtonNo")
                    {
                        lastButton = "ButtonNo";
                        noButtonCount = 0;
                        gauge.fillAmount = 0;
                    }
                    if (noButtonCount < 2)
                    {
                        noButtonCount += Time.deltaTime;
                        gauge.fillAmount = noButtonCount / 2;

                        if (gauge.fillAmount >= 1)
                        {
                            car.menuUI.SetActive(false);

                            // Count 및 Text 초기화
                            car.uiText.text = "차량의 정보를 보시겠습니까?"; 
                            carCount = 0;
                            yesButtonCount = 0;
                            noButtonCount = 0;
                            Debug.Log("아니오를 입력하였습니다. 메뉴를 종료합니다.");
                        }
                    }
                }
            }
            yield return null;
        }
    }


    IEnumerator ReleaseButton()
    {
        while (true)
        {
            Ray ray = new Ray(this.trans.position, this.trans.forward);
            if (!Physics.Raycast(ray, out hit, dist))
            {
                //car.menuUI.SetActive(false); -> Car, 버튼 어느것도 응시하지 않으면 menu 닫음
                gauge.fillAmount = 1;
                lastLayer = 0;
                lastButton = "";
            }
            yield return null;
        }
    }





}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.UI;
using TMPro;

public class Car : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IGvrPointerHoverHandler
{

    private Coroutine coroutine;
    public GameObject menuUI;
    public Text uiText; // menuUI Text

    private void Start()
    {
        //menuUI.SetActive(false);
    }



    public void OnGvrPointerHover(PointerEventData eventData)
    {
        //Debug.Log("Hover");
    }


    public void OnPointerEnter(PointerEventData eventData)
    {
        //coroutine = StartCoroutine(CoClick());
        //Debug.Log("Enter");
        ////menuUI.SetActive(true);
        //Debug.Log("이벤트 대상: " + eventData.pointerEnter.name);
    }


    private IEnumerator CoClick()
    {
        float delta = 0f;
        while (true)
        {
            delta += Time.deltaTime;
            if(delta >= 3)
            {
                Debug.LogFormat("Clicked , {0}", delta);
                delta = 0f;
            }
            yield return null;
        }
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        //Debug.Log("Exit");
        //menuUI.SetActive(false);
        //StopCoroutine(coroutine);
    }
}

+ Recent posts