self-driving car ในเกมมีความสามารถในการเรียนรู้ปรับตัว และสามารถขับรถให้เก่งขึ้นได้จากการใช้ machine learning ถายในเกมของ Unity
ขั้นแรก ตัวรถต้องสามารถ ขยับได้ด้วยตัวเองก่อนโดยใช้โคด
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarDriver : MonoBehaviour {
#region Fields
private float speed;
public float speedMax = 70f;
private float speedMin = -50f;
public float acceleration = 30f;
public float brakeSpeed = 100f;
private float reverseSpeed = 30f;
private float idleSlowdown = 10f;
private float turnSpeed;
public float turnSpeedMax = 300f;
private float turnSpeedAcceleration = 300f;
private float turnIdleSlowdown = 500f;
private float forwardAmount;
private float turnAmount;
private Rigidbody carRigidbody;
#endregion
private void Awake() {
carRigidbody = GetComponent<Rigidbody>();
}
private void Update() {
if (forwardAmount > 0) {
// Accelerating
speed += forwardAmount * acceleration * Time.deltaTime;
}
if (forwardAmount < 0) {
if (speed > 0) {
// Braking
speed += forwardAmount * brakeSpeed * Time.deltaTime;
} else {
// Reversing
speed += forwardAmount * reverseSpeed * Time.deltaTime;
}
}
if (forwardAmount == 0) {
// Not accelerating or braking
if (speed > 0) {
speed -= idleSlowdown * Time.deltaTime;
}
if (speed < 0) {
speed += idleSlowdown * Time.deltaTime;
}
}
speed = Mathf.Clamp(speed, speedMin, speedMax);
carRigidbody.velocity = transform.forward * speed;
if (speed < 0) {
// Going backwards, invert wheels
turnAmount = turnAmount * -1f;
}
if (turnAmount > 0 || turnAmount < 0) {
// Turning
if ((turnSpeed > 0 && turnAmount < 0) || (turnSpeed < 0 && turnAmount > 0)) {
// Changing turn direction
float minTurnAmount = 20f;
turnSpeed = turnAmount * minTurnAmount;
}
turnSpeed += turnAmount * turnSpeedAcceleration * Time.deltaTime;
} else {
// Not turning
if (turnSpeed > 0) {
turnSpeed -= turnIdleSlowdown * Time.deltaTime;
}
if (turnSpeed < 0) {
turnSpeed += turnIdleSlowdown * Time.deltaTime;
}
if (turnSpeed > -1f && turnSpeed < +1f) {
// Stop rotating
turnSpeed = 0f;
}
}
float speedNormalized = speed / speedMax;
float invertSpeedNormalized = Mathf.Clamp(1 - speedNormalized, .75f, 1f);
turnSpeed = Mathf.Clamp(turnSpeed, -turnSpeedMax, turnSpeedMax);
carRigidbody.angularVelocity = new Vector3(0, turnSpeed * (invertSpeedNormalized * 1f) * Mathf.Deg2Rad, 0);
if (transform.eulerAngles.x > 2 || transform.eulerAngles.x < -2 || transform.eulerAngles.z > 2 || transform.eulerAngles.z < -2) {
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
}
}
//private void OnCollisionEnter(Collision collision) {
// if (collision.gameObject.layer == GameHandler.SOLID_OBJECTS_LAYER) {
// speed = Mathf.Clamp(speed, 0f, 20f);
//}
//}
public void SetInputs(float forwardAmount, float turnAmount) {
this.forwardAmount = forwardAmount;
this.turnAmount = turnAmount;
}
public void ClearTurnSpeed() {
turnSpeed = 0f;
}
public float GetSpeed() {
return speed;
}
public void SetSpeedMax(float speedMax) {
this.speedMax = speedMax;
}
public void SetTurnSpeedMax(float turnSpeedMax) {
this.turnSpeedMax = turnSpeedMax;
}
public void SetTurnSpeedAcceleration(float turnSpeedAcceleration) {
this.turnSpeedAcceleration = turnSpeedAcceleration;
}
public void StopCompletely() {
speed = 0f;
turnSpeed = 0f;
}
}
และใน version ที่พึ่งได้เล่นไป จะเป็น version แรกที่รถ จะสามารถ ขับได้โดยผู้เล่นผ่านโค้ดของ
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarAi : MonoBehaviour
{
[SerializeField] private Transform targetPositionTranform;
private CarDriver CarDriver;
private Vector3 TargetPosition;
// Start is called before the first frame update
private void Awake()
{
CarDriver = GetComponent<CarDriver>();
}
// Update is called once per frame
void Update()
{
SetTargetPosition(targetPositionTranform.position);
float forwardAmount = 0;
float turnAmount = 0f;
float reachTargetDistance = 7f;
float distanceToTarget = Vector3.Distance(transform.position, TargetPosition);
if(distanceToTarget > reachTargetDistance) {
Vector3 dirToMovePosition = (TargetPosition - transform.position).normalized;
float dot = Vector3.Dot(transform.forward, dirToMovePosition);
if (dot > 0)
{
forwardAmount = 1f;
}
else
{
float reversDistance = 25f;
if(distanceToTarget > reversDistance)
{
forwardAmount = 1f;
}
else
{
forwardAmount = -1f;
}
}
float angleToDir = Vector3.SignedAngle(transform.forward, dirToMovePosition, Vector3.up);
if (angleToDir > 0)
{
turnAmount = 1f;
}
else
{
turnAmount = -1f;
}
}
else
{
if(CarDriver.GetSpeed() > 15f)
{
forwardAmount = -1f;
}
else
{
forwardAmount = 0f;
}
turnAmount = 0f;
}
CarDriver.SetInputs(forwardAmount, turnAmount);
}
public void SetTargetPosition(Vector3 TargetPosition)
{
this.TargetPosition = TargetPosition;
}
}
นำไปใส้เป็น component ของรถให้สามารถขับได้
จากนั้นเครื่องมือต่อไปที่ใช้ คือ asset ML-agent ที่เป็น asset ที่สามารถสร้าง agent ซึ่งจะเป็น component ของ ai ที่เราต้องการผ่าน GitHub
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 learning and imitation learning.
Unity ML-Agents Toolkit
(latest release) (all releases)
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. We provide implementations (based on PyTorch) of state-of-the-art algorithms to enable game developers and hobbyists to easily train intelligent agents for 2D, 3D and VR/AR games. Researchers can also use the provided simple-to-use Python API to train Agents using reinforcement learning imitation learning, neuroevolution, or any other methods. These trained agents can be used for multiple purposes, including controlling NPC behavior (in a variety of settings such as multi-agent and adversarial), automated testing of game builds and evaluating different game design decisions pre-release. The ML-Agents Toolkit is mutually beneficial for both game developers and AI researchers as it provides a central platform where advances in AI can be evaluated on Unity’s rich environments and then…
เมือทำการ install เสร็จแล้วจึงสามารถใช้ ML-agents Component ได้
โดยตัว Ai จะมีการทำ Reinforcement learning
โดยจะมีรำดับการทำงานที่
1.Observation
ทำการสังเกตุ enivromentในเกมเพื่อเก็บข้อมูลประกอบการทำงานในขั้นต่อไป
public override void CollectObservations(VectorSensor sensor)(
sensor.AddObervation(transform.position);//ให้ ai สั่งเกตุตำแหน่งของตัวรถ
sensor.AddObervation(target.Transform.position);//ให้ ai สังเกตุตำแหน่งของเป้าหมาย
2.Decision
การตัดสินใจจากองค์ประกอบต้างๆที่ได้เก็บข้อมูลมา
public override void OnActionReceived(ActionBuffers action){
float moveX = action.ContinuousActions[0];
float moveZ = action.ContinuousActions[1];// ให้aiทำการเคลื่อนที่เข้าหาเป้าหมายมากขึ้น
3.Reward
รับรางวัลเพื่อพิสูจว่าสิ่งที่ Ai ทำไปนั้นเป็นสิ่งที่ถูกต้องตามที่กำหนดไว้ซึ่งหากผิดจะต้องกับไปที่กระบวนการเเรกไหม่ทั้งหมด
private void OnTriggerEnter(Collider other){
SetReward(1f); // เมื่อรถชนวัตถุที่เราต้องการแล้วจึงจะได้รางวัล
EndEpisode();
เมือทำการCode สำเร็จ รถจะสามารถขับได้ด้วยตัวเอง>-<
Top comments (0)