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

public class ActiveCard : MonoBehaviour
{
    public GameObject cardPrefab; // 인스펙터에서 프리팹을 할당하세요
    public TMP_Text valueTextPrefab; // 인스펙터에서 텍스트 프리팹을 할당하세요
    public Transform parentTransform; // 인스펙터에서 부모 변환을 할당하세요

    void Start()
    {
        PlayerManager.Instance.LoadPlayerCardData();
        PlayerManager.Instance.LoadPlayerCardInfo();
        PlayerManager.Instance.LoadPlayerCardInfoListData();

        foreach (var playerActiveCardInfo in PlayerManager.Instance.dicPlayerCardInfoList)
        {
            Debug.Log("버튼이 눌림");

            // 프리팹에서 새 카드 오브젝트를 복제합니다.
            GameObject newCard = Instantiate(cardPrefab, parentTransform);

            // 카드의 자식 오브젝트로서 새로운 TMP_Text를 생성합니다.
            TMP_Text valueText = Instantiate(valueTextPrefab, newCard.transform);

            // 값을 설정합니다.
            valueText.text = playerActiveCardInfo.Value.value.ToString();

            Debug.Log(valueText.text);
        }

        Debug.Log("데이터 개수: " + PlayerManager.Instance.dicPlayerCardInfoList.Count);
    }
}

 

 

데이터 불러오기 

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

public class ActiveCard : MonoBehaviour
{
    public TMP_Text valueTextPrefab;
    public TMP_Text cardNamePrefab;
    public TMP_Text cardInfoPrefab;
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ActiveCardDecBtn : MonoBehaviour
{
    public Button btn;
    public GameObject ActiveCardInventory;

    public GameObject cardPrefab;
    public Transform parentTransform;
    void Start()
    {
        
            btn.onClick.AddListener(() =>
            {
                ActiveCardInventory.SetActive(true);
            });


        List<PlayerCardInfo> card = new List<PlayerCardInfo>(PlayerManager.Instance.dicPlayerCardInfo.Values);



        for (int i = 0; i < PlayerManager.Instance.dicPlayerCardInfoList.Count; i++)
        {
            Debug.Log("버튼이 눌림");

            // 프리팹에서 새 카드 오브젝트를 생성
            GameObject Card = Instantiate(cardPrefab, parentTransform);
            ActiveCard newCard = Card.GetComponent<ActiveCard>();


            // 값을 설정
            newCard.valueTextPrefab.text = card[i].value.ToString();

            newCard.cardNamePrefab.text = card[i].card_name;

            newCard.cardInfoPrefab.text = PlayerManager.Instance.dicPlayerCardDatas[card[i].card_original_id].desc;
        }

    }

    void Update()
    {

    }
}

https://github.com/Unity-Technologies/ml-agents/blob/develop/docs/Installation.md

 

ml-agents/docs/Installation.md at develop · Unity-Technologies/ml-agents

The Unity Machine Learning Agents Toolkit (ML-Agents) is an open-source project that enables games and simulations to serve as environments for training intelligent agents using deep reinforcement ...

github.com

 

https://github.com/adang1345/PythonWindows/blob/master/3.10.12/python-3.10.12-amd64-full.exe

 

PythonWindows/3.10.12/python-3.10.12-amd64-full.exe at master · adang1345/PythonWindows

Unofficial Python installers for Windows. Contribute to adang1345/PythonWindows development by creating an account on GitHub.

github.com

 

폴더를 만들어주고 결로를 지정해준다.

cmd를 켠 후 검색하면 찾을 수 있다.

pip3 install torch~=2.2.1 --index-url https://download.pytorch.org/whl/cu121

 

https://download.pytorch.org/whl/cu121

 

download.pytorch.org

pip install numpy==1.23.3

 

 

하지만 여기서 뒤에 더 추가해야 한다.

python -m pip install mlagents==1.0.0 --no-deps

 

git clone --branch release_21 https://github.com/Unity-Technologies/ml-agents.git

 

GitHub - Unity-Technologies/ml-agents: The Unity Machine Learning Agents Toolkit (ML-Agents) is an open-source project that enab

The Unity Machine Learning Agents Toolkit (ML-Agents) is an open-source project that enables games and simulations to serve as environments for training intelligent agents using deep reinforcement ...

github.com

 

 

소스트리를 활용하여 클론

 

유니티 허브에서 add를 한다.

 

패키지매니저를 열고 TextMeshPro를 설치하면 에러 2줄이 해결된다.

 

 

 

 

 

 

카드를 획득할 때 인벤토리에서 원하는 위치에서 생성되게 할 것이고,

하이어라이키 관점에서 봤을때는 부모와 같은 위치에서 생성되어야 Canvas 안에 적용이 될 것이다.

 

https://docs.unity3d.com/ScriptReference/Object.Instantiate.html

 

Unity - Scripting API: Object.Instantiate

This function makes a copy of an object in a similar way to the Duplicate command in the editor. If you are cloning a GameObject you can specify its position and rotation (these default to the original GameObject's position and rotation otherwise). If you

docs.unity3d.com

 

 

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

public class PreparedCard : MonoBehaviour
{
    private Button btn;
    private float spacing = 11.8f;

    void Start()
    {
        btn = GetComponent<Button>();

        btn.onClick.AddListener(() =>
        {
            Debug.Log("버튼이 눌림");

            // 새로운 오브젝트를 생성하고, 원본의 부모에 붙이기
            GameObject newObject = Instantiate(gameObject, transform.parent);

            // 새로운 오브젝트의 로컬 위치 조정
            newObject.transform.localPosition += new Vector3(spacing, 0, 0);
        });
    }
}

 

하지만 그리드 레이아웃을 설정할 때 이 spacing을 조절하였으므로

따로 spacing을 조절하지 않아도 되서 주석처리하였다.

 

시작을 하면 플레이어의 카드 인포를 찾아서 값을 가져올 수 있도록 변경

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

public class PreparedCard : MonoBehaviour
{
    private Button btn;
    //private float spacing = 11.8f;
    public TMP_Text value;

    void Start()
    {
        PlayerManager.Instance.LoadPreparedCardData();
        PlayerManager.Instance.LoadPreparedCardInfo();
        this.value.text = PlayerManager.Instance.dicPreparedCardInfo[2000].value.ToString();

        btn = GetComponent<Button>();

        btn.onClick.AddListener(() =>
        {
            Debug.Log("버튼이 눌림");

            // 새로운 오브젝트를 생성하고, 원본의 부모에 붙이기
            GameObject newObject = Instantiate(gameObject, transform.parent);

            // 새로운 오브젝트의 로컬 위치 조정
            //newObject.transform.localPosition += new Vector3(spacing, 0, 0);
            Debug.Log(value.text);

        });


    }

}

 

 

https://console.firebase.google.com/?hl=ko

 

로그인 - Google 계정

이메일 또는 휴대전화

accounts.google.com

 

 

다운로드 하면 이렇게 제이슨 파일이 만들어지고 이것을 프로젝트에 넣어주면 된다.

 

Firebase SDK도 설치

압축을 풀면 이렇게 생긴다.

여기서 필요한 것을 가져다가 쓰면 된다.

현재는 FirebaseDatabase를 사용할 것이다.

가장 가까운 싱가포르 선택

 

IOS Build 선택 후 다운로드

설치 후 다시 프로젝트로 들어간다.

 

창이 나오면 Yes만 클릭하면 된다.

 

이름으로 추가 를 선택 후

com.unity.nuget.newtonsoft-json를 넣는다.

 

스크립트 를 만든후 빈 오브젝트에 할당

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

public class DBManager : MonoBehaviour
{
    [SerializeField] private string databaseUrl;

    private void Start()
    {
       FirebaseApp.DefaultInstance.Options.DatabaseUrl
            = new System.Uri(databaseUrl);
    }

}

게임정보

유저 아이디

점수

GameInfo

userId

score

이 주소를 복사 한후

여기에 넣어주면 된다.

 

새 스크립트 생성 및 수정

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

public class GameMain : MonoBehaviour
{
    [SerializeField] private string userId;
    [SerializeField] private int score;

    void Start()
    {
        SaveGame();
    }

    public void SaveGame()
    {
        Debug.Log("SaveGame");

        GameInfo gameInfo = new GameInfo(userId, score);    //저장 객체 만들기 
        string json = JsonConvert.SerializeObject(gameInfo);  //직렬화 

        Debug.Log($"{json}");

        //저장 
        DBManager.instance.SaveData(json);
    }
}

 

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

public class GameInfo
{
    public string userId;
    public int score;

    //생성자 
    public GameInfo(string userId, int score) {
        this.userId = userId;
        this.score = score;
    }
}

 

using Firebase;
using Firebase.Database;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DBManager : MonoBehaviour
{
    [SerializeField] private string databaseUrl;

    public static DBManager instance;

    private void Awake()
    {
        instance = this;    //싱글톤 
    }

    void Start()
    {
        FirebaseApp.DefaultInstance.Options.DatabaseUrl
            = new System.Uri(databaseUrl);
    }

    public async void SaveData(string json)
    {
        Debug.Log("SaveData");

        //DB의 최상단 디렉토리를 참조 
        DatabaseReference dbRef = FirebaseDatabase.DefaultInstance.RootReference;

        Debug.Log($"dbRef: {dbRef}");

        //비동기 메서드때문에 완료 될때까지 대기
        await dbRef.SetRawJsonValueAsync(json);

        Debug.Log("데이터 저장 완료");
    }
}

 

------------------------- 오류가 계속 나서 다시 시작 ------------------------

이 세개를 빼고 library, obj 같이 생성시 생기는 파일들을 모두 삭제하였다.

Firebase 폴더가 삭제되지 않으면 오픈 윈도우로 들어가서 삭제해보고

그래도 관리자 권한때문에 삭제되지 않으면 재부팅하면 된다.

 

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

public class User
{
    public string username;
    public string email;

    public User()
    {
    }

    public User(string username, string email)
    {
        this.username = username;
        this.email = email;
    }
}

 

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

public class GameInfo
{
    public string userId;
    public int score;

    //생성자 
    public GameInfo(string userId, int score)
    {
        this.userId = userId;
        this.score = score;
    }
}

 

using Firebase.Database;
using Firebase.Extensions;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class GameMain : MonoBehaviour
{
    DatabaseReference mDatabaseRef;
    void Start()
    {
        Debug.Log($"Firebase.FirebaseApp.DefaultInstance: {Firebase.FirebaseApp.DefaultInstance}");
        // Get the root reference location of the database.

        mDatabaseRef = FirebaseDatabase.DefaultInstance.RootReference;

        Debug.Log($"reference : {mDatabaseRef}");

        writeNewUser("hong", "홍길동", "hong@gmail.com");


    }

    private void writeNewUser(string userId, string name, string email)
    {
        User user = new User(name, email);
        string json = JsonUtility.ToJson(user);

        mDatabaseRef.Child("Users").SetRawJsonValueAsync(json);
        CheckAndFixDependenciesAsync();
    }

    private void CheckAndFixDependenciesAsync()
    {
        Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => {
            var dependencyStatus = task.Result;
            if (dependencyStatus == Firebase.DependencyStatus.Available)
            {
                // Create and hold a reference to your FirebaseApp,
                // where app is a Firebase.FirebaseApp property of your application class.
                var app = Firebase.FirebaseApp.DefaultInstance;
                Debug.Log($"app : {app}");


                // Set a flag here to indicate whether Firebase is ready to use by your app.
            }
            else
            {
                UnityEngine.Debug.LogError(System.String.Format(
                  "Could not resolve all Firebase dependencies: {0}", dependencyStatus));
                // Firebase Unity SDK is not safe to use here.
            }
        });
    }

}

 

using Firebase;
using Firebase.Database;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DBManager : MonoBehaviour
{
    [SerializeField] private string databaseUrl;

    public static DBManager instance;

    private void Awake()
    {
        instance = this;    //싱글톤 
    }


    public void Init()
    {
        FirebaseApp.DefaultInstance.Options.DatabaseUrl
            = new System.Uri(databaseUrl);

        FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {

            FirebaseApp app = FirebaseApp.DefaultInstance;

            if (app != null)
            {
                Debug.Log("DefaultInstance를 찾을수 없습니다.");
            }
            else
            {
                Debug.Log("초기화가 정상적으로 되었습니다.");
            }
        });
    }

    public async void SaveData(string json)
    {
        Debug.Log("SaveData");

        //DB의 최상단 디렉토리를 참조 
        DatabaseReference dbRef = FirebaseDatabase.DefaultInstance.RootReference;

        Debug.Log($"dbRef: {dbRef}");

        //비동기 메서드때문에 완료 될때까지 대기
        await dbRef.SetRawJsonValueAsync(json);

        Debug.Log("데이터 저장 완료");
    }
}

 

 

 

지정된 파이어베이스 주소로 데이터가 잘 들어옴을 확인할 수 있다.

 

 

 

 

실행을 하면 json에 저장된 정보를

역직렬화와 직렬화 가정을 거쳐

info파일에 있는 수치들을 가져온다.

 

 

 

카드 창을 클릭하면 팝업이 나오고 각각의 카드는 클릭을 입력 받을 수 있게 하며,

x버튼을 누르면 팝업이 닫힌다.

 

 

 

 

 

1. 인벤토리 영역 지정

2. 빈 오브젝트(content) 생성 후, 좌상단 (Alt + Shift) 앵커 프리셋 설정

3. 이미지(InvenCell) 생성 후, 앵커 프리셋 좌상단 (Alt + Shift) 설정

4. Guide의 Cell 하나 크기 만큼으로 Cell 크기 설정

5. Width, Height 각각 크기 설정

6. Content에 Content Size Fitter, Grid Layout Group 컴포넌트 추가

7. InvenCell을 (Ctrl + D)로 여러개 복사한 후, Cell 과 Cell 사이 간의 Space(공간) 설정

8. UIInvenScrollView의 Scroll Rect의 Content에 Content를 연결하고 Horizontal 체크 해제

9. 씬 실행 후, 스크롤 뷰가 제대로 작동하는지 확인

10. ScrollVIew에 Rect Mask 2D 컴포넌트 추가

11. 수량 표시를 위해 텍스트(Text - Text Mesh Pro) 생성 후, 위치/크기 설정

12. Frame과 Icon 설정

13., ScrollView-Scroll Rect의 Movement Tyoe을 Clamped로 설정

 

※ 스크롤바를 경직하게 하고 싶지 않으면 Clamped 대신에 Elastic사용

 

Hp와 Energy는 슬라이더로 제작

향후 대미지를 받았을 경우 혹은 Energy(기력)을 사용할 경우 감소되게 하기 위함.

이런식으로 Grabbable에 옵션으로 한손과 두손관련 정보를 담은 스크립트를 할당해주면

크기를 늘릴 수 있다.

 

 

 


 

 

 

 


 

미완성

 

 

 

위의 코드는 오른손과 왼손은의 인지를 다르게 해주게 하기 위함이다.

예를들어 왼손으로는 오른손아래 손잡이를 잡지 못하게 할 수 있다.

using Oculus.Interaction;
using Oculus.Interaction.HandGrab;
using UnityEngine;
using static OVRHand;

public class HandController : MonoBehaviour
{
    [SerializeField]
    private Hand HandType = Hand.None;
    public HandGrabInteractor leftHandGrabInteractor;
    public HandGrabInteractor rightHandGrabInteractor;

    private void OnTriggerEnter(Collider other)
    {
        if (HandType == Hand.HandLeft 
            && other.GetComponent<OneGrabFreeTransformer>() != null) {

            leftHandGrabInteractor.gameObject.SetActive(false);

        }
        else if (HandType == Hand.HandRight
            && other.GetComponent<TwoGrabFreeTransformer>() != null)
        {
            rightHandGrabInteractor.gameObject.SetActive(false);
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (HandType == Hand.HandLeft
            && other.GetComponent<OneGrabFreeTransformer>() != null)
        {
            leftHandGrabInteractor.gameObject.SetActive(true);
        }
        else if (HandType == Hand.HandRight
            && other.GetComponent<TwoGrabFreeTransformer>() != null)
        {
            rightHandGrabInteractor.gameObject.SetActive(true);
        }

    }
}

 

완성이되면 왼손 오른손 각각 이미지를 로드 후 세이브 해서 손모양을 저장하고

 

손을 가져다 대면 각각 왼손과 오른손이 지정된 위치로 그랩을 할 수 있다.

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

[VR] Locomotion(Teleport)  (0) 2024.04.23
[VR]반대손 복사와 회전 및 던지기  (0) 2024.04.19
[VR]총 잡기 - HandGun Grab  (1) 2024.04.18
Create Ghost Reticles  (0) 2024.04.18
Oculus Settings and Grab  (0) 2024.04.17

https://assetstore.unity.com/packages/3d/environments/simplepoly-city-low-poly-assets-58899

 

SimplePoly City - Low Poly Assets | 3D 주변환경 | Unity Asset Store

Elevate your workflow with the SimplePoly City - Low Poly Assets asset from VenCreations. Find this & other 주변환경 options on the Unity Asset Store.

assetstore.unity.com

 

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

public class SimpleCapsuleWithStickMovement : MonoBehaviour
{
    public bool EnableLinearMovement = true;
    public bool EnableRotation = true;
    public bool HMDRotatesPlayer = true;
    public bool RotationEitherThumbstick = false;
    public float RotationAngle = 45.0f;
    public float Speed = 0.0f;
    public OVRCameraRig CameraRig;

    private bool ReadyToSnapTurn;
    private Rigidbody _rigidbody;

    public event Action CameraUpdated;
    public event Action PreCharacterMove;

    private void Awake()
    {
        _rigidbody = GetComponent<Rigidbody>();
        if (CameraRig == null) CameraRig = GetComponentInChildren<OVRCameraRig>();
    }

    void Start()
    {
    }

    private void FixedUpdate()
    {
        if (CameraUpdated != null) CameraUpdated();
        if (PreCharacterMove != null) PreCharacterMove();

        if (HMDRotatesPlayer) RotatePlayerToHMD();
        if (EnableLinearMovement) StickMovement();
        if (EnableRotation) SnapTurn();
    }

    void RotatePlayerToHMD()
    {
        Transform root = CameraRig.trackingSpace;
        Transform centerEye = CameraRig.centerEyeAnchor;

        Vector3 prevPos = root.position;
        Quaternion prevRot = root.rotation;

        transform.rotation = Quaternion.Euler(0.0f, centerEye.rotation.eulerAngles.y, 0.0f);

        root.position = prevPos;
        root.rotation = prevRot;
    }

    void StickMovement()
    {
        Quaternion ort = CameraRig.centerEyeAnchor.rotation;
        Vector3 ortEuler = ort.eulerAngles;
        ortEuler.z = ortEuler.x = 0f;
        ort = Quaternion.Euler(ortEuler);

        Vector3 moveDir = Vector3.zero;
        Vector2 primaryAxis = OVRInput.Get(OVRInput.Axis2D.PrimaryThumbstick);
        moveDir += ort * (primaryAxis.x * Vector3.right);
        moveDir += ort * (primaryAxis.y * Vector3.forward);
        //_rigidbody.MovePosition(_rigidbody.transform.position + moveDir * Speed * Time.fixedDeltaTime);
        _rigidbody.MovePosition(_rigidbody.position + moveDir * Speed * Time.fixedDeltaTime);
    }

    void SnapTurn()
    {
        if (OVRInput.Get(OVRInput.Button.SecondaryThumbstickLeft) ||
            (RotationEitherThumbstick && OVRInput.Get(OVRInput.Button.PrimaryThumbstickLeft)))
        {
            if (ReadyToSnapTurn)
            {
                ReadyToSnapTurn = false;
                transform.RotateAround(CameraRig.centerEyeAnchor.position, Vector3.up, -RotationAngle);
            }
        }
        else if (OVRInput.Get(OVRInput.Button.SecondaryThumbstickRight) ||
                 (RotationEitherThumbstick && OVRInput.Get(OVRInput.Button.PrimaryThumbstickRight)))
        {
            if (ReadyToSnapTurn)
            {
                ReadyToSnapTurn = false;
                transform.RotateAround(CameraRig.centerEyeAnchor.position, Vector3.up, RotationAngle);
            }
        }
        else
        {
            ReadyToSnapTurn = true;
        }
    }
}

 

 

collider가 있어서 이 안으로 텔레포트 할 수 없다.

어싸인 확인

이건 엄지와 검지를 닿게 할 것인지를 결정

이제 핸드트래킹(손가락)으로도 턴을 적용 시킬 수 있다.

 

 

 

 

영상과 같이 길로만 이동할수 있따.

 

 


 

 

 

 

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

[VR] Transformer Interaction  (0) 2024.04.23
[VR]반대손 복사와 회전 및 던지기  (0) 2024.04.19
[VR]총 잡기 - HandGun Grab  (1) 2024.04.18
Create Ghost Reticles  (0) 2024.04.18
Oculus Settings and Grab  (0) 2024.04.17

한손만 복사본을 저장했다면 이버튼을 눌러 반대손도 적용 할 수 있다.

 

 

 

 


그런데 공을 다시 잡으면 손이 저장된 위치로 가기 때문에 공이 회전한다.

이 공의 회전을 고정하기 위한 작업을 실행했다.

모든 작업들은 오른손을 했으면 왼손도 적용해주면 된다.

 

 

이제 공을 다시 잡아도 돌지 않는다.

 

 

 

이번에는 책에 적용해 보았다.

아까 설명한 오른손으로 이미지를 잡고 왼손을 복사하여 적용된 모습이고

 

생성된 Hand Grab Pose에 Box Grab Surface 컴포너트를 추가한 후

박스를 정하는데

이는 손목을 기준점으로 잡힌다.

 

그후

 

 

여기 Follow Surface를 설정하면 테스트도 해볼 수 있다.

 

 

 

중력을 키면 책이 책상에 떨어진다.

프로젝트에 있는 HandVelocityCalculator 추가 한후

인트렉터에 넣어준다.

 

주의 !

책의 y좌표보다 낮아야지 리스폰이 된다.

즉, 기존의 좌표보다 낮을 경우 리스폰이 된다.

 

 

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

[VR] Transformer Interaction  (0) 2024.04.23
[VR] Locomotion(Teleport)  (0) 2024.04.23
[VR]총 잡기 - HandGun Grab  (1) 2024.04.18
Create Ghost Reticles  (0) 2024.04.18
Oculus Settings and Grab  (0) 2024.04.17

+ Recent posts