이 전 글에서 게임을 다 만들어봤다.
https://corinyoungee.tistory.com/29
[C# & UNITY] 간단한 Penguin 게임 예제 진행해보기 5 Fish Scripts
이 전 글에서 게임을 다 만들어봤다. https://corinyoungee.tistory.com/28 [C# & UNITY] 간단한 Penguin 게임 예제 진행해보기 4 https://corinyoungee.tistory.com/25 [C# & UNITY] 간단한 Penguin 게임 예제 진행해보기 3 이 글
corinyoungee.tistory.com
PenguinAgent script - 엄마 펭귄
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;
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
/// <summary>
/// Initial setup, called when the agent is enabled
/// </summary>
public override void Initialize()
{
base.Initialize();
penguinArea = GetComponentInParent<PenguinArea>();
baby = penguinArea.penguinBaby;
rigidbody = GetComponent<Rigidbody>();
}
/// <summary>
/// Perform actions based on a vector of numbers
/// </summary>
/// <param name="actionBuffers">The struct of actions to take</param>
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);
}
/// <summary>
/// Read inputs from the keyboard and convert them to a list of actions.
/// This is called only when the player wants to control the agent and has set
/// Behavior Type to "Heuristic Only" in the Behavior Parameters inspector.
/// </summary>
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;
}
/// <summary>
/// When a new episode begins, reset the agent and area
/// </summary>
public override void OnEpisodeBegin()
{
isFull = false;
penguinArea.ResetArea();
}
/// <summary>
/// Collect all non-Raycast observations
/// </summary>
/// <param name="sensor">The vector sensor to add observations to</param>
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
}
/// <summary>
/// When the agent collides with something, take action
/// </summary>
/// <param name="collision">The collision info</param>
private void OnCollisionEnter(Collision collision)
{
if (collision.transform.CompareTag("fish")) // 충돌 대상이 fish면
{
// Try to eat the fish
EatFish(collision.gameObject); // fish를 먹고
}
else if (collision.transform.CompareTag("baby")) // 충돌 대상이 babypenguin이면
{
// Try to feed the baby
RegurgitateFish(); // 손질한 물고기를 가져와 아기 펭귄에게 먹이를 준다.
}
}
/// <summary>
/// Check if agent is full, if not, eat the fish and get a reward
/// </summary>
/// <param name="fishObject">The fish to eat</param>
private void EatFish(GameObject fishObject)
{
if (isFull) return; // Can't eat another fish while full
isFull = true;
penguinArea.RemoveSpecificFish(fishObject);
AddReward(1f); // reward를 결정해준다.
}
/// <summary>
/// Check if agent is full, if yes, feed the baby
/// </summary>
private void RegurgitateFish() // 손질한 물고기
{
if (!isFull) return; // Nothing to regurgitate
isFull = false;
// Spawn regurgitated fish
// 유니티 게임 상에서 손질된 물고기를 생성한다.
GameObject regurgitatedFish = Instantiate<GameObject>(regurgitatedFishPrefab);
// transform.parent : 기준점이 되는 위치를 parent의 위치로
regurgitatedFish.transform.parent = transform.parent;
// transform.position : 실제 놓여질 위치를 정의
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();
}
}
}
// ML-agent에 중요한 함수는 PenguinAgent에 몰려있다.
// OnActionReceived()
// OnEpisodeBegin() : 에피소드를 시작할 때마다
// CollectObservation() : 입력을 결정하는 부분
// OnCollisionEnter() : 충돌이 발생했을 때 어떻게 해야할지
참고 사이트
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
이 페이지를 보고 만들어봤다.
교수님 강의를 보고 적었습니당
첫 이미지의 상어와 암석 asset은 unity asset store에서 무료 asset을 찾아서 다운받았습니다.
다음에 asset을 다운받아서 적용하는 방법에 대한 글을 올리겠습니당.
https://assetstore.unity.com/packages/3d/characters/animals/fish/fish-polypack-202232
Fish - PolyPack | 캐릭터 | Unity Asset Store
Get the Fish - PolyPack package from Alstra Infinite and speed up your game development process. Find this & other 캐릭터 options on the Unity Asset Store.
assetstore.unity.com
https://assetstore.unity.com/packages/3d/environments/landscapes/stylized-snow-forest-230653#content
Stylized Snow Forest | 3D 풍경 | Unity Asset Store
Elevate your workflow with the Stylized Snow Forest asset from Frag112. Find this & other 풍경 options on the Unity Asset Store.
assetstore.unity.com
팀플이였는데.. 혼자서 찾느라 힘들었다,,
'언어 > UNITY' 카테고리의 다른 글
[C# / UNITY] 간단한 Penguin 게임 예제 진행해보기 8 강화학습 환경 만들어주기 (0) | 2023.03.24 |
---|---|
[C# / UNITY] 간단한 Penguin 게임 예제 진행해보기 7 PenguinArea scripts (1) | 2023.03.22 |
[C# / UNITY] 간단한 Penguin 게임 예제 진행해보기 5 Fish Scripts (0) | 2023.03.17 |
[C# / UNITY] 간단한 Penguin 게임 예제 진행해보기 4 (0) | 2023.03.15 |
[C# / UNITY] 간단한 Penguin 게임 예제 진행해보기 3 (0) | 2023.03.10 |