using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.U2D;
using Random = UnityEngine.Random;

public class Test : MonoBehaviour
{
    public Board board;
    private void Start()
    {
        board.CreateBoard();
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 1);
            RaycastHit2D raycastHit2D = Physics2D.Raycast(ray.origin, ray.direction);
            if (raycastHit2D.collider != null)
            {
                Block block = raycastHit2D.collider.GetComponent<Block>();
                Debug.Log($"[{block.row}, {block.col}] ({block.transform.position.x}, {block.transform.position.y}), {block.blockType}");
            }
        }
    }
}

 

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

public class Block : MonoBehaviour
{
    public enum BlockType
    {
        Rabbit, Pig, Rat, Monkey, Cat, Chick, Puppy
    }

    public BlockType blockType;
    public SpriteRenderer spriteRenderer;
    public TMP_Text debugText;
    public int row;
    public int col;

    public void Init(BlockType blockType)
    {
        this.blockType = blockType;
        //이미지 변경 
        ChangeSprite(blockType);
    }

    public void ChangeSprite(BlockType blockType)
    {
        Sprite sp =
            AtlasManager.instance.blockAtlas.GetSprite(blockType.ToString());
        spriteRenderer.sprite = sp;
    }

    public void SetPosition(Vector2 pos)
    {
        transform.position = pos;
        var index = Position2Index(pos);
        row = index.row;
        col = index.col;
        debugText.text = $"[{index.row},{index.col}]";
    }

    public static (int row, int col) Position2Index(Vector2 pos)
    {
        return ((int)pos.y, (int)pos.x);
    }

    public static (int x, int y) Index2Position(Vector2 index)
    {
        return ((int)index.x, (int)index.y);
    }
}

 

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

    [CustomEditor(typeof(Block))]
    public class BlockEditor : Editor
    {
        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            Block block = target as Block;
            if (GUILayout.Button("제거"))
            {
                Debug.Log($"[{block.row},{block.col}]을 제거 합니다.");

                Board.instance.RemoveBlock(block.row, block.col);
            }
        }
    }

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Random = UnityEngine.Random;

public class Board : MonoBehaviour
{
    public static Board instance;   //싱글톤
    private Block[,] board;  //2차원 배열이 Block들을 관리
    public GameObject blockPrefab;

    public int totalHeight = 14;
    public int height = 7;
    public int width = 7;

    private void Awake()
    {
        instance = this;
    }

    public void CreateBoard()
    {
        //크기가 7개인 Block타입의 2차원 배열을 만들기
        board = new Block[totalHeight, width];

        for (int i = 0; i < height; i++)    //행
        {
            for (int j = 0; j < width; j++)    //열 
            {
                CreateBlock(i, j);
            }
        }
        PrintBoard();
    }

    public void CreateBlock(int row, int col)
    {
        Vector2 pos = new Vector2(col, row);
        Block.BlockType blockType = (Block.BlockType)Random.Range(0, 7); //0 ~ 6  
        GameObject blockGo = Instantiate(blockPrefab, this.transform);
        Block block = blockGo.GetComponent<Block>();
        block.Init(blockType);
        block.SetPosition(pos);

        //배열의 요소에 블록 넣기 
        board[row, col] = block;
    }

    public void RemoveBlock(int row, int col)
    {
        Block block = board[row, col];
        Destroy(block.gameObject);  //게임오브젝트 파괴 

        //배열의 요소를 비워줌 
        board[row, col] = null;
    }

    public void PrintBoard()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < height; i++)    //행
        {
            for (int j = 0; j < width; j++)    //열
            {
                Block block = board[i, j];
                string strElement = (block == null) ? "null" : block.blockType.ToString();
                // 각 엘리먼트를 고정된 너비로 출력
                sb.AppendFormat("[{0},{1}] = {2,-10}", i, j, strElement);
            }
            sb.AppendLine();
        }
        Debug.Log(sb.ToString());
    }

    private int[] arrEmptySpaceCol; //빈공간이 있는 컬럼 배열 

    public void FindEmptySpaceFromColumn()
    {
        arrEmptySpaceCol = new int[width]; //배열 초기화
                                           //0 : 행, 1: 열 
        for (int i = 0; i < width; i++)    //열 
        {
            int existBlockCnt = 0;

            for (int j = 0; j < totalHeight; j++)    //행 
            {
                Block block = board[j, i];
                if (block != null) existBlockCnt++;
            }

            int emptySpace = height - existBlockCnt;
            arrEmptySpaceCol[i] = emptySpace;
            Debug.Log($"{i} 열의 빈공간은 {emptySpace}개 입니다.");
        }
    }

    public void CreateNewBlocks()
    {
        // arrEmptySpaceCol가 null이거나 모든 요소가 0이면 빈공간이 없음
        if (arrEmptySpaceCol == null || arrEmptySpaceCol.All(x => x == 0))
        {
            Debug.Log("빈공간이 없습니다.");
        }
        else
        {
            for (int i = 0; i < arrEmptySpaceCol.Length; i++)
            {
                int cnt = arrEmptySpaceCol[i];  //i(col)에 몇개 빈공간이 있는가?
                if (cnt > 0)
                {
                    Debug.Log($"{i}열에 {cnt}만큼 블록 생성 필요");
                    CreateBlockFromColumn(i, cnt);
                }
            }
        }

        arrEmptySpaceCol = null;
    }

    private void CreateBlockFromColumn(int col, int cnt)
    {
        int startRow = height;  //행 

        for (int i = 0; i < cnt; i++)
        {
            //[7, col] -> [8, col] -> [9,col]
            CreateBlock(startRow, col);
            startRow++;
        }
    }
}

 

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

[CustomEditor(typeof(Board))]
public class BoardEditor : Editor
{
    private int currentColIdx = 0;

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Board board = target as Board;

        if (GUILayout.Button("배열 요소 출력"))
        {
            board.PrintBoard(); ;
        }

        GUILayout.Space(5);

        if (GUILayout.Button("각 열에 빈공간 찾기"))
        {
            board.FindEmptySpaceFromColumn();
        }

        GUILayout.Space(5);

        if (GUILayout.Button("새로운 블록들 생성하기"))
        {
            board.CreateNewBlocks();
        }

        GUILayout.Space(5);
        if (GUILayout.Button($"현재 행({currentColIdx})에 있는 모든 블록 내려보내기"))
        {
            Debug.Log($"{currentColIdx}행에 있는 모든 블록 내려 보냅니다.");
            currentColIdx++;
            if (currentColIdx > 6)
            {
                currentColIdx = 0;
            }
        }
        GUILayout.Space(5);

        if (GUILayout.Button("리셋 행"))
        {
            currentColIdx = 0;
        }
    }
}

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

2D 3Matchpuzzle - 매치 시 파괴 및 로드 + 힌트  (0) 2024.05.20
2D 3Matchpuzzle - 블록 위치 찾기 테스트  (0) 2024.05.16
Download Python  (0) 2024.05.08
Learn Firebase  (0) 2024.05.02
2D Vertical Shooting Game 모작 최종  (0) 2024.04.08

 

 

 

카드 클릭시 체크 표시 및 알파 값 조절

 

클릭시 desc 나오는건 수정 요망

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://www.immersivelimit.com/tutorials/reinforcement-learning-penguins-part-1-unity-ml-agents

 

Reinforcement Learning Penguins (Part 1/4) | Unity ML-Agents — Immersive Limit

Unity Project Setup and Asset Import

www.immersivelimit.com

 

 

 

 

https://docs.unity3d.com/ScriptReference/TooltipAttribute.html

 

Unity - Scripting API: TooltipAttribute

Tooltip hovering over the class it was added to. In the following script a Tooltip is added. This provides information to the user about the range of values for the health variable. The suggested range is provided in the TooltipAttribute string. Note: Unit

docs.unity3d.com

https://docs.unity3d.com/Packages/com.unity.ml-agents@3.0/api/Unity.MLAgents.Agent.GetCumulativeReward.html

 

Method GetCumulativeReward | ML Agents | 3.0.0-exp.1

Method GetCumulativeReward GetCumulativeReward() Retrieves the episode reward for the Agent. Declaration public float GetCumulativeReward() Returns Type Description float The episode reward.

docs.unity3d.com

 

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

[CustomEditor(typeof(PenguinArea))]
public class PenguinAreaEditor : Editor
{
    public override void OnInspectorGUI()
    {
        PenguinArea penguinArea = (PenguinArea)target;
        base.OnInspectorGUI();
        if (GUILayout.Button("Choose Random Position"))
        {
            Debug.Log("ChooseRandomPosition");
            Vector3 center = penguinArea.transform.position;
            float minAngle = -15;
            float maxAngle = 15;
            float minRadius = 1;
            float maxRadius = 2;
            Vector3 randPos =
                PenguinArea.ChooseRandomPosition(center, minAngle, maxAngle, minRadius, maxRadius);

            Debug.Log(randPos);

            Debug.DrawLine(center, randPos, Color.red, 10);
        }
    }
}

 

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

public class PenguinArea : MonoBehaviour
{
    [Tooltip("The agent inside the area")]
    public PenguinAgent penguinAgent;

    [Tooltip("The baby penguin inside the area")]
    public GameObject penguinBaby;

    [Tooltip("The TextMeshPro text that shows the cumulative reward of the agent")]
    public TextMeshPro cumulativeRewardText;

    [Tooltip("Prefab of a live fish")]
    public Fish fishPrefab;

    private List<GameObject> fishList;

    //씬에 남아 있는 물고기 수 

    public int FishRemaining
    {
        get { return fishList.Count; }
    }

    private void Start()
    {
        this.fishList = new List<GameObject>();

        ResetArea();
    }

    private void Update()
    {
        // Update the cumulative reward text
        cumulativeRewardText.text = penguinAgent.GetCumulativeReward().ToString("0.00");
    }


    public void ResetArea()
    {
        RemoveAllFish();
        PlacePenguin();
        PlaceBaby();
        SpawnFish(4, .5f);
    }

    //엄마 펭귄의 이동속도, 회전속도 초기화 및 랜덤위치, 랜덤회전
    private void PlacePenguin()
    {
        Rigidbody rigidbody = penguinAgent.GetComponent<Rigidbody>();
        rigidbody.velocity = Vector3.zero;
        rigidbody.angularVelocity = Vector3.zero;
        penguinAgent.transform.position = ChooseRandomPosition(transform.position, 0f, 360f, 0f, 9f) + Vector3.up * .5f;
        penguinAgent.transform.rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0f, 360f), 0f);
    }

    private void PlaceBaby()
    {
        Rigidbody rigidbody = penguinBaby.GetComponent<Rigidbody>();
        rigidbody.velocity = Vector3.zero;
        rigidbody.angularVelocity = Vector3.zero;
        penguinBaby.transform.position = ChooseRandomPosition(transform.position, -45f, 45f, 4f, 9f) + Vector3.up * .5f;
        penguinBaby.transform.rotation = Quaternion.Euler(0f, 180f, 0f);
    }


    //물고기를 먹었다면 리스트에서 제거하고 씬에서 제거한다 
    public void RemoveSpecificFish(GameObject fishObject)
    {
        fishList.Remove(fishObject);
        Destroy(fishObject);
    }

    public static Vector3 ChooseRandomPosition(Vector3 center, float minAngle, float maxAngle, float minRadius, float maxRadius)
    {
        float radius = minRadius;
        float angle = minAngle;

        if (maxRadius > minRadius)
        {
            // Pick a random radius
            radius = UnityEngine.Random.Range(minRadius, maxRadius);
        }

        if (maxAngle > minAngle)
        {
            // Pick a random angle
            angle = UnityEngine.Random.Range(minAngle, maxAngle);
        }

        // Center position + forward vector rotated around the Y axis by "angle" degrees, multiplies by "radius"
        return center + Quaternion.Euler(0f, angle, 0f) * Vector3.forward * radius;
    }

    //count만큼 fish프리팹 인스턴스 생성, 리스트에 넣기, 이동속도 설정하기 
    private void SpawnFish(int count, float fishSpeed)
    {
        for (int i = 0; i < count; i++)
        {
            // Spawn and place the fish
            GameObject fishObject = Instantiate<GameObject>(fishPrefab.gameObject);
            fishObject.transform.position = ChooseRandomPosition(transform.position, 100f, 260f, 2f, 13f) + Vector3.up * .5f;
            fishObject.transform.rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0f, 360f), 0f);

            // Set the fish's parent to this area's transform
            fishObject.transform.SetParent(transform);

            // Keep track of the fish
            fishList.Add(fishObject);

            // Set the fish speed
            fishObject.GetComponent<Fish>().fishSpeed = fishSpeed;
        }
    }

    private void RemoveAllFish()
    {
        if (fishList != null)
        {
            for (int i = 0; i < fishList.Count; i++)
            {
                if (fishList[i] != null)
                {
                    Destroy(fishList[i]);
                }
            }
        }

        fishList = new List<GameObject>();
    }

    private void OnDrawGizmos()
    {
        Vector3 center = this.transform.position;
        Vector3 dir = Vector3.forward;
        float angleRange = 30f;
        float radius = 2f;

        GizmosExtensions.DrawWireArc(center, dir, angleRange, radius);
    }
}

 

using UnityEngine;

public class GizmosExtensions
{
    private GizmosExtensions() { }

    public static void DrawWireArc(Vector3 position, Vector3 dir, float anglesRange, float radius, Color color, float maxSteps = 20)
    {
        Gizmos.color = color;

        var srcAngles = GetAnglesFromDir(position, dir);
        var initialPos = position;
        var posA = initialPos;
        var stepAngles = anglesRange / maxSteps;
        var angle = srcAngles - anglesRange / 2;
        for (var i = 0; i <= maxSteps; i++)
        {
            var rad = Mathf.Deg2Rad * angle;
            var posB = initialPos;
            posB += new Vector3(radius * Mathf.Cos(rad), radius * Mathf.Sin(rad), 0);

            Gizmos.DrawLine(posA, posB);

            angle += stepAngles;
            posA = posB;
        }
        Gizmos.DrawLine(posA, initialPos);
    }


    /// <summary>
    /// Draws a wire arc.
    /// </summary>
    /// <param name="position"></param>
    /// <param name="dir">The direction from which the anglesRange is taken into account</param>
    /// <param name="anglesRange">The angle range, in degrees.</param>
    /// <param name="radius"></param>
    /// <param name="maxSteps">How many steps to use to draw the arc.</param>
    public static void DrawWireArc(Vector3 position, Vector3 dir, float anglesRange, float radius, float maxSteps = 20)
    {
        var srcAngles = GetAnglesFromDir(position, dir);
        var initialPos = position;
        var posA = initialPos;
        var stepAngles = anglesRange / maxSteps;
        var angle = srcAngles - anglesRange / 2;
        for (var i = 0; i <= maxSteps; i++)
        {
            var rad = Mathf.Deg2Rad * angle;
            var posB = initialPos;
            posB += new Vector3(radius * Mathf.Cos(rad), 0, radius * Mathf.Sin(rad));

            Gizmos.DrawLine(posA, posB);

            angle += stepAngles;
            posA = posB;
        }
        Gizmos.DrawLine(posA, initialPos);
    }

    static float GetAnglesFromDir(Vector3 position, Vector3 dir)
    {
        var forwardLimitPos = position + dir;
        var srcAngles = Mathf.Rad2Deg * Mathf.Atan2(forwardLimitPos.z - position.z, forwardLimitPos.x - position.x);

        return srcAngles;
    }
}

 

using System.Collections;
using System.Collections.Generic;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;
using UnityEngine;

public class PenguinAgent : Agent
{
    [Tooltip("How fast the agent moves forward")]
    public float moveSpeed = 5f;

    [Tooltip("How fast the agent turns")]
    public float turnSpeed = 180f;

    [Tooltip("Prefab of the heart that appears when the baby is fed")]
    public GameObject heartPrefab;

    [Tooltip("Prefab of the regurgitated fish that appears when the baby is fed")]
    public GameObject regurgitatedFishPrefab;

    private PenguinArea penguinArea;
    new private Rigidbody rigidbody;
    private GameObject baby;
    private bool isFull; // If true, penguin has a full stomach

    public override void Initialize()
    {
        base.Initialize();
        penguinArea = GetComponentInParent<PenguinArea>();
        baby = penguinArea.penguinBaby;
        rigidbody = GetComponent<Rigidbody>();
    }
    public override void OnActionReceived(ActionBuffers actionBuffers)
    {
        // Convert the first action to forward movement
        float forwardAmount = actionBuffers.DiscreteActions[0];

        // Convert the second action to turning left or right
        float turnAmount = 0f;
        if (actionBuffers.DiscreteActions[1] == 1f)
        {
            turnAmount = -1f;
        }
        else if (actionBuffers.DiscreteActions[1] == 2f)
        {
            turnAmount = 1f;
        }

        // Apply movement
        rigidbody.MovePosition(transform.position + transform.forward * forwardAmount * moveSpeed * Time.fixedDeltaTime);
        transform.Rotate(transform.up * turnAmount * turnSpeed * Time.fixedDeltaTime);

        // Apply a tiny negative reward every step to encourage action
        if (MaxStep > 0) AddReward(-1f / MaxStep);
    }

    public override void Heuristic(in ActionBuffers actionsOut)
    {
        int forwardAction = 0;
        int turnAction = 0;
        if (Input.GetKey(KeyCode.W))
        {
            // move forward
            forwardAction = 1;
        }
        if (Input.GetKey(KeyCode.A))
        {
            // turn left
            turnAction = 1;
        }
        else if (Input.GetKey(KeyCode.D))
        {
            // turn right
            turnAction = 2;
        }

        // Put the actions into the array
        actionsOut.DiscreteActions.Array[0] = forwardAction;
        actionsOut.DiscreteActions.Array[1] = turnAction;
    }
    public override void OnEpisodeBegin()
    {
        isFull = false;
        penguinArea.ResetArea();
    }
    public override void CollectObservations(VectorSensor sensor)
    {
        // Whether the penguin has eaten a fish (1 float = 1 value)
        sensor.AddObservation(isFull);

        // Distance to the baby (1 float = 1 value)
        sensor.AddObservation(Vector3.Distance(baby.transform.position, transform.position));

        // Direction to baby (1 Vector3 = 3 values)
        sensor.AddObservation((baby.transform.position - transform.position).normalized);

        // Direction penguin is facing (1 Vector3 = 3 values)
        sensor.AddObservation(transform.forward);

        // 1 + 1 + 3 + 3 = 8 total values
    }
    private void OnCollisionEnter(Collision collision)
    {
        if (collision.transform.CompareTag("fish"))
        {
            // Try to eat the fish
            EatFish(collision.gameObject);
        }
        else if (collision.transform.CompareTag("baby"))
        {
            // Try to feed the baby
            RegurgitateFish();
        }
    }
    private void EatFish(GameObject fishObject)
    {
        if (isFull) return; // Can't eat another fish while full
        isFull = true;

        penguinArea.RemoveSpecificFish(fishObject);

        AddReward(1f);
    }

    private void RegurgitateFish()
    {
        if (!isFull) return; // Nothing to regurgitate
        isFull = false;

        // Spawn regurgitated fish
        GameObject regurgitatedFish = Instantiate<GameObject>(regurgitatedFishPrefab);
        regurgitatedFish.transform.parent = transform.parent;
        regurgitatedFish.transform.position = baby.transform.position;
        Destroy(regurgitatedFish, 4f);

        // Spawn heart
        GameObject heart = Instantiate<GameObject>(heartPrefab);
        heart.transform.parent = transform.parent;
        heart.transform.position = baby.transform.position + Vector3.up;
        Destroy(heart, 4f);

        AddReward(1f);

        if (penguinArea.FishRemaining <= 0)
        {
            EndEpisode();
        }
    }


}

 

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

public class Fish : MonoBehaviour
{
    [Tooltip("The swim speed")]
    public float fishSpeed;

    private float randomizedSpeed = 0f;
    private float nextActionTime = -1f;
    private Vector3 targetPosition;

    private void FixedUpdate()
    {
        if (fishSpeed > 0f)
        {
            Swim();
        }
    }

    private void Swim()
    {
        // If it's time for the next action, pick a new speed and destination
        // Else, swim toward the destination
        if (Time.fixedTime >= nextActionTime)
        {
            // Randomize the speed
            randomizedSpeed = fishSpeed * UnityEngine.Random.Range(.5f, 1.5f);

            // Pick a random target
            targetPosition = PenguinArea.ChooseRandomPosition(transform.parent.position, 100f, 260f, 2f, 13f);

            // Rotate toward the target
            transform.rotation = Quaternion.LookRotation(targetPosition - transform.position, Vector3.up);

            // Calculate the time to get there
            float timeToGetThere = Vector3.Distance(transform.position, targetPosition) / randomizedSpeed;
            nextActionTime = Time.fixedTime + timeToGetThere;
        }
        else
        {
            // Make sure that the fish does not swim past the target
            Vector3 moveVector = randomizedSpeed * transform.forward * Time.fixedDeltaTime;
            if (moveVector.magnitude <= Vector3.Distance(transform.position, targetPosition))
            {
                transform.position += moveVector;
            }
            else
            {
                transform.position = targetPosition;
                nextActionTime = Time.fixedTime;
            }
        }
    }
}

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

 

ml-agents/docs/Getting-Started.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/Unity-Technologies/ml-agents/blob/develop/docs/Learning-Environment-Create-New.md

 

ml-agents/docs/Learning-Environment-Create-New.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

경로 창에 cmd를 입력하고 엔터를 누르면 이 창에 들어온다.

 

pip install attrs==23.2.0 cattrs==1.5.0 h5py==3.11.0 huggingface-hub==0.23.0 onnx==1.15.0 pypiwin32==223 tensorboard==2.16.2 mlagents-envs==1.1.0.dev0 protobuf==3.20.3 absl-py==2.1.0 --no-deps

 

오류가 나면

버전을 정하지 않고 설치

python -m pip install mlagents

 

mlagents-learn config/ppo/3DBall.yaml --run-id=first3DBallRun

생성이 되면 지우고 다시 설치 후 플레이를 하면 학습을 한다.

 

mlagents-learn config/ppo/3DBall.yaml --run-id=first3DBallRun

 

cmd창에서 컨트롤 + C 누르면 중지

 

중지 후 시간이 지나면 이렇게 학습된 기록들이 만들어진다.

 

 

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줄이 해결된다.

 

 

 

 

 

 

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

2D 3Matchpuzzle - 블록 위치 찾기 테스트  (0) 2024.05.16
2D 3Matchpuzzle - 빈공간 찾기  (0) 2024.05.14
Learn Firebase  (0) 2024.05.02
2D Vertical Shooting Game 모작 최종  (0) 2024.04.08
팬텀로즈스칼렛 모작 최종  (0) 2024.04.08

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

하이어라이키 관점에서 봤을때는 부모와 같은 위치에서 생성되어야 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("데이터 저장 완료");
    }
}

 

 

 

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

 

 

 

 

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

2D 3Matchpuzzle - 빈공간 찾기  (0) 2024.05.14
Download Python  (0) 2024.05.08
2D Vertical Shooting Game 모작 최종  (0) 2024.04.08
팬텀로즈스칼렛 모작 최종  (0) 2024.04.08
2D Airplane - 원근감있는 무한 배경 만들  (0) 2024.03.17

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

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

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

 

 

 

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

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

 

+ Recent posts