Reputation: 81
I've been working with the ML-Agents library and trying to create a border around a randomly spawning target object. I created it, modified the script to teleport it to the same position as the target, but it often spawns in the same position as my ragdoll object, clipping into it and preventing its movement.
I'm fairly new to Unity, so feel free to post supposedly obvious fixes.
Things I've tried:
My TargetSpawner script:
using UnityEngine;
using Random = UnityEngine.Random;
using Unity.MLAgents;
using UnityEngine.Events;
namespace Unity.MLAgentsExamples
{
/// <summary>
/// Utility class to allow target placement and collision detection with an agent
/// Add this script to the target you want the agent to touch.
/// Callbacks will be triggered any time the target is touched with a collider tagged as 'tagToDetect'
/// </summary>
public class TargetController : MonoBehaviour
{
[Header("Collider Tag To Detect")]
public string tagToDetect = "agent"; //collider tag to detect
[Header("Target Placement")]
public float spawnRadius; //The radius in which a target can be randomly spawned.
public bool respawnIfTouched; //Should the target respawn to a different position when touched
[Header("Target Fell Protection")]
public bool respawnIfFallsOffPlatform = true; //If the target falls off the platform, reset the position.
public float fallDistance = 5; //distance below the starting height that will trigger a respawn
private Vector3 m_startingPos; //the starting position of the target
[System.Serializable]
public class TriggerEvent : UnityEvent<Collider>
{
}
[Header("Trigger Callbacks")]
public TriggerEvent onTriggerEnterEvent = new TriggerEvent();
public TriggerEvent onTriggerStayEvent = new TriggerEvent();
public TriggerEvent onTriggerExitEvent = new TriggerEvent();
[System.Serializable]
public class CollisionEvent : UnityEvent<Collision>
{
}
[Header("Collision Callbacks")]
public CollisionEvent onCollisionEnterEvent = new CollisionEvent();
public CollisionEvent onCollisionStayEvent = new CollisionEvent();
public CollisionEvent onCollisionExitEvent = new CollisionEvent();
public GameObject boundary;
public GameObject ragdoll;
// Start is called before the first frame update
void OnEnable()
{
m_startingPos = transform.position;
if (respawnIfTouched)
{
MoveTargetToRandomPosition();
}
}
void Update()
{
if (respawnIfFallsOffPlatform)
{
if (transform.position.y < m_startingPos.y - fallDistance)
{
Debug.Log($"{transform.name} Fell Off Platform");
MoveTargetToRandomPosition();
}
}
}
/// <summary>
/// Moves target to a random position within specified radius.
/// </summary>
public void MoveTargetToRandomPosition()
{
var newTargetPos = m_startingPos + (Random.insideUnitSphere * spawnRadius);
float dis = Vector3.Distance(newTargetPos, ragdoll.transform.position);
while (dis < 10){
newTargetPos = m_startingPos + (Random.insideUnitSphere * spawnRadius);
dis = Vector3.Distance(newTargetPos, ragdoll.transform.position);
}
newTargetPos.y = m_startingPos.y;
transform.position = newTargetPos;
boundary.transform.position = newTargetPos + new Vector3(0f, -0.75f,-2f);
}
private void OnCollisionEnter(Collision col)
{
if (col.transform.CompareTag(tagToDetect))
{
onCollisionEnterEvent.Invoke(col);
if (respawnIfTouched)
{
MoveTargetToRandomPosition();
}
}
}
private void OnCollisionStay(Collision col)
{
if (col.transform.CompareTag(tagToDetect))
{
onCollisionStayEvent.Invoke(col);
}
}
private void OnCollisionExit(Collision col)
{
if (col.transform.CompareTag(tagToDetect))
{
onCollisionExitEvent.Invoke(col);
}
}
private void OnTriggerEnter(Collider col)
{
if (col.CompareTag(tagToDetect))
{
onTriggerEnterEvent.Invoke(col);
}
}
private void OnTriggerStay(Collider col)
{
if (col.CompareTag(tagToDetect))
{
onTriggerStayEvent.Invoke(col);
}
}
private void OnTriggerExit(Collider col)
{
if (col.CompareTag(tagToDetect))
{
onTriggerExitEvent.Invoke(col);
}
}
}
}
Any help would be greatly appreciated.
Thanks in advance
Cheers!
Upvotes: -1
Views: 66
Reputation: 66
If I understood you correctly, your entire problem is that your border doesn't spawn in the right location. 'clipping it' as in spawning halfway through it? If so, your entire problem is with your teleporting mechanism
boundary.transform.position = newTargetPos + new Vector3(0f, -0.75f,-2f);
that to me seems the issue, try experimenting with teleporting your boundary regardless of the target object. Doing that should give you an indication as to why it doesn't teleport to exactly where it should. Perhaps you have a non-uniform scale somewhere which could theoretically create an issue.
Also, depending on the extent of the game you're trying to make, you could make a not-so-clean but working solution. You could make the target the boundary's parent, and make the boundary just move around with the target while surrounding it, and once you're satisfied with their position, unparent them. Just might work(;
alternatively, if I misunderstood you and your main problem is the collision detection issue, I would again suggest simplifying the problem. create a cube and a sphere and make sure you have no problem with detecting collisions and teleporting them at impact. you said you're fairly new to unity so perhaps going back to the very basics and making sure you have them all figured out could be key to solving your problem.
Upvotes: 0