Unity 机器学习代理工具包 (ML-Agents) 是一个开源项目,它使游戏和模拟能够作为训练智能代理的环境。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

162 行
5.1 KiB

using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Logic for robot projectiles.
/// </summary>
public class ShootProjectiles : MonoBehaviour
{
public bool initialized; //has this robot been initialized
public GameObject projectilePrefab;
public int numberOfProjectilesToPool = 25;
private List<Projectile> projectilePoolList = new List<Projectile>(); //projectiles to shoot
public Transform projectileStartingPos; //the transform the projectile will originate from
public float projectileLaunchAngle = 5; //the angle at which the projectile will launch
public float shootingRate = .02f; //can shoot every shootingRate seconds. ex: .5 can shoot every .5 seconds
private float shootTimer;
public bool coolDownWait;
//for standalone projectiles
public bool autoShootEnabled;
public float autoShootDistance = 30;
public bool useStandaloneInput = false;
public KeyCode shootKey = KeyCode.J;
void Start()
{
if (!initialized)
{
Initialize();
}
}
void OnEnable()
{
if (!initialized)
{
Initialize();
}
}
void Initialize()
{
projectilePoolList.Clear(); //clear list in case it's not empty
for (var i = 0; i < numberOfProjectilesToPool; i++)
{
GameObject obj = Instantiate(projectilePrefab, transform.position, Quaternion.identity);
Projectile p = obj.GetComponent<Projectile>();
projectilePoolList.Add(p);
p.transform.position = projectileStartingPos.position;
// p.projectileController = this;
p.gameObject.SetActive(false);
}
initialized = true;
}
void Update()
{
if (Input.GetKey(shootKey))
{
Shoot(projectileStartingPos.position,
projectileStartingPos.TransformPoint(Vector3.forward * autoShootDistance));
}
}
void FixedUpdate()
{
coolDownWait = shootTimer > shootingRate ? false : true;
shootTimer += Time.fixedDeltaTime;
if (autoShootEnabled)
{
Shoot(projectileStartingPos.position,
projectileStartingPos.TransformPoint(Vector3.forward * autoShootDistance));
Debug.DrawRay(projectileStartingPos.TransformPoint(Vector3.forward * autoShootDistance), Vector3.up);
}
}
public void Shoot(Vector3 startPos, Vector3 targetPos)
{
if (coolDownWait)
{
return;
}
shootTimer = 0; //reset timer
//shoot first available projectile in the pool
foreach (var item in projectilePoolList)
{
if (!item.gameObject.activeInHierarchy)
{
LaunchProjectile(item.rb, startPos, targetPos); //shoot
break;
}
}
}
public void Shoot()
{
if (coolDownWait)
{
return;
}
shootTimer = 0; //reset timer
//shoot first available projectile in the pool
foreach (var item in projectilePoolList)
{
if (!item.gameObject.activeInHierarchy)
{
LaunchProjectile(item.rb, projectileStartingPos.position, projectileStartingPos.TransformPoint(Vector3.forward * autoShootDistance));
break;
}
}
}
public void LaunchProjectile(Rigidbody rb, Vector3 startPos, Vector3 targetPos)
{
rb.transform.position = startPos;
// rb.transform.rotation = Quaternion.identity;
rb.transform.rotation = transform.rotation;
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
rb.gameObject.SetActive(true);
Vector3 p = targetPos;
float gravity = Physics.gravity.magnitude;
// Selected angle in radians
float angle = projectileLaunchAngle * Mathf.Deg2Rad;
// Positions of this object and the target on the same plane
Vector3 planarTarget = new Vector3(p.x, 0, p.z);
Vector3 planarPostion = new Vector3(startPos.x, 0, startPos.z);
// Planar distance between objects
float distance = Vector3.Distance(planarTarget, planarPostion);
// Distance along the y axis between objects
float yOffset = startPos.y - p.y;
float initialVelocity = (1 / Mathf.Cos(angle)) *
Mathf.Sqrt((0.5f * gravity * Mathf.Pow(distance, 2)) /
(distance * Mathf.Tan(angle) + yOffset));
Vector3 velocity = new Vector3(0, initialVelocity * Mathf.Sin(angle), initialVelocity * Mathf.Cos(angle));
// Rotate our velocity to match the direction between the two objects
float angleBetweenObjects =
Vector3.Angle(Vector3.forward, planarTarget - planarPostion) * (p.x > startPos.x ? 1 : -1);
Vector3 finalVelocity = Quaternion.AngleAxis(angleBetweenObjects, Vector3.up) * velocity;
if (!float.IsNaN(finalVelocity.x)) //NaN checked
{
rb.velocity = finalVelocity;
}
}
}