inspector에서 string으로 원하는 scene의 이름을 저장한 후 클릭을 하면 해당  씬으로 이동

 

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

public class ChangeScene : MonoBehaviour
{
    public string sceneName;
    private Button btn;

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

        btn.onClick.AddListener(() =>
        {
            SceneManager.LoadScene(sceneName);
        });
    }
}

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

[애드몹] 배너 광고 붙이기  (0) 2024.06.28
플레이콘솔 리더보드에 점수 올리기  (0) 2024.06.26
2D 3Matchpuzzle - 블록 위치 찾기 테스트  (0) 2024.05.16
2D 3Matchpuzzle - 빈공간 찾기  (0) 2024.05.14
Download Python  (0) 2024.05.08

https://github.com/wlgys8/Sprites-Outline

 

GitHub - wlgys8/Sprites-Outline: Outline effect for Unity SpriteRenderer

Outline effect for Unity SpriteRenderer. Contribute to wlgys8/Sprites-Outline development by creating an account on GitHub.

github.com

 

'라이브러리' 카테고리의 다른 글

DOTween  (1) 2024.03.29

완전 탐색을 하여 2중 for문을 돌린다

 

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

public class MatchTest : MonoBehaviour
{
    private static readonly int Rows = 4;
    private static readonly int Cols = 4;
    
    private int[,] board =
    {
        {1, 1, 2, 0},
        {1, 1, 1, 1},
        {2, 1, 0, 1},
        {0, 0, 1, 1}
    };
    void Start()
    {
        FindMatchingBlocks();
    }
    
    private void FindMatchingBlocks()
    {
        HashSet<(int, int)> matchedBlocks = new HashSet<(int, int)>();

        for (int i = 0; i < Rows; i++)
        {
            for (int j = 0; j < Cols; j++)
            {
                CheckHorizontalMatch(i, j, matchedBlocks);
                CheckVerticalMatch(i, j, matchedBlocks);
            }
        }

        Debug.Log("Matching Blocks:");
        foreach (var block in matchedBlocks)
        {
            Debug.Log($"({block.Item1}, {block.Item2})");
        }
    }

    private void CheckHorizontalMatch(int row, int col, HashSet<(int, int)> matchedBlocks)
    {
        if (col + 2 < Cols &&
            board[row, col] == board[row, col + 1] &&
            board[row, col] == board[row, col + 2])
        {
            matchedBlocks.Add((row, col));
            matchedBlocks.Add((row, col + 1));
            matchedBlocks.Add((row, col + 2));
        }
    }

    private void CheckVerticalMatch(int row, int col, HashSet<(int, int)> matchedBlocks)
    {
        if (row + 2 < Rows &&
            board[row, col] == board[row + 1, col] &&
            board[row, col] == board[row + 2, col])
        {
            matchedBlocks.Add((row, col));
            matchedBlocks.Add((row + 1, col));
            matchedBlocks.Add((row + 2, col));
        }
    }
}

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

플레이콘솔 리더보드에 점수 올리기  (0) 2024.06.26
2D 3Matchpuzzle - 매치 시 파괴 및 로드 + 힌트  (0) 2024.05.20
2D 3Matchpuzzle - 빈공간 찾기  (0) 2024.05.14
Download Python  (0) 2024.05.08
Learn Firebase  (0) 2024.05.02

 

 

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 누르면 중지

 

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

 

 

+ Recent posts